xypriss 9.3.56 → 9.3.58
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 +2 -1
- package/scripts/install-memory-cli.js +183 -0
- package/scripts/install-xems.js +269 -0
- package/scripts/monitor_memory.sh +125 -0
- package/scripts/postinstall-xsys.js +233 -0
- package/scripts/postinstall.js +134 -0
- package/scripts/test-fs-full.ts +96 -0
- package/scripts/verify-xsys-bridge.ts +48 -0
- package/scripts/xems.run.js +113 -0
- package/scripts/xys.run.js +129 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xypriss",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.58",
|
|
4
4
|
"description": "XyPriss is a lightweight, TypeScript-first, open-source Node.js web framework crafted for developers seeking a familiar Express-like API without Express dependencies. It features built-in security middleware, a robust routing system, and performance optimizations to build scalable, secure web applications effortlessly. Join our community and contribute on GitHub!",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Nehonix",
|
|
@@ -125,6 +125,7 @@
|
|
|
125
125
|
"files": [
|
|
126
126
|
"dist/",
|
|
127
127
|
"shared/",
|
|
128
|
+
"scripts/",
|
|
128
129
|
"README.md",
|
|
129
130
|
"LICENSE",
|
|
130
131
|
"CONTRIBUTING.md"
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* XyPriss Memory CLI Installer
|
|
5
|
+
* Downloads platform-specific memory CLI binary during npm install
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import https from "https";
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { execSync, spawn } from "child_process";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
|
|
17
|
+
const CDN_BASE_URL = "https://dll.nehonix.com/dl/mds/xypriss/bin";
|
|
18
|
+
const BIN_DIR = path.join(__dirname, "..", "bin");
|
|
19
|
+
const TIMEOUT = 40000;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get platform-specific binary information
|
|
23
|
+
*/
|
|
24
|
+
function getPlatformBinary() {
|
|
25
|
+
const platform = process.platform;
|
|
26
|
+
const arch = process.arch;
|
|
27
|
+
|
|
28
|
+
let binaryTarget;
|
|
29
|
+
if (platform === "win32") {
|
|
30
|
+
binaryTarget = arch === "arm64" ? "windows-arm64" : "windows-x64";
|
|
31
|
+
} else if (platform === "darwin") {
|
|
32
|
+
binaryTarget = arch === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
33
|
+
} else if (platform === "linux") {
|
|
34
|
+
binaryTarget = arch === "arm64" ? "linux-arm64" : "linux-x64";
|
|
35
|
+
} else {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const binaryName = `memory-cli-${binaryTarget}${platform === "win32" ? ".exe" : ""}`;
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
binaryName,
|
|
43
|
+
url: `${CDN_BASE_URL}/${binaryName}`,
|
|
44
|
+
localPath: path.join(BIN_DIR, binaryName),
|
|
45
|
+
genericPath: path.join(
|
|
46
|
+
BIN_DIR,
|
|
47
|
+
"memory-cli" + (platform === "win32" ? ".exe" : ""),
|
|
48
|
+
),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Download file from URL with Redirect support
|
|
54
|
+
*/
|
|
55
|
+
function downloadFile(url, destination) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const file = fs.createWriteStream(destination);
|
|
58
|
+
const request = https.get(url, { timeout: TIMEOUT }, (response) => {
|
|
59
|
+
if (
|
|
60
|
+
response.statusCode >= 300 &&
|
|
61
|
+
response.statusCode < 400 &&
|
|
62
|
+
response.headers.location
|
|
63
|
+
) {
|
|
64
|
+
file.close();
|
|
65
|
+
fs.unlinkSync(destination);
|
|
66
|
+
return downloadFile(response.headers.location, destination)
|
|
67
|
+
.then(resolve)
|
|
68
|
+
.catch(reject);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (response.statusCode === 200) {
|
|
72
|
+
response.pipe(file);
|
|
73
|
+
file.on("finish", () => {
|
|
74
|
+
file.close();
|
|
75
|
+
resolve();
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
file.close();
|
|
79
|
+
fs.unlinkSync(destination);
|
|
80
|
+
reject(new Error(`HTTP ${response.statusCode}`));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
request.on("error", (error) => {
|
|
85
|
+
file.close();
|
|
86
|
+
if (fs.existsSync(destination)) fs.unlinkSync(destination);
|
|
87
|
+
reject(error);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Verify downloaded binary works
|
|
94
|
+
*/
|
|
95
|
+
function verifyBinary(filePath) {
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
try {
|
|
98
|
+
const child = spawn(filePath, ["--help"], {
|
|
99
|
+
stdio: "pipe",
|
|
100
|
+
timeout: 5000,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
let output = "";
|
|
104
|
+
child.stdout.on("data", (data) => {
|
|
105
|
+
output += data.toString();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
child.on("close", (code) => {
|
|
109
|
+
if (code === 0 && output.includes("XyPriss Memory Info CLI")) {
|
|
110
|
+
resolve(true);
|
|
111
|
+
} else {
|
|
112
|
+
resolve(false);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
child.on("error", () => resolve(false));
|
|
117
|
+
} catch (error) {
|
|
118
|
+
resolve(false);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function installMemoryCLI() {
|
|
124
|
+
if (!fs.existsSync(BIN_DIR)) {
|
|
125
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const info = getPlatformBinary();
|
|
129
|
+
if (!info) return;
|
|
130
|
+
|
|
131
|
+
console.log(`📂 Target directory: ${BIN_DIR}`);
|
|
132
|
+
console.log(`📦 Binary: ${info.binaryName}`);
|
|
133
|
+
|
|
134
|
+
if (fs.existsSync(info.genericPath)) {
|
|
135
|
+
console.log(
|
|
136
|
+
`✨ Memory CLI already present at ${info.genericPath}, skipping.`,
|
|
137
|
+
);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
console.log(`📥 Fetching Memory CLI from:`);
|
|
143
|
+
console.log(` 🔗 URL: ${info.url}`);
|
|
144
|
+
await downloadFile(info.url, info.localPath);
|
|
145
|
+
console.log("✅ Downloaded successfully.");
|
|
146
|
+
|
|
147
|
+
if (process.platform !== "win32") {
|
|
148
|
+
fs.chmodSync(info.localPath, 0o755);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (process.platform === "win32") {
|
|
152
|
+
fs.copyFileSync(info.localPath, info.genericPath);
|
|
153
|
+
} else {
|
|
154
|
+
if (fs.existsSync(info.genericPath))
|
|
155
|
+
fs.unlinkSync(info.genericPath);
|
|
156
|
+
fs.symlinkSync(path.basename(info.localPath), info.genericPath);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const isValid = await verifyBinary(info.localPath);
|
|
160
|
+
if (isValid) {
|
|
161
|
+
console.log(
|
|
162
|
+
`🎉 XyPriss MCLI installed successfully at: ${info.genericPath}`,
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
console.warn(
|
|
166
|
+
"⚠️ MCLI verification failed, it might not work as expected.",
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error("❌ Failed to install Memory CLI:", error.message);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Only run if this is the main module (not being imported)
|
|
175
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
176
|
+
installMemoryCLI().catch((error) => {
|
|
177
|
+
console.error("💥 Installation failed:", error);
|
|
178
|
+
process.exit(0);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export { installMemoryCLI, getPlatformBinary, downloadFile, verifyBinary };
|
|
183
|
+
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* XEMS Installer Script
|
|
5
|
+
* Downloads the XEMS (XyPriss Entry Management System) binary from GitHub Releases.
|
|
6
|
+
* Supports cross-platform: Windows, Linux, and macOS (Intel & Silicon).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
import https from "https";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
|
|
17
|
+
// ─────────────────────────────────────────────
|
|
18
|
+
// ANSI Color Palette
|
|
19
|
+
// ─────────────────────────────────────────────
|
|
20
|
+
const c = {
|
|
21
|
+
reset: "\x1b[0m",
|
|
22
|
+
bold: "\x1b[1m",
|
|
23
|
+
dim: "\x1b[2m",
|
|
24
|
+
|
|
25
|
+
// Foreground
|
|
26
|
+
white: "\x1b[97m",
|
|
27
|
+
gray: "\x1b[90m",
|
|
28
|
+
red: "\x1b[91m",
|
|
29
|
+
green: "\x1b[92m",
|
|
30
|
+
yellow: "\x1b[93m",
|
|
31
|
+
blue: "\x1b[94m",
|
|
32
|
+
magenta: "\x1b[95m",
|
|
33
|
+
cyan: "\x1b[96m",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// ─────────────────────────────────────────────
|
|
37
|
+
// Logger
|
|
38
|
+
// ─────────────────────────────────────────────
|
|
39
|
+
const log = {
|
|
40
|
+
info: (msg) =>
|
|
41
|
+
console.log(
|
|
42
|
+
`${c.cyan}${c.bold} ℹ ${c.reset}${c.white}${msg}${c.reset}`,
|
|
43
|
+
),
|
|
44
|
+
success: (msg) =>
|
|
45
|
+
console.log(
|
|
46
|
+
`${c.green}${c.bold} ✔ ${c.reset}${c.green}${msg}${c.reset}`,
|
|
47
|
+
),
|
|
48
|
+
warn: (msg) =>
|
|
49
|
+
console.log(
|
|
50
|
+
`${c.yellow}${c.bold} ⚠ ${c.reset}${c.yellow}${msg}${c.reset}`,
|
|
51
|
+
),
|
|
52
|
+
error: (msg) =>
|
|
53
|
+
console.log(`${c.red}${c.bold} ✖ ${c.reset}${c.red}${msg}${c.reset}`),
|
|
54
|
+
step: (msg) =>
|
|
55
|
+
console.log(
|
|
56
|
+
`${c.magenta}${c.bold} ▶ ${c.reset}${c.magenta}${msg}${c.reset}`,
|
|
57
|
+
),
|
|
58
|
+
link: (label, url) =>
|
|
59
|
+
console.log(
|
|
60
|
+
`${c.gray} └─ ${c.dim}${label}:${c.reset} ${c.blue}${url}${c.reset}`,
|
|
61
|
+
),
|
|
62
|
+
detail: (msg) => console.log(`${c.gray} ${msg}${c.reset}`),
|
|
63
|
+
divider: () => console.log(`${c.gray} ${"─".repeat(52)}${c.reset}`),
|
|
64
|
+
blank: () => console.log(),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// ─────────────────────────────────────────────
|
|
68
|
+
// Constants
|
|
69
|
+
// ─────────────────────────────────────────────
|
|
70
|
+
const BIN_DIR = path.join(__dirname, "..", "bin");
|
|
71
|
+
const REPO = "Nehonix-Team/XyPriss-XEMS";
|
|
72
|
+
const CDN_BASE_URL = "https://dll.nehonix.com/dl/mds/xems/bin";
|
|
73
|
+
|
|
74
|
+
// ─────────────────────────────────────────────
|
|
75
|
+
// Platform Detection
|
|
76
|
+
// ─────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns platform-specific binary metadata for XEMS.
|
|
80
|
+
* Maps to the files in tools/XEMS/dist/
|
|
81
|
+
*/
|
|
82
|
+
function getPlatformBinary() {
|
|
83
|
+
const platform = process.platform;
|
|
84
|
+
const arch = process.arch;
|
|
85
|
+
|
|
86
|
+
let binaryTarget;
|
|
87
|
+
if (platform === "win32") {
|
|
88
|
+
binaryTarget = arch === "arm64" ? "windows-arm64" : "windows-x64";
|
|
89
|
+
} else if (platform === "darwin") {
|
|
90
|
+
binaryTarget = arch === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
91
|
+
} else if (platform === "linux") {
|
|
92
|
+
binaryTarget = arch === "arm64" ? "linux-arm64" : "linux-x64";
|
|
93
|
+
} else {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const ext = platform === "win32" ? ".exe" : "";
|
|
98
|
+
const binaryName = `xems-${binaryTarget}${ext}`;
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
binaryName,
|
|
102
|
+
platform,
|
|
103
|
+
arch,
|
|
104
|
+
url: `https://github.com/${REPO}/releases/latest/download/${binaryName}`,
|
|
105
|
+
fallbackUrl: `${CDN_BASE_URL}/${binaryName}`,
|
|
106
|
+
localPath: path.join(BIN_DIR, binaryName),
|
|
107
|
+
genericPath: path.join(BIN_DIR, `xems${ext}`),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ─────────────────────────────────────────────
|
|
112
|
+
// Downloader (with redirect support)
|
|
113
|
+
// ─────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
function downloadFile(url, dest) {
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
const file = fs.createWriteStream(dest);
|
|
118
|
+
const request = https.get(
|
|
119
|
+
url,
|
|
120
|
+
{ headers: { "User-Agent": "XyPriss-Installer" } },
|
|
121
|
+
(response) => {
|
|
122
|
+
// Follow redirects
|
|
123
|
+
if (
|
|
124
|
+
response.statusCode >= 300 &&
|
|
125
|
+
response.statusCode < 400 &&
|
|
126
|
+
response.headers.location
|
|
127
|
+
) {
|
|
128
|
+
file.close();
|
|
129
|
+
fs.unlinkSync(dest);
|
|
130
|
+
return downloadFile(response.headers.location, dest)
|
|
131
|
+
.then(resolve)
|
|
132
|
+
.catch(reject);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (response.statusCode !== 200) {
|
|
136
|
+
file.close();
|
|
137
|
+
fs.unlinkSync(dest);
|
|
138
|
+
return reject(
|
|
139
|
+
new Error(
|
|
140
|
+
`Server responded with HTTP ${response.statusCode}`,
|
|
141
|
+
),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Stream progress dots
|
|
146
|
+
let received = 0;
|
|
147
|
+
process.stdout.write(`${c.gray} └─ Downloading `);
|
|
148
|
+
response.on("data", (chunk) => {
|
|
149
|
+
received += chunk.length;
|
|
150
|
+
if (received % (50 * 1024) < chunk.length)
|
|
151
|
+
process.stdout.write(`${c.blue}.${c.reset}`);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
response.pipe(file);
|
|
155
|
+
file.on("finish", () => {
|
|
156
|
+
process.stdout.write(` ${c.green}done${c.reset}\n`);
|
|
157
|
+
file.close();
|
|
158
|
+
resolve();
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
request.on("error", (err) => {
|
|
164
|
+
file.close();
|
|
165
|
+
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
166
|
+
reject(err);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ─────────────────────────────────────────────
|
|
172
|
+
// Main Installer
|
|
173
|
+
// ─────────────────────────────────────────────
|
|
174
|
+
|
|
175
|
+
async function installXems() {
|
|
176
|
+
log.blank();
|
|
177
|
+
log.divider();
|
|
178
|
+
console.log(
|
|
179
|
+
`${c.cyan}${c.bold} XEMS Installer — XyPriss Entry Management System${c.reset}`,
|
|
180
|
+
);
|
|
181
|
+
log.divider();
|
|
182
|
+
log.blank();
|
|
183
|
+
|
|
184
|
+
// Ensure bin directory exists
|
|
185
|
+
if (!fs.existsSync(BIN_DIR)) {
|
|
186
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
187
|
+
log.detail(`Created bin directory: ${BIN_DIR}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const info = getPlatformBinary();
|
|
191
|
+
if (!info) {
|
|
192
|
+
log.error(
|
|
193
|
+
"Unsupported platform/architecture. XEMS cannot be installed.",
|
|
194
|
+
);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
log.info(
|
|
199
|
+
`Platform : ${c.yellow}${info.platform}${c.reset} ${c.gray}(${info.arch})${c.reset}`,
|
|
200
|
+
);
|
|
201
|
+
log.info(`Binary : ${c.yellow}${info.binaryName}${c.reset}`);
|
|
202
|
+
log.info(`Target : ${c.yellow}${BIN_DIR}${c.reset}`);
|
|
203
|
+
log.blank();
|
|
204
|
+
|
|
205
|
+
// Skip if already installed
|
|
206
|
+
if (fs.existsSync(info.genericPath)) {
|
|
207
|
+
log.success(`XEMS is already installed → ${info.genericPath}`);
|
|
208
|
+
log.blank();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Attempt GitHub download, then fallback CDN
|
|
213
|
+
log.step("Downloading XEMS binary…");
|
|
214
|
+
try {
|
|
215
|
+
try {
|
|
216
|
+
log.link("GitHub", info.url);
|
|
217
|
+
await downloadFile(info.url, info.localPath);
|
|
218
|
+
log.success("Downloaded from GitHub.");
|
|
219
|
+
} catch (githubErr) {
|
|
220
|
+
log.warn(`GitHub download failed: ${githubErr.message}`);
|
|
221
|
+
log.step("Retrying with fallback CDN…");
|
|
222
|
+
log.link("CDN", info.fallbackUrl);
|
|
223
|
+
await downloadFile(info.fallbackUrl, info.localPath);
|
|
224
|
+
log.success("Downloaded from fallback CDN.");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Set executable bit on Unix
|
|
228
|
+
if (process.platform !== "win32") {
|
|
229
|
+
fs.chmodSync(info.localPath, 0o755);
|
|
230
|
+
log.detail("Executable permission set (chmod 755).");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Create generic alias (symlink on Unix, copy on Windows)
|
|
234
|
+
if (process.platform === "win32") {
|
|
235
|
+
fs.copyFileSync(info.localPath, info.genericPath);
|
|
236
|
+
log.detail(`Copied binary → ${info.genericPath}`);
|
|
237
|
+
} else {
|
|
238
|
+
if (fs.existsSync(info.genericPath))
|
|
239
|
+
fs.unlinkSync(info.genericPath);
|
|
240
|
+
fs.symlinkSync(path.basename(info.localPath), info.genericPath);
|
|
241
|
+
log.detail(`Symlink created → ${info.genericPath}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
log.blank();
|
|
245
|
+
log.success(
|
|
246
|
+
`XEMS successfully installed at: ${c.bold}${info.genericPath}${c.reset}`,
|
|
247
|
+
);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
log.blank();
|
|
250
|
+
log.error(`XEMS installation failed: ${err.message}`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
log.blank();
|
|
254
|
+
log.divider();
|
|
255
|
+
log.blank();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ─────────────────────────────────────────────
|
|
259
|
+
// Entry Point
|
|
260
|
+
// ─────────────────────────────────────────────
|
|
261
|
+
|
|
262
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
263
|
+
installXems().catch((error) => {
|
|
264
|
+
log.error(`Fatal error: ${error.message}`);
|
|
265
|
+
process.exit(0);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export { installXems };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
readonly BLUE='\033[0;34m'
|
|
6
|
+
readonly GREEN='\033[0;32m'
|
|
7
|
+
readonly YELLOW='\033[1;33m'
|
|
8
|
+
readonly NC='\033[0m'
|
|
9
|
+
|
|
10
|
+
log_section() {
|
|
11
|
+
echo -e "\n${BLUE}========================================${NC}"
|
|
12
|
+
echo -e "${BLUE}$*${NC}"
|
|
13
|
+
echo -e "${BLUE}========================================${NC}"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get_xsys_pid() {
|
|
17
|
+
pgrep -f "xsys server start" | head -n 1 || echo ""
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
bytes_to_mb() {
|
|
21
|
+
echo "scale=2; $1 / 1024" | bc
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
monitor_memory() {
|
|
25
|
+
local xsys_pid
|
|
26
|
+
xsys_pid=$(get_xsys_pid)
|
|
27
|
+
|
|
28
|
+
if [ -z "$xsys_pid" ]; then
|
|
29
|
+
echo "xsys process not found"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
log_section "XyPriss Memory Usage Monitor"
|
|
34
|
+
|
|
35
|
+
echo -e "${GREEN}Parent Process (PID: $xsys_pid)${NC}"
|
|
36
|
+
ps -p "$xsys_pid" -o pid,%mem,rss,vsz,cmd --no-headers | while read -r line; do
|
|
37
|
+
local pid=$(echo "$line" | awk '{print $1}')
|
|
38
|
+
local mem_percent=$(echo "$line" | awk '{print $2}')
|
|
39
|
+
local rss=$(echo "$line" | awk '{print $3}')
|
|
40
|
+
local vsz=$(echo "$line" | awk '{print $4}')
|
|
41
|
+
local cmd=$(echo "$line" | awk '{$1=$2=$3=$4=""; print $0}' | xargs)
|
|
42
|
+
|
|
43
|
+
local rss_mb=$(bytes_to_mb "$rss")
|
|
44
|
+
local vsz_mb=$(bytes_to_mb "$vsz")
|
|
45
|
+
|
|
46
|
+
printf " PID: %-8s | MEM: %6s%% | RSS: %8s MB | VSZ: %8s MB\n" \
|
|
47
|
+
"$pid" "$mem_percent" "$rss_mb" "$vsz_mb"
|
|
48
|
+
printf " CMD: %s\n" "$cmd"
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
echo ""
|
|
52
|
+
echo -e "${GREEN}Worker Processes${NC}"
|
|
53
|
+
|
|
54
|
+
local worker_pids
|
|
55
|
+
worker_pids=$(pgrep -P "$xsys_pid" 2>/dev/null || true)
|
|
56
|
+
|
|
57
|
+
if [ -z "$worker_pids" ]; then
|
|
58
|
+
echo " No worker processes found"
|
|
59
|
+
else
|
|
60
|
+
local worker_count=0
|
|
61
|
+
local total_rss=0
|
|
62
|
+
|
|
63
|
+
printf " %-8s | %-8s | %-12s | %-12s\n" "PID" "MEM %" "RSS (MB)" "VSZ (MB)"
|
|
64
|
+
echo " ----------------------------------------------------------------"
|
|
65
|
+
|
|
66
|
+
ps --ppid "$xsys_pid" -o pid,%mem,rss,vsz --no-headers | while read -r pid mem rss vsz; do
|
|
67
|
+
local rss_mb=$(bytes_to_mb "$rss")
|
|
68
|
+
local vsz_mb=$(bytes_to_mb "$vsz")
|
|
69
|
+
|
|
70
|
+
printf " %-8s | %6s%% | %10s | %10s\n" \
|
|
71
|
+
"$pid" "$mem" "$rss_mb" "$vsz_mb"
|
|
72
|
+
|
|
73
|
+
worker_count=$((worker_count + 1))
|
|
74
|
+
total_rss=$((total_rss + rss))
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
local worker_count=$(echo "$worker_pids" | wc -w)
|
|
78
|
+
local total_rss=$(ps --ppid "$xsys_pid" -o rss --no-headers | awk '{sum+=$1} END {print sum}')
|
|
79
|
+
local total_rss_mb=$(bytes_to_mb "$total_rss")
|
|
80
|
+
|
|
81
|
+
echo " ----------------------------------------------------------------"
|
|
82
|
+
printf " ${YELLOW}Total: %d workers | Total RSS: %s MB${NC}\n" \
|
|
83
|
+
"$worker_count" "$total_rss_mb"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
log_section "System Memory Overview"
|
|
87
|
+
|
|
88
|
+
free -h | grep -E "(total|Mem|Swap)"
|
|
89
|
+
|
|
90
|
+
log_section "Pre-allocated Memory Check"
|
|
91
|
+
|
|
92
|
+
local parent_rss=$(ps -p "$xsys_pid" -o rss --no-headers)
|
|
93
|
+
local parent_rss_mb=$(bytes_to_mb "$parent_rss")
|
|
94
|
+
|
|
95
|
+
echo "Parent process RSS: ${parent_rss_mb} MB"
|
|
96
|
+
|
|
97
|
+
if (( $(echo "$parent_rss_mb > 100" | bc -l) )); then
|
|
98
|
+
echo -e "${GREEN}✓ Parent has significant memory footprint (pre-allocation likely active)${NC}"
|
|
99
|
+
else
|
|
100
|
+
echo -e "${YELLOW}âš Parent has low memory footprint (pre-allocation may not be active)${NC}"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
log_section "Top 10 Memory Consumers (System-wide)"
|
|
104
|
+
|
|
105
|
+
ps aux --sort=-%mem | head -11 | awk 'NR==1 || /xsys/ || NR<=11 {print}' | \
|
|
106
|
+
awk '{printf "%-8s %-8s %6s%% %10s %s\n", $2, $1, $4, $6, $11}'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
continuous_monitor() {
|
|
110
|
+
while true; do
|
|
111
|
+
clear
|
|
112
|
+
monitor_memory
|
|
113
|
+
echo ""
|
|
114
|
+
echo "Press Ctrl+C to stop. Refreshing in 3 seconds..."
|
|
115
|
+
sleep 3
|
|
116
|
+
done
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if [ "${1:-}" = "-c" ] || [ "${1:-}" = "--continuous" ]; then
|
|
120
|
+
continuous_monitor
|
|
121
|
+
else
|
|
122
|
+
monitor_memory
|
|
123
|
+
echo ""
|
|
124
|
+
echo "Tip: Use './monitor_memory.sh -c' for continuous monitoring"
|
|
125
|
+
fi
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* XSYS Installer Script
|
|
5
|
+
* Downloads the XSYS (XyPriss System Core) binary from GitHub Releases.
|
|
6
|
+
* Supports cross-platform: Windows, Linux, and macOS (Intel & Silicon).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import { join, dirname, basename } from "path";
|
|
11
|
+
import { platform, arch } from "os";
|
|
12
|
+
import https from "https";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
|
|
18
|
+
// ─────────────────────────────────────────────
|
|
19
|
+
// ANSI Color Palette
|
|
20
|
+
// ─────────────────────────────────────────────
|
|
21
|
+
const c = {
|
|
22
|
+
reset: "\x1b[0m",
|
|
23
|
+
bold: "\x1b[1m",
|
|
24
|
+
dim: "\x1b[2m",
|
|
25
|
+
white: "\x1b[97m",
|
|
26
|
+
gray: "\x1b[90m",
|
|
27
|
+
red: "\x1b[91m",
|
|
28
|
+
green: "\x1b[92m",
|
|
29
|
+
yellow: "\x1b[93m",
|
|
30
|
+
blue: "\x1b[94m",
|
|
31
|
+
magenta: "\x1b[95m",
|
|
32
|
+
cyan: "\x1b[96m",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// ─────────────────────────────────────────────
|
|
36
|
+
// Logger
|
|
37
|
+
// ─────────────────────────────────────────────
|
|
38
|
+
const log = {
|
|
39
|
+
info: (msg) =>
|
|
40
|
+
console.log(
|
|
41
|
+
`${c.cyan}${c.bold} ℹ ${c.reset}${c.white}${msg}${c.reset}`,
|
|
42
|
+
),
|
|
43
|
+
success: (msg) =>
|
|
44
|
+
console.log(
|
|
45
|
+
`${c.green}${c.bold} ✔ ${c.reset}${c.green}${msg}${c.reset}`,
|
|
46
|
+
),
|
|
47
|
+
warn: (msg) =>
|
|
48
|
+
console.log(
|
|
49
|
+
`${c.yellow}${c.bold} ⚠ ${c.reset}${c.yellow}${msg}${c.reset}`,
|
|
50
|
+
),
|
|
51
|
+
error: (msg) =>
|
|
52
|
+
console.log(`${c.red}${c.bold} ✖ ${c.reset}${c.red}${msg}${c.reset}`),
|
|
53
|
+
step: (msg) =>
|
|
54
|
+
console.log(
|
|
55
|
+
`${c.magenta}${c.bold} ▶ ${c.reset}${c.magenta}${msg}${c.reset}`,
|
|
56
|
+
),
|
|
57
|
+
link: (label, url) =>
|
|
58
|
+
console.log(
|
|
59
|
+
`${c.gray} └─ ${c.dim}${label}:${c.reset} ${c.blue}${url}${c.reset}`,
|
|
60
|
+
),
|
|
61
|
+
detail: (msg) => console.log(`${c.gray} ${msg}${c.reset}`),
|
|
62
|
+
divider: () => console.log(`${c.gray} ${"─".repeat(52)}${c.reset}`),
|
|
63
|
+
blank: () => console.log(),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ─────────────────────────────────────────────
|
|
67
|
+
// Constants
|
|
68
|
+
// ─────────────────────────────────────────────
|
|
69
|
+
const REPO = "Nehonix-Team/XyPriss";
|
|
70
|
+
const BIN_NAME = "xsys";
|
|
71
|
+
const BIN_DIR = join(__dirname, "..", "bin");
|
|
72
|
+
|
|
73
|
+
// ─────────────────────────────────────────────
|
|
74
|
+
// Downloader (with redirect support)
|
|
75
|
+
// ─────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
function downloadFile(url, dest) {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const file = fs.createWriteStream(dest);
|
|
80
|
+
const request = https.get(
|
|
81
|
+
url,
|
|
82
|
+
{ headers: { "User-Agent": "XyPriss-Installer" } },
|
|
83
|
+
(response) => {
|
|
84
|
+
// Follow redirects
|
|
85
|
+
if (
|
|
86
|
+
response.statusCode >= 300 &&
|
|
87
|
+
response.statusCode < 400 &&
|
|
88
|
+
response.headers.location
|
|
89
|
+
) {
|
|
90
|
+
file.close();
|
|
91
|
+
fs.unlinkSync(dest);
|
|
92
|
+
return downloadFile(response.headers.location, dest)
|
|
93
|
+
.then(resolve)
|
|
94
|
+
.catch(reject);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (response.statusCode !== 200) {
|
|
98
|
+
file.close();
|
|
99
|
+
fs.unlinkSync(dest);
|
|
100
|
+
return reject(
|
|
101
|
+
new Error(
|
|
102
|
+
`Server responded with HTTP ${response.statusCode}`,
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Stream progress dots
|
|
108
|
+
let received = 0;
|
|
109
|
+
process.stdout.write(`${c.gray} └─ Downloading `);
|
|
110
|
+
response.on("data", (chunk) => {
|
|
111
|
+
received += chunk.length;
|
|
112
|
+
if (received % (50 * 1024) < chunk.length)
|
|
113
|
+
process.stdout.write(`${c.blue}.${c.reset}`);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
response.pipe(file);
|
|
117
|
+
file.on("finish", () => {
|
|
118
|
+
process.stdout.write(` ${c.green}done${c.reset}\n`);
|
|
119
|
+
file.close();
|
|
120
|
+
resolve();
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
request.on("error", (err) => {
|
|
126
|
+
file.close();
|
|
127
|
+
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
128
|
+
reject(err);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ─────────────────────────────────────────────
|
|
134
|
+
// Main Installer
|
|
135
|
+
// ─────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
async function installXsys() {
|
|
138
|
+
log.blank();
|
|
139
|
+
log.divider();
|
|
140
|
+
console.log(
|
|
141
|
+
`${c.cyan}${c.bold} XSYS Installer — XyPriss System Core${c.reset}`,
|
|
142
|
+
);
|
|
143
|
+
log.divider();
|
|
144
|
+
log.blank();
|
|
145
|
+
|
|
146
|
+
// Ensure bin directory exists
|
|
147
|
+
if (!fs.existsSync(BIN_DIR)) {
|
|
148
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
149
|
+
log.detail(`Created bin directory: ${BIN_DIR}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const osName = platform();
|
|
153
|
+
const archName = arch();
|
|
154
|
+
|
|
155
|
+
// Map to binary target name
|
|
156
|
+
let binaryTarget = "";
|
|
157
|
+
if (osName === "linux") {
|
|
158
|
+
binaryTarget = archName === "arm64" ? "linux-arm64" : "linux-amd64";
|
|
159
|
+
} else if (osName === "darwin") {
|
|
160
|
+
binaryTarget = archName === "arm64" ? "darwin-arm64" : "darwin-amd64";
|
|
161
|
+
} else if (osName === "win32") {
|
|
162
|
+
binaryTarget = archName === "arm64" ? "windows-arm64" : "windows-amd64";
|
|
163
|
+
} else {
|
|
164
|
+
log.error(`Unsupported platform: ${osName}`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const ext = osName === "win32" ? ".exe" : "";
|
|
169
|
+
const binaryFileName = `${BIN_NAME}-${binaryTarget}${ext}`;
|
|
170
|
+
const url = `https://github.com/${REPO}/releases/latest/download/${binaryFileName}`;
|
|
171
|
+
const localPath = join(BIN_DIR, binaryFileName);
|
|
172
|
+
const genericPath = join(BIN_DIR, `${BIN_NAME}${ext}`);
|
|
173
|
+
|
|
174
|
+
log.info(
|
|
175
|
+
`Platform : ${c.yellow}${osName}${c.reset} ${c.gray}(${archName})${c.reset}`,
|
|
176
|
+
);
|
|
177
|
+
log.info(`Binary : ${c.yellow}${binaryFileName}${c.reset}`);
|
|
178
|
+
log.info(`Target : ${c.yellow}${BIN_DIR}${c.reset}`);
|
|
179
|
+
log.blank();
|
|
180
|
+
|
|
181
|
+
// Skip if already installed
|
|
182
|
+
if (fs.existsSync(genericPath)) {
|
|
183
|
+
log.success(`XSYS is already installed → ${genericPath}`);
|
|
184
|
+
log.blank();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Download
|
|
189
|
+
log.step("Downloading XSYS binary…");
|
|
190
|
+
log.link("GitHub", url);
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
await downloadFile(url, localPath);
|
|
194
|
+
|
|
195
|
+
// Set executable bit on Unix
|
|
196
|
+
if (osName !== "win32") {
|
|
197
|
+
fs.chmodSync(localPath, 0o755);
|
|
198
|
+
log.detail("Executable permission set (chmod 755).");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Create generic alias (symlink on Unix, copy on Windows)
|
|
202
|
+
if (osName === "win32") {
|
|
203
|
+
fs.copyFileSync(localPath, genericPath);
|
|
204
|
+
log.detail(`Copied binary → ${genericPath}`);
|
|
205
|
+
} else {
|
|
206
|
+
if (fs.existsSync(genericPath)) fs.unlinkSync(genericPath);
|
|
207
|
+
fs.symlinkSync(basename(localPath), genericPath);
|
|
208
|
+
log.detail(`Symlink created → ${genericPath}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
log.blank();
|
|
212
|
+
log.success(
|
|
213
|
+
`XSYS successfully installed at: ${c.bold}${genericPath}${c.reset}`,
|
|
214
|
+
);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
log.blank();
|
|
217
|
+
log.error(`XSYS installation failed: ${err.message}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
log.blank();
|
|
221
|
+
log.divider();
|
|
222
|
+
log.blank();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ─────────────────────────────────────────────
|
|
226
|
+
// Entry Point - EP
|
|
227
|
+
// ─────────────────────────────────────────────
|
|
228
|
+
|
|
229
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
230
|
+
installXsys().catch(() => process.exit(0));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export { installXsys };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* XyPriss Post-Install Script
|
|
5
|
+
* Runs after `npm install` to set up all platform-specific binaries.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { installMemoryCLI } from "./install-memory-cli.js";
|
|
9
|
+
import { installXems } from "./install-xems.js";
|
|
10
|
+
import { installXsys } from "./postinstall-xsys.js";
|
|
11
|
+
|
|
12
|
+
// ─────────────────────────────────────────────
|
|
13
|
+
// ANSI Color Palette
|
|
14
|
+
// ─────────────────────────────────────────────
|
|
15
|
+
const c = {
|
|
16
|
+
reset: "\x1b[0m",
|
|
17
|
+
bold: "\x1b[1m",
|
|
18
|
+
dim: "\x1b[2m",
|
|
19
|
+
white: "\x1b[97m",
|
|
20
|
+
gray: "\x1b[90m",
|
|
21
|
+
red: "\x1b[91m",
|
|
22
|
+
green: "\x1b[92m",
|
|
23
|
+
yellow: "\x1b[93m",
|
|
24
|
+
blue: "\x1b[94m",
|
|
25
|
+
magenta: "\x1b[95m",
|
|
26
|
+
cyan: "\x1b[96m",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// ─────────────────────────────────────────────
|
|
30
|
+
// Logger
|
|
31
|
+
// ─────────────────────────────────────────────
|
|
32
|
+
const log = {
|
|
33
|
+
info: (msg) =>
|
|
34
|
+
console.log(
|
|
35
|
+
`${c.cyan}${c.bold} ℹ ${c.reset}${c.white}${msg}${c.reset}`,
|
|
36
|
+
),
|
|
37
|
+
success: (msg) =>
|
|
38
|
+
console.log(
|
|
39
|
+
`${c.green}${c.bold} ✔ ${c.reset}${c.green}${msg}${c.reset}`,
|
|
40
|
+
),
|
|
41
|
+
warn: (msg) =>
|
|
42
|
+
console.log(
|
|
43
|
+
`${c.yellow}${c.bold} ⚠ ${c.reset}${c.yellow}${msg}${c.reset}`,
|
|
44
|
+
),
|
|
45
|
+
error: (msg) =>
|
|
46
|
+
console.log(`${c.red}${c.bold} ✖ ${c.reset}${c.red}${msg}${c.reset}`),
|
|
47
|
+
step: (n, label) =>
|
|
48
|
+
console.log(
|
|
49
|
+
`${c.magenta}${c.bold} [${n}] ${c.reset}${c.magenta}${label}${c.reset}`,
|
|
50
|
+
),
|
|
51
|
+
divider: () => console.log(`${c.gray} ${"─".repeat(52)}${c.reset}`),
|
|
52
|
+
blank: () => console.log(),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// ─────────────────────────────────────────────
|
|
56
|
+
// Steps Definition
|
|
57
|
+
// ─────────────────────────────────────────────
|
|
58
|
+
const STEPS = [
|
|
59
|
+
{ label: "Memory CLI", fn: installMemoryCLI },
|
|
60
|
+
{ label: "XEMS — XyPriss Entry Management System", fn: installXems },
|
|
61
|
+
{ label: "XSYS — XyPriss System Core", fn: installXsys },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
// ─────────────────────────────────────────────
|
|
65
|
+
// Post-Install Orchestrator
|
|
66
|
+
// ─────────────────────────────────────────────
|
|
67
|
+
async function postInstall() {
|
|
68
|
+
log.blank();
|
|
69
|
+
log.divider();
|
|
70
|
+
console.log(`${c.cyan}${c.bold} XyPriss — Post-Install Setup${c.reset}`);
|
|
71
|
+
log.divider();
|
|
72
|
+
log.blank();
|
|
73
|
+
|
|
74
|
+
const results = [];
|
|
75
|
+
|
|
76
|
+
for (let i = 0; i < STEPS.length; i++) {
|
|
77
|
+
const { label, fn } = STEPS[i];
|
|
78
|
+
log.step(`${i + 1}/${STEPS.length}`, label);
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
await fn();
|
|
82
|
+
results.push({ label, ok: true });
|
|
83
|
+
} catch (err) {
|
|
84
|
+
log.warn(`Step "${label}" encountered an issue: ${err.message}`);
|
|
85
|
+
results.push({ label, ok: false, err: err.message });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
log.blank();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Summary ──────────────────────────────────
|
|
92
|
+
log.divider();
|
|
93
|
+
console.log(`${c.cyan}${c.bold} Setup Summary${c.reset}`);
|
|
94
|
+
log.divider();
|
|
95
|
+
|
|
96
|
+
let allOk = true;
|
|
97
|
+
for (const r of results) {
|
|
98
|
+
if (r.ok) {
|
|
99
|
+
log.success(r.label);
|
|
100
|
+
} else {
|
|
101
|
+
log.warn(`${r.label} ${c.gray}(skipped: ${r.err})${c.reset}`);
|
|
102
|
+
allOk = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
log.blank();
|
|
107
|
+
|
|
108
|
+
if (allOk) {
|
|
109
|
+
log.success("All components installed. XyPriss is ready!");
|
|
110
|
+
} else {
|
|
111
|
+
log.warn(
|
|
112
|
+
"Setup completed with warnings. XyPriss will run in fallback mode.",
|
|
113
|
+
);
|
|
114
|
+
log.info(
|
|
115
|
+
"Some features may be limited until missing binaries are installed.",
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
log.blank();
|
|
120
|
+
log.divider();
|
|
121
|
+
log.blank();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ─────────────────────────────────────────────
|
|
125
|
+
// Entry Point
|
|
126
|
+
// ─────────────────────────────────────────────
|
|
127
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
128
|
+
postInstall().catch((error) => {
|
|
129
|
+
log.error(`Fatal error during post-install: ${error.message}`);
|
|
130
|
+
process.exit(0); // Don't break `npm install`
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export { postInstall };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { XyPrissSys } from "../src/sys";
|
|
2
|
+
import { XyPrissRunner } from "../src/sys/XyPrissRunner";
|
|
3
|
+
|
|
4
|
+
// Mock the global object structure if needed or just instantiate verify
|
|
5
|
+
// Since we are running with bun, we can probably just use the classes directly if we export them or setup the environment.
|
|
6
|
+
// But easier: invoke the existing API logic.
|
|
7
|
+
|
|
8
|
+
// We need to instantiate the system similar to how index.ts does it
|
|
9
|
+
const runner = new XyPrissRunner(process.cwd());
|
|
10
|
+
const sys = new XyPrissSys(runner);
|
|
11
|
+
|
|
12
|
+
// Monkey patch global if needed by some internals, but FSApi mainly uses `this.runner`
|
|
13
|
+
// casting to any to access the dynamically mixed-in methods if typescript complains,
|
|
14
|
+
// though we instantiated SysApi which extends FSApi.
|
|
15
|
+
|
|
16
|
+
console.log("\n--- STARTING DEDICATED FS API VERIFICATION ---");
|
|
17
|
+
|
|
18
|
+
const testDir = "temp_fs_verification";
|
|
19
|
+
const testFile = `${testDir}/verify.txt`;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// 1. Directory Management
|
|
23
|
+
sys.$rmIfExists(testDir);
|
|
24
|
+
sys.$ensureDir(testDir);
|
|
25
|
+
if (!sys.$isDir(testDir)) throw new Error("Dir creation failed");
|
|
26
|
+
console.log("[PASS] Directory creation");
|
|
27
|
+
|
|
28
|
+
// 2. File Writing & Existence
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
sys.$writeIfNotExists(testFile, "Line 1\n");
|
|
31
|
+
if (!sys.$exists(testFile)) throw new Error("File creation failed");
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
const wroteAgain = sys.$writeIfNotExists(testFile, "New Content");
|
|
34
|
+
if (wroteAgain)
|
|
35
|
+
throw new Error(
|
|
36
|
+
"writeIfNotExists should return false for existing file"
|
|
37
|
+
);
|
|
38
|
+
console.log("[PASS] File writing and existence check");
|
|
39
|
+
|
|
40
|
+
// 3. Appending & Reading
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
sys.$appendLine(testFile, "Line 2");
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
const lines = sys.$readLines(testFile);
|
|
45
|
+
if (lines.length !== 3)
|
|
46
|
+
throw new Error(`Expected 3 lines (incl empty), got ${lines.length}`);
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
const nonEmpty = sys.$readNonEmptyLines(testFile);
|
|
49
|
+
if (nonEmpty.length !== 2)
|
|
50
|
+
throw new Error(`Expected 2 non-empty lines, got ${nonEmpty.length}`);
|
|
51
|
+
console.log("[PASS] Append and Read Lines");
|
|
52
|
+
|
|
53
|
+
// 4. Metadata
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
const sizeHuman = sys.$sizeHuman(testFile);
|
|
56
|
+
if (!sizeHuman.includes("B")) throw new Error("Invalid human size format");
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
const createdAt = sys.$createdAt(testFile);
|
|
59
|
+
if (!(createdAt instanceof Date) || isNaN(createdAt.getTime()))
|
|
60
|
+
throw new Error("Invalid creation date");
|
|
61
|
+
console.log("[PASS] Metadata (Size & Dates)");
|
|
62
|
+
|
|
63
|
+
// 5. Manipulation
|
|
64
|
+
const copyFile = "verify_copy.txt";
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
sys.$duplicate(testFile, copyFile);
|
|
67
|
+
if (!sys.$exists(`${testDir}/${copyFile}`))
|
|
68
|
+
throw new Error("Duplication failed");
|
|
69
|
+
|
|
70
|
+
const renamedFile = "verify_renamed.txt";
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
sys.$rename(`${testDir}/${copyFile}`, `${testDir}/${renamedFile}`);
|
|
73
|
+
if (sys.$exists(`${testDir}/${copyFile}`))
|
|
74
|
+
throw new Error("Old file still exists after rename");
|
|
75
|
+
if (!sys.$exists(`${testDir}/${renamedFile}`))
|
|
76
|
+
throw new Error("Renamed file missing");
|
|
77
|
+
console.log("[PASS] Duplication and Renaming");
|
|
78
|
+
|
|
79
|
+
// 6. Search
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
const txtFiles = sys.$findByExt(testDir, "txt");
|
|
82
|
+
if (txtFiles.length < 2) throw new Error("Failed to find .txt files");
|
|
83
|
+
console.log("[PASS] Extension search");
|
|
84
|
+
|
|
85
|
+
// 7. Cleanup
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
sys.$rmIfExists(testDir);
|
|
88
|
+
if (sys.$exists(testDir)) throw new Error("Cleanup failed");
|
|
89
|
+
console.log("[PASS] Cleanup");
|
|
90
|
+
|
|
91
|
+
console.log("\n✅ ALL FS API TESTS PASSED SUCCESSFULLY");
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("\n❌ TEST FAILED:", error);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { XyPrissFS } from "../src/sys/System";
|
|
2
|
+
|
|
3
|
+
async function testBridge() {
|
|
4
|
+
console.log("🚀 Testing XyPrissFS Rust Bridge...");
|
|
5
|
+
|
|
6
|
+
const root = process.cwd();
|
|
7
|
+
const xfs = new XyPrissFS({ __root__: root });
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
// 1. Test Path Operations (JS)
|
|
11
|
+
console.log("\n--- Path Operations (JS) ---");
|
|
12
|
+
const resolved = xfs.$resolve("src", "index.ts");
|
|
13
|
+
console.log(`Resolved path: ${resolved}`);
|
|
14
|
+
|
|
15
|
+
// 2. Test Filesystem Operations (Rust)
|
|
16
|
+
console.log("\n--- Filesystem Operations (Rust) ---");
|
|
17
|
+
const items = xfs.$ls(".");
|
|
18
|
+
console.log(`Found ${items.length} items in root.`);
|
|
19
|
+
console.log(`First 5 items: ${items.slice(0, 5).join(", ")}`);
|
|
20
|
+
|
|
21
|
+
// 3. Test System Operations (Rust)
|
|
22
|
+
console.log("\n--- System Operations (Rust) ---");
|
|
23
|
+
const cpuCores = xfs.$cpu(true);
|
|
24
|
+
if (cpuCores && cpuCores.length > 0) {
|
|
25
|
+
console.log(`CPU: ${cpuCores[0].brand}`);
|
|
26
|
+
console.log(`Cores: ${cpuCores[0].core_count} detected`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const memInfo = xfs.$memory();
|
|
30
|
+
console.log(
|
|
31
|
+
`Memory: ${(memInfo.total / 1024 / 1024 / 1024).toFixed(2)} GB`
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// 4. Test Search Operations (Rust)
|
|
35
|
+
console.log("\n--- Search Operations (Rust) ---");
|
|
36
|
+
const tsFiles = xfs.$find("src", "\\.ts$");
|
|
37
|
+
console.log(`Found ${tsFiles.length} TypeScript files in src.`);
|
|
38
|
+
|
|
39
|
+
console.log("\n✅ All bridge tests passed!");
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error("\n--- OUTPUT DEBUG ---");
|
|
42
|
+
console.error(error);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
testBridge();
|
|
48
|
+
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/***************************************************************************
|
|
3
|
+
* XyPrissJS - Fast And Secure
|
|
4
|
+
*
|
|
5
|
+
* @author Nehonix
|
|
6
|
+
* @license Nehonix OSL (NOSL)
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2025 Nehonix. All rights reserved.
|
|
9
|
+
*
|
|
10
|
+
* This License governs the use, modification, and distribution of software
|
|
11
|
+
* provided by NEHONIX under its open source projects.
|
|
12
|
+
* NEHONIX is committed to fostering collaborative innovation while strictly
|
|
13
|
+
* protecting its intellectual property rights.
|
|
14
|
+
* Violation of any term of this License will result in immediate termination of all granted rights
|
|
15
|
+
* and may subject the violator to legal action.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
18
|
+
* INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
|
19
|
+
* AND NON-INFRINGEMENT.
|
|
20
|
+
* IN NO EVENT SHALL NEHONIX BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
21
|
+
* OR CONSEQUENTIAL DAMAGES ARISING FROM THE USE OR INABILITY TO USE THE SOFTWARE,
|
|
22
|
+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
23
|
+
*
|
|
24
|
+
***************************************************************************** */
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Nehonix XEMS CLI Bridge
|
|
28
|
+
*
|
|
29
|
+
* This is the main bridge for the xems command.
|
|
30
|
+
* It manages the execution of the proprietary Go-based XEMS binary.
|
|
31
|
+
*
|
|
32
|
+
* © 2026 Nehonix Team. All rights reserved.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { spawn } from "node:child_process";
|
|
36
|
+
import path from "node:path";
|
|
37
|
+
import fs from "node:fs";
|
|
38
|
+
import os from "node:os";
|
|
39
|
+
import { fileURLToPath } from "node:url";
|
|
40
|
+
|
|
41
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
42
|
+
const __dirname = path.dirname(__filename);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the path to the xems binary
|
|
46
|
+
*/
|
|
47
|
+
function getBinaryPath() {
|
|
48
|
+
const isWin = os.platform() === "win32";
|
|
49
|
+
const binName = isWin ? "xems.exe" : "xems";
|
|
50
|
+
|
|
51
|
+
// Strategic locations for the binary
|
|
52
|
+
const locations = [
|
|
53
|
+
path.join(__dirname, "..", "bin", binName), // Production (npm install)
|
|
54
|
+
path.join(process.cwd(), "bin", binName), // Local development
|
|
55
|
+
path.join(__dirname, "..", "tools", "XEMS", "bin", binName), // Dev target
|
|
56
|
+
path.join(__dirname, "..", "tools", "XEMS", "dist", binName), // Dist target
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
for (const loc of locations) {
|
|
60
|
+
if (fs.existsSync(loc)) {
|
|
61
|
+
return loc;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Execute the binary with the provided arguments
|
|
70
|
+
*/
|
|
71
|
+
function main() {
|
|
72
|
+
const binaryPath = getBinaryPath();
|
|
73
|
+
const args = process.argv.slice(2);
|
|
74
|
+
|
|
75
|
+
if (!binaryPath) {
|
|
76
|
+
console.error("\x1b[31m[ERROR] XEMS Binary not found.\x1b[0m");
|
|
77
|
+
console.error(
|
|
78
|
+
"Please ensure the binary is installed by running: \x1b[36mxfpm update xypriss\x1b[0m",
|
|
79
|
+
);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Spawn the binary process
|
|
84
|
+
const child = spawn(binaryPath, args, {
|
|
85
|
+
stdio: "inherit",
|
|
86
|
+
env: {
|
|
87
|
+
...process.env,
|
|
88
|
+
XEMS_BINARY_PATH: binaryPath,
|
|
89
|
+
XEMS_EXEC_CONTEXT: "npm-bin",
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Mirror exit signals and codes
|
|
94
|
+
child.on("exit", (code, signal) => {
|
|
95
|
+
if (signal) {
|
|
96
|
+
process.kill(process.pid, signal);
|
|
97
|
+
} else {
|
|
98
|
+
process.exit(code ?? 0);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
child.on("error", (err) => {
|
|
103
|
+
console.error(
|
|
104
|
+
"\x1b[31m[CRITICAL] Failed to initiate xems execution:\x1b[0m",
|
|
105
|
+
err.message,
|
|
106
|
+
);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
main();
|
|
112
|
+
|
|
113
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* *****************************************************************************
|
|
3
|
+
* Nehonix XyPriss System CLI
|
|
4
|
+
*
|
|
5
|
+
* ACCESS RESTRICTIONS:
|
|
6
|
+
* - This software is exclusively for use by Authorized Personnel of NEHONIX
|
|
7
|
+
* - Intended for Internal Use only within NEHONIX operations
|
|
8
|
+
* - No rights granted to unauthorized individuals or entities
|
|
9
|
+
* - All modifications are works made for hire assigned to NEHONIX
|
|
10
|
+
*
|
|
11
|
+
* PROHIBITED ACTIVITIES:
|
|
12
|
+
* - Copying, distributing, or sublicensing without written permission
|
|
13
|
+
* - Reverse engineering, decompiling, or disassembling
|
|
14
|
+
* - Creating derivative works without explicit authorization
|
|
15
|
+
* - External use or commercial distribution outside NEHONIX
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
* SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* For questions or permissions, contact:
|
|
26
|
+
* NEHONIX Legal Department
|
|
27
|
+
* Email: legal@nehonix.com
|
|
28
|
+
* Website: www.nehonix.com
|
|
29
|
+
***************************************************************************** */
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Nehonix XyPriss System CLI Tool - High-performance system & FS management
|
|
33
|
+
*
|
|
34
|
+
* This is the main bridge for the xsys command.
|
|
35
|
+
* It manages the execution of the proprietary Rust-based xsys binary.
|
|
36
|
+
*
|
|
37
|
+
* © 2026 Nehonix Team. All rights reserved.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import { spawn } from "node:child_process";
|
|
41
|
+
import path from "node:path";
|
|
42
|
+
import fs from "node:fs";
|
|
43
|
+
import os from "node:os";
|
|
44
|
+
import { fileURLToPath } from "node:url";
|
|
45
|
+
|
|
46
|
+
// Support ESM __dirname
|
|
47
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
48
|
+
const __dirname = path.dirname(__filename);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get the path to the xsys binary
|
|
52
|
+
*/
|
|
53
|
+
function getBinaryPath() {
|
|
54
|
+
const isWin = os.platform() === "win32";
|
|
55
|
+
const binName = isWin ? "xsys.exe" : "xsys";
|
|
56
|
+
|
|
57
|
+
// Strategic locations for the binary
|
|
58
|
+
const locations = [
|
|
59
|
+
path.join(__dirname, "..", "bin", binName), // Production (npm install)
|
|
60
|
+
path.join(process.cwd(), "bin", binName), // Local development
|
|
61
|
+
path.join(
|
|
62
|
+
__dirname,
|
|
63
|
+
"..",
|
|
64
|
+
"tools",
|
|
65
|
+
"xypriss-sys",
|
|
66
|
+
"target",
|
|
67
|
+
"release",
|
|
68
|
+
binName
|
|
69
|
+
), // Dev target
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
for (const loc of locations) {
|
|
73
|
+
if (fs.existsSync(loc)) {
|
|
74
|
+
return loc;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Execute the binary with the provided arguments
|
|
83
|
+
*/
|
|
84
|
+
function main() {
|
|
85
|
+
const binaryPath = getBinaryPath();
|
|
86
|
+
const args = process.argv.slice(2);
|
|
87
|
+
|
|
88
|
+
if (!binaryPath) {
|
|
89
|
+
console.error(
|
|
90
|
+
"\x1b[31m[ERROR] XyPriss System Binary (xsys) not found.\x1b[0m"
|
|
91
|
+
);
|
|
92
|
+
console.error(
|
|
93
|
+
"Please ensure the binary is installed by running: \x1b[36mnpm update xypriss\x1b[0m"
|
|
94
|
+
);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Spawn the binary process
|
|
99
|
+
const child = spawn(binaryPath, args, {
|
|
100
|
+
stdio: "inherit",
|
|
101
|
+
env: {
|
|
102
|
+
...process.env,
|
|
103
|
+
XYPRISS_BINARY_PATH: binaryPath,
|
|
104
|
+
XYPRISS_EXEC_CONTEXT: "npm-bin",
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Mirror exit signals and codes
|
|
109
|
+
child.on("exit", (code, signal) => {
|
|
110
|
+
if (signal) {
|
|
111
|
+
process.kill(process.pid, signal);
|
|
112
|
+
} else {
|
|
113
|
+
process.exit(code ?? 0);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
child.on("error", (err) => {
|
|
118
|
+
console.error(
|
|
119
|
+
"\x1b[31m[CRITICAL] Failed to initiate xsys execution:\x1b[0m",
|
|
120
|
+
err.message
|
|
121
|
+
);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Execution entry point
|
|
127
|
+
main();
|
|
128
|
+
|
|
129
|
+
|