patchwarden 0.6.0 → 0.6.4
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/PatchWarden-Control-Tray.cmd +11 -0
- package/PatchWarden-Control.cmd +6 -0
- package/PatchWarden-Desktop.cmd +5 -0
- package/PatchWarden.cmd +1 -1
- package/README.en.md +106 -18
- package/README.md +30 -19
- package/Restart-PatchWarden-Control.cmd +6 -0
- package/Stop-PatchWarden.cmd +11 -0
- package/dist/controlCenter.d.ts +14 -0
- package/dist/controlCenter.js +2002 -0
- package/dist/doctor.js +4 -4
- package/dist/logging.d.ts +52 -0
- package/dist/logging.js +123 -0
- package/dist/runner/changeCapture.d.ts +41 -0
- package/dist/runner/changeCapture.js +171 -1
- package/dist/runner/runTask.js +204 -24
- package/dist/smoke-test.js +8 -8
- package/dist/test/unit/android-doctor.test.d.ts +1 -0
- package/dist/test/unit/android-doctor.test.js +118 -0
- package/dist/test/unit/chinese-path.test.d.ts +1 -0
- package/dist/test/unit/chinese-path.test.js +91 -0
- package/dist/test/unit/command-guard.test.d.ts +1 -0
- package/dist/test/unit/command-guard.test.js +160 -0
- package/dist/test/unit/direct-guards.test.d.ts +1 -0
- package/dist/test/unit/direct-guards.test.js +213 -0
- package/dist/test/unit/logging.test.d.ts +1 -0
- package/dist/test/unit/logging.test.js +275 -0
- package/dist/test/unit/path-guard.test.d.ts +1 -0
- package/dist/test/unit/path-guard.test.js +109 -0
- package/dist/test/unit/safe-status.test.d.ts +1 -0
- package/dist/test/unit/safe-status.test.js +165 -0
- package/dist/test/unit/sensitive-guard.test.d.ts +1 -0
- package/dist/test/unit/sensitive-guard.test.js +104 -0
- package/dist/test/unit/sync-file.test.d.ts +1 -0
- package/dist/test/unit/sync-file.test.js +154 -0
- package/dist/test/unit/watcher-status.test.d.ts +1 -0
- package/dist/test/unit/watcher-status.test.js +169 -0
- package/dist/tools/androidDoctor.d.ts +38 -0
- package/dist/tools/androidDoctor.js +391 -0
- package/dist/tools/auditTask.js +11 -5
- package/dist/tools/getTaskSummary.d.ts +3 -0
- package/dist/tools/getTaskSummary.js +15 -1
- package/dist/tools/healthCheck.d.ts +5 -0
- package/dist/tools/healthCheck.js +21 -0
- package/dist/tools/registry.js +53 -0
- package/dist/tools/safeStatus.d.ts +19 -0
- package/dist/tools/safeStatus.js +72 -0
- package/dist/tools/syncFile.d.ts +18 -0
- package/dist/tools/syncFile.js +65 -0
- package/dist/tools/taskOutputs.d.ts +2 -2
- package/dist/tools/toolCatalog.d.ts +2 -2
- package/dist/tools/toolCatalog.js +2 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/watcherStatus.d.ts +1 -0
- package/dist/watcherStatus.js +96 -4
- package/docs/control-center/README.md +33 -0
- package/docs/control-center/control-center-daily-driver.md +211 -0
- package/docs/control-center/control-center-mvp.md +205 -0
- package/docs/control-center/control-center-phase2.md +159 -0
- package/docs/demo.md +3 -0
- package/docs/performance-notes.md +55 -0
- package/docs/release-v0.6.1.md +75 -0
- package/docs/release-v0.6.4.md +45 -0
- package/examples/openai-tunnel/README.md +5 -5
- package/examples/openai-tunnel/tunnel-client.example.yaml +3 -3
- package/package.json +23 -14
- package/scripts/README.md +47 -0
- package/scripts/{brand-check.js → checks/brand-check.js} +2 -2
- package/scripts/checks/control-center-smoke.js +1098 -0
- package/scripts/{control-smoke.js → checks/control-smoke.js} +17 -3
- package/scripts/{doctor-smoke.js → checks/doctor-smoke.js} +1 -1
- package/scripts/{http-mcp-smoke.js → checks/http-mcp-smoke.js} +12 -4
- package/scripts/{lifecycle-smoke.js → checks/lifecycle-smoke.js} +347 -13
- package/scripts/{mcp-manifest-check.js → checks/mcp-manifest-check.js} +32 -9
- package/scripts/{mcp-smoke.js → checks/mcp-smoke.js} +14 -9
- package/scripts/{package-manifest-check.js → checks/package-manifest-check.js} +2 -1
- package/scripts/{tunnel-supervisor-smoke.js → checks/tunnel-supervisor-smoke.js} +2 -2
- package/scripts/checks/unit-tests.js +36 -0
- package/scripts/{watcher-supervisor-smoke.js → checks/watcher-supervisor-smoke.js} +11 -5
- package/scripts/control/control-center-tray.ps1 +281 -0
- package/scripts/{get-patchwarden-health.ps1 → control/get-patchwarden-health.ps1} +3 -3
- package/scripts/{manage-patchwarden.ps1 → control/manage-patchwarden.ps1} +30 -4
- package/scripts/control/restart-control-center.ps1 +173 -0
- package/scripts/{restart-patchwarden.ps1 → control/restart-patchwarden.ps1} +1 -1
- package/scripts/control/start-control-center.ps1 +263 -0
- package/scripts/{start-patchwarden-tunnel.ps1 → control/start-patchwarden-tunnel.ps1} +48 -6
- package/scripts/control/stop-patchwarden.ps1 +114 -0
- package/scripts/launchers/Check-PatchWarden-Health.cmd +1 -1
- package/scripts/launchers/Reset-PatchWarden-Tunnel-Key.cmd +1 -1
- package/scripts/launchers/Restart-PatchWarden.cmd +1 -1
- package/scripts/launchers/Start-PatchWarden-Direct-Tunnel.cmd +1 -1
- package/scripts/launchers/Start-PatchWarden-Tunnel.cmd +1 -1
- package/scripts/{patchwarden-mcp-direct.cmd → mcp/patchwarden-mcp-direct.cmd} +1 -1
- package/scripts/{patchwarden-mcp-stdio.cmd → mcp/patchwarden-mcp-stdio.cmd} +1 -1
- package/scripts/release/pack-clean.js +305 -0
- package/src/controlCenter.ts +2152 -0
- package/src/doctor.ts +5 -5
- package/src/logging.ts +152 -0
- package/src/runner/changeCapture.ts +212 -1
- package/src/runner/runTask.ts +220 -22
- package/src/smoke-test.ts +5 -5
- package/src/test/unit/android-doctor.test.ts +158 -0
- package/src/test/unit/chinese-path.test.ts +106 -0
- package/src/test/unit/command-guard.test.ts +221 -0
- package/src/test/unit/direct-guards.test.ts +297 -0
- package/src/test/unit/logging.test.ts +325 -0
- package/src/test/unit/path-guard.test.ts +150 -0
- package/src/test/unit/safe-status.test.ts +187 -0
- package/src/test/unit/sensitive-guard.test.ts +124 -0
- package/src/test/unit/sync-file.test.ts +231 -0
- package/src/test/unit/watcher-status.test.ts +190 -0
- package/src/tools/androidDoctor.ts +424 -0
- package/src/tools/auditTask.ts +11 -5
- package/src/tools/getTaskSummary.ts +22 -1
- package/src/tools/healthCheck.ts +22 -0
- package/src/tools/registry.ts +63 -0
- package/src/tools/safeStatus.ts +96 -0
- package/src/tools/syncFile.ts +122 -0
- package/src/tools/toolCatalog.ts +2 -0
- package/src/version.ts +2 -2
- package/src/watcherStatus.ts +101 -4
- package/ui/colors_and_type.css +141 -0
- package/ui/pages/audit.html +743 -0
- package/ui/pages/dashboard.html +1154 -0
- package/ui/pages/direct-sessions.html +652 -0
- package/ui/pages/logs.html +502 -0
- package/ui/pages/task-detail.html +1229 -0
- package/ui/pages/tasks.html +702 -0
- package/ui/pages/workspace.html +947 -0
- package/ui/partials/project-shell.html +362 -0
- package/ui/vendor/lucide.js +12 -0
- package/ui/vendor/tailwindcss-browser.js +947 -0
- package/scripts/pack-clean.js +0 -141
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
cpSync,
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
readdirSync,
|
|
8
|
+
rmSync,
|
|
9
|
+
statSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
} from "node:fs";
|
|
12
|
+
import { execFileSync } from "node:child_process";
|
|
13
|
+
import { deflateRawSync } from "node:zlib";
|
|
14
|
+
import { join, relative, resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
const scriptDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
|
|
18
|
+
const root = resolve(scriptDir, "..", "..");
|
|
19
|
+
const releaseDir = resolve(root, "release");
|
|
20
|
+
const archivePath = resolve(root, "patchwarden-release.tar.gz");
|
|
21
|
+
|
|
22
|
+
// Read version from package.json for zip naming
|
|
23
|
+
const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf-8"));
|
|
24
|
+
const zipArchivePath = resolve(root, `PatchWarden-v${pkg.version}.zip`);
|
|
25
|
+
|
|
26
|
+
const include = [
|
|
27
|
+
"dist",
|
|
28
|
+
"docs",
|
|
29
|
+
"examples",
|
|
30
|
+
"scripts",
|
|
31
|
+
"src",
|
|
32
|
+
"ui",
|
|
33
|
+
"PatchWarden.cmd",
|
|
34
|
+
"PatchWarden-Control.cmd",
|
|
35
|
+
"PatchWarden-Control-Tray.cmd",
|
|
36
|
+
"PatchWarden-Desktop.cmd",
|
|
37
|
+
"Restart-PatchWarden-Control.cmd",
|
|
38
|
+
"Stop-PatchWarden.cmd",
|
|
39
|
+
".gitignore",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"README.md",
|
|
42
|
+
"package-lock.json",
|
|
43
|
+
"package.json",
|
|
44
|
+
"tsconfig.json",
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const forbidden = [
|
|
48
|
+
/(^|[\\/])node_modules([\\/]|$)/,
|
|
49
|
+
/(^|[\\/])\.patchwarden([\\/]|$)/,
|
|
50
|
+
/(^|[\\/])\.safe-bifrost([\\/]|$)/,
|
|
51
|
+
/(^|[\\/])\.local([\\/]|$)/,
|
|
52
|
+
/(^|[\\/])\.tmp([\\/]|$)/,
|
|
53
|
+
/(^|[\\/])patchwarden\.config\.json$/,
|
|
54
|
+
/(^|[\\/])safe-bifrost\.config\.json$/,
|
|
55
|
+
/\.local\.(cmd|ps1)$/i,
|
|
56
|
+
/\.dpapi$/i,
|
|
57
|
+
/(^|[\\/])\.env$/,
|
|
58
|
+
/\.log$/,
|
|
59
|
+
/^docs[\\/]optimization-proposal\.md$/i,
|
|
60
|
+
/(^|[\\/])kill-patchwarden\.(cmd|ps1)$/i,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
// ── Minimal zip writer helpers (POSIX paths, DEFLATE via zlib) ────
|
|
64
|
+
// Defined before main execution so const CRC_TABLE is initialized.
|
|
65
|
+
|
|
66
|
+
const CRC_TABLE = new Uint32Array(256);
|
|
67
|
+
for (let i = 0; i < 256; i++) {
|
|
68
|
+
let c = i;
|
|
69
|
+
for (let j = 0; j < 8; j++) {
|
|
70
|
+
c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1);
|
|
71
|
+
}
|
|
72
|
+
CRC_TABLE[i] = c;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function crc32(buf) {
|
|
76
|
+
let c = 0xFFFFFFFF;
|
|
77
|
+
for (let i = 0; i < buf.length; i++) {
|
|
78
|
+
c = CRC_TABLE[(c ^ buf[i]) & 0xFF] ^ (c >>> 8);
|
|
79
|
+
}
|
|
80
|
+
return (c ^ 0xFFFFFFFF) >>> 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function dosDateTime(date) {
|
|
84
|
+
const dosTime = (date.getHours() << 11) | (date.getMinutes() << 5) | (date.getSeconds() >> 1);
|
|
85
|
+
const dosDate = (((date.getFullYear() - 1980) & 0x7F) << 9) | ((date.getMonth() + 1) << 5) | date.getDate();
|
|
86
|
+
return { dosTime, dosDate };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function createZip(files, outputPath) {
|
|
90
|
+
const localParts = [];
|
|
91
|
+
const centralParts = [];
|
|
92
|
+
let offset = 0;
|
|
93
|
+
const now = new Date();
|
|
94
|
+
const { dosTime, dosDate } = dosDateTime(now);
|
|
95
|
+
|
|
96
|
+
for (const file of files) {
|
|
97
|
+
const posixPath = file.path.replace(/\\/g, "/");
|
|
98
|
+
const nameBuf = Buffer.from(posixPath, "utf-8");
|
|
99
|
+
const content = file.content;
|
|
100
|
+
const compressed = deflateRawSync(content);
|
|
101
|
+
const useDeflate = compressed.length < content.length;
|
|
102
|
+
const method = useDeflate ? 8 : 0;
|
|
103
|
+
const data = useDeflate ? compressed : content;
|
|
104
|
+
const crc = crc32(content);
|
|
105
|
+
|
|
106
|
+
const lh = Buffer.alloc(30);
|
|
107
|
+
lh.writeUInt32LE(0x04034b50, 0);
|
|
108
|
+
lh.writeUInt16LE(20, 4);
|
|
109
|
+
lh.writeUInt16LE(0, 6);
|
|
110
|
+
lh.writeUInt16LE(method, 8);
|
|
111
|
+
lh.writeUInt16LE(dosTime, 10);
|
|
112
|
+
lh.writeUInt16LE(dosDate, 12);
|
|
113
|
+
lh.writeUInt32LE(crc, 14);
|
|
114
|
+
lh.writeUInt32LE(data.length, 18);
|
|
115
|
+
lh.writeUInt32LE(content.length, 22);
|
|
116
|
+
lh.writeUInt16LE(nameBuf.length, 26);
|
|
117
|
+
lh.writeUInt16LE(0, 28);
|
|
118
|
+
|
|
119
|
+
const localHeaderOffset = offset;
|
|
120
|
+
localParts.push(Buffer.concat([lh, nameBuf, data]));
|
|
121
|
+
offset += lh.length + nameBuf.length + data.length;
|
|
122
|
+
|
|
123
|
+
const cd = Buffer.alloc(46);
|
|
124
|
+
cd.writeUInt32LE(0x02014b50, 0);
|
|
125
|
+
cd.writeUInt16LE(20, 4);
|
|
126
|
+
cd.writeUInt16LE(20, 6);
|
|
127
|
+
cd.writeUInt16LE(0, 8);
|
|
128
|
+
cd.writeUInt16LE(method, 10);
|
|
129
|
+
cd.writeUInt16LE(dosTime, 12);
|
|
130
|
+
cd.writeUInt16LE(dosDate, 14);
|
|
131
|
+
cd.writeUInt32LE(crc, 16);
|
|
132
|
+
cd.writeUInt32LE(data.length, 20);
|
|
133
|
+
cd.writeUInt32LE(content.length, 24);
|
|
134
|
+
cd.writeUInt16LE(nameBuf.length, 28);
|
|
135
|
+
cd.writeUInt16LE(0, 30);
|
|
136
|
+
cd.writeUInt16LE(0, 32);
|
|
137
|
+
cd.writeUInt16LE(0, 34);
|
|
138
|
+
cd.writeUInt16LE(0, 36);
|
|
139
|
+
cd.writeUInt32LE(0, 38);
|
|
140
|
+
cd.writeUInt32LE(localHeaderOffset, 42);
|
|
141
|
+
centralParts.push(Buffer.concat([cd, nameBuf]));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const centralDir = Buffer.concat(centralParts);
|
|
145
|
+
const centralDirOffset = offset;
|
|
146
|
+
|
|
147
|
+
const eocd = Buffer.alloc(22);
|
|
148
|
+
eocd.writeUInt32LE(0x06054b50, 0);
|
|
149
|
+
eocd.writeUInt16LE(0, 4);
|
|
150
|
+
eocd.writeUInt16LE(0, 6);
|
|
151
|
+
eocd.writeUInt16LE(files.length, 8);
|
|
152
|
+
eocd.writeUInt16LE(files.length, 10);
|
|
153
|
+
eocd.writeUInt32LE(centralDir.length, 12);
|
|
154
|
+
eocd.writeUInt32LE(centralDirOffset, 16);
|
|
155
|
+
eocd.writeUInt16LE(0, 20);
|
|
156
|
+
|
|
157
|
+
writeFileSync(outputPath, Buffer.concat([...localParts, centralDir, eocd]));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function readZipEntryNames(zipPath) {
|
|
161
|
+
const buf = readFileSync(zipPath);
|
|
162
|
+
const names = [];
|
|
163
|
+
for (let i = 0; i < buf.length - 4; i++) {
|
|
164
|
+
if (buf.readUInt32LE(i) === 0x02014b50) {
|
|
165
|
+
const nameLen = buf.readUInt16LE(i + 28);
|
|
166
|
+
const extraLen = buf.readUInt16LE(i + 30);
|
|
167
|
+
const commentLen = buf.readUInt16LE(i + 32);
|
|
168
|
+
const name = buf.toString("utf-8", i + 46, i + 46 + nameLen);
|
|
169
|
+
names.push(name);
|
|
170
|
+
i += 45 + nameLen + extraLen + commentLen;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return names;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log("[pack-clean] Preparing clean release directory...");
|
|
177
|
+
rmSync(releaseDir, { recursive: true, force: true });
|
|
178
|
+
rmSync(archivePath, { force: true });
|
|
179
|
+
mkdirSync(releaseDir, { recursive: true });
|
|
180
|
+
|
|
181
|
+
for (const item of include) {
|
|
182
|
+
const source = resolve(root, item);
|
|
183
|
+
const target = resolve(releaseDir, item);
|
|
184
|
+
if (!existsSync(source)) {
|
|
185
|
+
console.log(` skip missing: ${item}`);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
cpSync(source, target, {
|
|
189
|
+
recursive: true,
|
|
190
|
+
filter(sourcePath) {
|
|
191
|
+
const rel = toPosix(relative(root, sourcePath));
|
|
192
|
+
return !isForbidden(rel);
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
console.log(` copied: ${item}`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const releaseFiles = listFiles(releaseDir);
|
|
199
|
+
const badReleaseEntries = releaseFiles.filter((file) =>
|
|
200
|
+
isForbidden(toPosix(relative(releaseDir, file)))
|
|
201
|
+
);
|
|
202
|
+
if (badReleaseEntries.length > 0) {
|
|
203
|
+
console.error("[pack-clean] Forbidden files in release directory:");
|
|
204
|
+
for (const file of badReleaseEntries) {
|
|
205
|
+
console.error(` ${relative(releaseDir, file)}`);
|
|
206
|
+
}
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.log("[pack-clean] Creating tar.gz archive...");
|
|
211
|
+
|
|
212
|
+
// Convert Windows paths to WSL/Linux paths when tar is a Unix binary
|
|
213
|
+
function toTarPath(p) {
|
|
214
|
+
if (process.platform === "win32") {
|
|
215
|
+
return p;
|
|
216
|
+
}
|
|
217
|
+
return p.replace(/^([A-Za-z]):/, (_, d) => `/${d.toLowerCase()}`).replace(/\\/g, "/");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const tarArchivePath = toTarPath(archivePath);
|
|
221
|
+
const tarReleaseDir = toTarPath(releaseDir);
|
|
222
|
+
|
|
223
|
+
execFileSync("tar", ["-czf", tarArchivePath, "-C", tarReleaseDir, "."], {
|
|
224
|
+
stdio: "inherit",
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const archiveEntries = execFileSync("tar", ["-tzf", tarArchivePath], {
|
|
228
|
+
encoding: "utf-8",
|
|
229
|
+
})
|
|
230
|
+
.split(/\r?\n/)
|
|
231
|
+
.filter(Boolean)
|
|
232
|
+
.map((entry) => toPosix(entry.replace(/^\.\//, "")));
|
|
233
|
+
|
|
234
|
+
const badArchiveEntries = archiveEntries.filter(isForbidden);
|
|
235
|
+
if (badArchiveEntries.length > 0) {
|
|
236
|
+
console.error("[pack-clean] Forbidden files in archive:");
|
|
237
|
+
for (const entry of badArchiveEntries) {
|
|
238
|
+
console.error(` ${entry}`);
|
|
239
|
+
}
|
|
240
|
+
rmSync(archivePath, { force: true });
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const sizeKb = (statSync(archivePath).size / 1024).toFixed(1);
|
|
245
|
+
console.log(`[pack-clean] Release directory: ${releaseFiles.length} files`);
|
|
246
|
+
console.log(`[pack-clean] tar.gz Archive: ${archivePath} (${sizeKb} KB)`);
|
|
247
|
+
|
|
248
|
+
// ── Create zip archive with POSIX path separators ─────────────────
|
|
249
|
+
console.log("[pack-clean] Creating zip archive with POSIX paths...");
|
|
250
|
+
rmSync(zipArchivePath, { force: true });
|
|
251
|
+
|
|
252
|
+
const zipFiles = releaseFiles.map((file) => {
|
|
253
|
+
const rel = toPosix(relative(releaseDir, file));
|
|
254
|
+
return { path: rel, content: readFileSync(file) };
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
createZip(zipFiles, zipArchivePath);
|
|
258
|
+
|
|
259
|
+
// Verify zip entries use POSIX separators
|
|
260
|
+
const zipEntryNames = readZipEntryNames(zipArchivePath);
|
|
261
|
+
const badZipEntries = zipEntryNames.filter((name) => name.includes("\\"));
|
|
262
|
+
if (badZipEntries.length > 0) {
|
|
263
|
+
console.error("[pack-clean] Backslash path separators found in zip entries:");
|
|
264
|
+
for (const name of badZipEntries.slice(0, 20)) {
|
|
265
|
+
console.error(` ${name}`);
|
|
266
|
+
}
|
|
267
|
+
rmSync(zipArchivePath, { force: true });
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const badZipForbidden = zipEntryNames.filter(isForbidden);
|
|
272
|
+
if (badZipForbidden.length > 0) {
|
|
273
|
+
console.error("[pack-clean] Forbidden files in zip archive:");
|
|
274
|
+
for (const entry of badZipForbidden) {
|
|
275
|
+
console.error(` ${entry}`);
|
|
276
|
+
}
|
|
277
|
+
rmSync(zipArchivePath, { force: true });
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const zipSizeKb = (statSync(zipArchivePath).size / 1024).toFixed(1);
|
|
282
|
+
console.log(`[pack-clean] zip Archive: ${zipArchivePath} (${zipSizeKb} KB, ${zipEntryNames.length} entries)`);
|
|
283
|
+
console.log("[pack-clean] OK");
|
|
284
|
+
|
|
285
|
+
function listFiles(dir) {
|
|
286
|
+
const entries = [];
|
|
287
|
+
for (const name of readdirSync(dir)) {
|
|
288
|
+
const fullPath = join(dir, name);
|
|
289
|
+
const stat = statSync(fullPath);
|
|
290
|
+
if (stat.isDirectory()) {
|
|
291
|
+
entries.push(...listFiles(fullPath));
|
|
292
|
+
} else {
|
|
293
|
+
entries.push(fullPath);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return entries;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function isForbidden(value) {
|
|
300
|
+
return forbidden.some((pattern) => pattern.test(value));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function toPosix(value) {
|
|
304
|
+
return value.replace(/\\/g, "/");
|
|
305
|
+
}
|