xypriss 9.0.1 → 9.0.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.
- package/package.json +3 -2
- package/scripts/install-memory-cli.js +12 -3
- package/scripts/install-xems.js +137 -29
- package/scripts/postinstall-xsys.js +134 -23
- package/scripts/postinstall.js +109 -19
- package/scripts/xems.run.js +113 -0
package/package.json
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
},
|
|
7
7
|
"bin": {
|
|
8
8
|
"xsys": "scripts/xys.run.js",
|
|
9
|
-
"xypriss-sys": "scripts/xys.run.js"
|
|
9
|
+
"xypriss-sys": "scripts/xys.run.js",
|
|
10
|
+
"xems": "scripts/xems.run.js"
|
|
10
11
|
},
|
|
11
12
|
"browserslist": [
|
|
12
13
|
"> 1%",
|
|
@@ -274,6 +275,6 @@
|
|
|
274
275
|
"support": "https://github.com/Nehonix-Team/XyPriss/issues",
|
|
275
276
|
"type": "module",
|
|
276
277
|
"types": "dist/index.d.ts",
|
|
277
|
-
"version": "9.0.
|
|
278
|
+
"version": "9.0.3"
|
|
278
279
|
}
|
|
279
280
|
|
|
@@ -128,14 +128,21 @@ async function installMemoryCLI() {
|
|
|
128
128
|
const info = getPlatformBinary();
|
|
129
129
|
if (!info) return;
|
|
130
130
|
|
|
131
|
+
console.log(`📂 Target directory: ${BIN_DIR}`);
|
|
132
|
+
console.log(`📦 Binary: ${info.binaryName}`);
|
|
133
|
+
|
|
131
134
|
if (fs.existsSync(info.genericPath)) {
|
|
132
|
-
console.log(
|
|
135
|
+
console.log(
|
|
136
|
+
`✨ Memory CLI already present at ${info.genericPath}, skipping.`,
|
|
137
|
+
);
|
|
133
138
|
return;
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
try {
|
|
137
|
-
console.log(`📥 Fetching Memory CLI
|
|
142
|
+
console.log(`📥 Fetching Memory CLI from:`);
|
|
143
|
+
console.log(` 🔗 URL: ${info.url}`);
|
|
138
144
|
await downloadFile(info.url, info.localPath);
|
|
145
|
+
console.log("✅ Downloaded successfully.");
|
|
139
146
|
|
|
140
147
|
if (process.platform !== "win32") {
|
|
141
148
|
fs.chmodSync(info.localPath, 0o755);
|
|
@@ -151,7 +158,9 @@ async function installMemoryCLI() {
|
|
|
151
158
|
|
|
152
159
|
const isValid = await verifyBinary(info.localPath);
|
|
153
160
|
if (isValid) {
|
|
154
|
-
console.log(
|
|
161
|
+
console.log(
|
|
162
|
+
`🎉 XyPriss MCLI installed successfully at: ${info.genericPath}`,
|
|
163
|
+
);
|
|
155
164
|
} else {
|
|
156
165
|
console.warn(
|
|
157
166
|
"⚠️ MCLI verification failed, it might not work as expected.",
|
package/scripts/install-xems.js
CHANGED
|
@@ -14,13 +14,70 @@ import https from "https";
|
|
|
14
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
15
|
const __dirname = path.dirname(__filename);
|
|
16
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
|
+
// ─────────────────────────────────────────────
|
|
17
70
|
const BIN_DIR = path.join(__dirname, "..", "bin");
|
|
18
71
|
const REPO = "Nehonix-Team/XyPriss-XEMS";
|
|
19
|
-
const CDN_BASE_URL = "https://dll.nehonix.com/dl/mds/xems/bin";
|
|
72
|
+
const CDN_BASE_URL = "https://dll.nehonix.com/dl/mds/xems/bin";
|
|
73
|
+
|
|
74
|
+
// ─────────────────────────────────────────────
|
|
75
|
+
// Platform Detection
|
|
76
|
+
// ─────────────────────────────────────────────
|
|
20
77
|
|
|
21
78
|
/**
|
|
22
|
-
*
|
|
23
|
-
* Maps
|
|
79
|
+
* Returns platform-specific binary metadata for XEMS.
|
|
80
|
+
* Maps to the files in tools/XEMS/dist/
|
|
24
81
|
*/
|
|
25
82
|
function getPlatformBinary() {
|
|
26
83
|
const platform = process.platform;
|
|
@@ -37,34 +94,32 @@ function getPlatformBinary() {
|
|
|
37
94
|
return null;
|
|
38
95
|
}
|
|
39
96
|
|
|
40
|
-
|
|
41
|
-
const binaryName = `xems-${binaryTarget}${
|
|
97
|
+
const ext = platform === "win32" ? ".exe" : "";
|
|
98
|
+
const binaryName = `xems-${binaryTarget}${ext}`;
|
|
42
99
|
|
|
43
100
|
return {
|
|
44
101
|
binaryName,
|
|
102
|
+
platform,
|
|
103
|
+
arch,
|
|
45
104
|
url: `https://github.com/${REPO}/releases/latest/download/${binaryName}`,
|
|
46
105
|
fallbackUrl: `${CDN_BASE_URL}/${binaryName}`,
|
|
47
106
|
localPath: path.join(BIN_DIR, binaryName),
|
|
48
|
-
genericPath: path.join(
|
|
49
|
-
BIN_DIR,
|
|
50
|
-
"xems" + (platform === "win32" ? ".exe" : ""),
|
|
51
|
-
),
|
|
107
|
+
genericPath: path.join(BIN_DIR, `xems${ext}`),
|
|
52
108
|
};
|
|
53
109
|
}
|
|
54
110
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
111
|
+
// ─────────────────────────────────────────────
|
|
112
|
+
// Downloader (with redirect support)
|
|
113
|
+
// ─────────────────────────────────────────────
|
|
114
|
+
|
|
58
115
|
function downloadFile(url, dest) {
|
|
59
116
|
return new Promise((resolve, reject) => {
|
|
60
117
|
const file = fs.createWriteStream(dest);
|
|
61
|
-
|
|
62
118
|
const request = https.get(
|
|
63
119
|
url,
|
|
64
|
-
{
|
|
65
|
-
headers: { "User-Agent": "XyPriss-Installer" },
|
|
66
|
-
},
|
|
120
|
+
{ headers: { "User-Agent": "XyPriss-Installer" } },
|
|
67
121
|
(response) => {
|
|
122
|
+
// Follow redirects
|
|
68
123
|
if (
|
|
69
124
|
response.statusCode >= 300 &&
|
|
70
125
|
response.statusCode < 400 &&
|
|
@@ -82,14 +137,23 @@ function downloadFile(url, dest) {
|
|
|
82
137
|
fs.unlinkSync(dest);
|
|
83
138
|
return reject(
|
|
84
139
|
new Error(
|
|
85
|
-
`Server responded with ${response.statusCode}`,
|
|
140
|
+
`Server responded with HTTP ${response.statusCode}`,
|
|
86
141
|
),
|
|
87
142
|
);
|
|
88
143
|
}
|
|
89
144
|
|
|
90
|
-
|
|
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
|
+
});
|
|
91
153
|
|
|
154
|
+
response.pipe(file);
|
|
92
155
|
file.on("finish", () => {
|
|
156
|
+
process.stdout.write(` ${c.green}done${c.reset}\n`);
|
|
93
157
|
file.close();
|
|
94
158
|
resolve();
|
|
95
159
|
});
|
|
@@ -104,58 +168,102 @@ function downloadFile(url, dest) {
|
|
|
104
168
|
});
|
|
105
169
|
}
|
|
106
170
|
|
|
171
|
+
// ─────────────────────────────────────────────
|
|
172
|
+
// Main Installer
|
|
173
|
+
// ─────────────────────────────────────────────
|
|
174
|
+
|
|
107
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
|
|
108
185
|
if (!fs.existsSync(BIN_DIR)) {
|
|
109
186
|
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
187
|
+
log.detail(`Created bin directory: ${BIN_DIR}`);
|
|
110
188
|
}
|
|
111
189
|
|
|
112
190
|
const info = getPlatformBinary();
|
|
113
191
|
if (!info) {
|
|
114
|
-
|
|
115
|
-
"
|
|
192
|
+
log.error(
|
|
193
|
+
"Unsupported platform/architecture. XEMS cannot be installed.",
|
|
116
194
|
);
|
|
117
195
|
return;
|
|
118
196
|
}
|
|
119
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
|
|
120
206
|
if (fs.existsSync(info.genericPath)) {
|
|
121
|
-
|
|
207
|
+
log.success(`XEMS is already installed → ${info.genericPath}`);
|
|
208
|
+
log.blank();
|
|
122
209
|
return;
|
|
123
210
|
}
|
|
124
211
|
|
|
125
|
-
|
|
126
|
-
|
|
212
|
+
// Attempt GitHub download, then fallback CDN
|
|
213
|
+
log.step("Downloading XEMS binary…");
|
|
127
214
|
try {
|
|
128
215
|
try {
|
|
216
|
+
log.link("GitHub", info.url);
|
|
129
217
|
await downloadFile(info.url, info.localPath);
|
|
130
|
-
|
|
131
|
-
|
|
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);
|
|
132
223
|
await downloadFile(info.fallbackUrl, info.localPath);
|
|
224
|
+
log.success("Downloaded from fallback CDN.");
|
|
133
225
|
}
|
|
134
226
|
|
|
227
|
+
// Set executable bit on Unix
|
|
135
228
|
if (process.platform !== "win32") {
|
|
136
229
|
fs.chmodSync(info.localPath, 0o755);
|
|
230
|
+
log.detail("Executable permission set (chmod 755).");
|
|
137
231
|
}
|
|
138
232
|
|
|
233
|
+
// Create generic alias (symlink on Unix, copy on Windows)
|
|
139
234
|
if (process.platform === "win32") {
|
|
140
235
|
fs.copyFileSync(info.localPath, info.genericPath);
|
|
236
|
+
log.detail(`Copied binary → ${info.genericPath}`);
|
|
141
237
|
} else {
|
|
142
238
|
if (fs.existsSync(info.genericPath))
|
|
143
239
|
fs.unlinkSync(info.genericPath);
|
|
144
240
|
fs.symlinkSync(path.basename(info.localPath), info.genericPath);
|
|
241
|
+
log.detail(`Symlink created → ${info.genericPath}`);
|
|
145
242
|
}
|
|
146
243
|
|
|
147
|
-
|
|
244
|
+
log.blank();
|
|
245
|
+
log.success(
|
|
246
|
+
`XEMS successfully installed at: ${c.bold}${info.genericPath}${c.reset}`,
|
|
247
|
+
);
|
|
148
248
|
} catch (err) {
|
|
149
|
-
|
|
249
|
+
log.blank();
|
|
250
|
+
log.error(`XEMS installation failed: ${err.message}`);
|
|
150
251
|
}
|
|
252
|
+
|
|
253
|
+
log.blank();
|
|
254
|
+
log.divider();
|
|
255
|
+
log.blank();
|
|
151
256
|
}
|
|
152
257
|
|
|
258
|
+
// ─────────────────────────────────────────────
|
|
259
|
+
// Entry Point
|
|
260
|
+
// ─────────────────────────────────────────────
|
|
261
|
+
|
|
153
262
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
154
263
|
installXems().catch((error) => {
|
|
155
|
-
|
|
264
|
+
log.error(`Fatal error: ${error.message}`);
|
|
156
265
|
process.exit(0);
|
|
157
266
|
});
|
|
158
267
|
}
|
|
159
268
|
|
|
160
269
|
export { installXems };
|
|
161
|
-
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
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
|
+
|
|
2
9
|
import fs from "fs";
|
|
3
10
|
import { join, dirname, basename } from "path";
|
|
4
11
|
import { platform, arch } from "os";
|
|
@@ -8,22 +15,73 @@ import { fileURLToPath } from "url";
|
|
|
8
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
16
|
const __dirname = dirname(__filename);
|
|
10
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
|
+
// ─────────────────────────────────────────────
|
|
11
69
|
const REPO = "Nehonix-Team/XyPriss";
|
|
12
70
|
const BIN_NAME = "xsys";
|
|
13
71
|
const BIN_DIR = join(__dirname, "..", "bin");
|
|
14
72
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
73
|
+
// ─────────────────────────────────────────────
|
|
74
|
+
// Downloader (with redirect support)
|
|
75
|
+
// ─────────────────────────────────────────────
|
|
76
|
+
|
|
18
77
|
function downloadFile(url, dest) {
|
|
19
78
|
return new Promise((resolve, reject) => {
|
|
20
79
|
const file = fs.createWriteStream(dest);
|
|
21
80
|
const request = https.get(
|
|
22
81
|
url,
|
|
23
|
-
{
|
|
24
|
-
headers: { "User-Agent": "XyPriss-Installer" },
|
|
25
|
-
},
|
|
82
|
+
{ headers: { "User-Agent": "XyPriss-Installer" } },
|
|
26
83
|
(response) => {
|
|
84
|
+
// Follow redirects
|
|
27
85
|
if (
|
|
28
86
|
response.statusCode >= 300 &&
|
|
29
87
|
response.statusCode < 400 &&
|
|
@@ -35,18 +93,35 @@ function downloadFile(url, dest) {
|
|
|
35
93
|
.then(resolve)
|
|
36
94
|
.catch(reject);
|
|
37
95
|
}
|
|
96
|
+
|
|
38
97
|
if (response.statusCode !== 200) {
|
|
39
98
|
file.close();
|
|
40
99
|
fs.unlinkSync(dest);
|
|
41
|
-
return reject(
|
|
100
|
+
return reject(
|
|
101
|
+
new Error(
|
|
102
|
+
`Server responded with HTTP ${response.statusCode}`,
|
|
103
|
+
),
|
|
104
|
+
);
|
|
42
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
|
+
|
|
43
116
|
response.pipe(file);
|
|
44
117
|
file.on("finish", () => {
|
|
118
|
+
process.stdout.write(` ${c.green}done${c.reset}\n`);
|
|
45
119
|
file.close();
|
|
46
120
|
resolve();
|
|
47
121
|
});
|
|
48
122
|
},
|
|
49
123
|
);
|
|
124
|
+
|
|
50
125
|
request.on("error", (err) => {
|
|
51
126
|
file.close();
|
|
52
127
|
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
@@ -55,68 +130,104 @@ function downloadFile(url, dest) {
|
|
|
55
130
|
});
|
|
56
131
|
}
|
|
57
132
|
|
|
133
|
+
// ─────────────────────────────────────────────
|
|
134
|
+
// Main Installer
|
|
135
|
+
// ─────────────────────────────────────────────
|
|
136
|
+
|
|
58
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
|
|
59
147
|
if (!fs.existsSync(BIN_DIR)) {
|
|
60
148
|
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
149
|
+
log.detail(`Created bin directory: ${BIN_DIR}`);
|
|
61
150
|
}
|
|
62
151
|
|
|
63
152
|
const osName = platform();
|
|
64
153
|
const archName = arch();
|
|
65
154
|
|
|
66
|
-
//
|
|
155
|
+
// Map to binary target name
|
|
67
156
|
let binaryTarget = "";
|
|
68
157
|
if (osName === "linux") {
|
|
69
158
|
binaryTarget = archName === "arm64" ? "linux-arm64" : "linux-amd64";
|
|
70
159
|
} else if (osName === "darwin") {
|
|
71
|
-
binaryTarget = archName === "arm64" ? "darwin-arm64" : "darwin-amd64";
|
|
160
|
+
binaryTarget = archName === "arm64" ? "darwin-arm64" : "darwin-amd64";
|
|
72
161
|
} else if (osName === "win32") {
|
|
73
162
|
binaryTarget = archName === "arm64" ? "windows-arm64" : "windows-amd64";
|
|
74
163
|
} else {
|
|
75
|
-
|
|
164
|
+
log.error(`Unsupported platform: ${osName}`);
|
|
76
165
|
return;
|
|
77
166
|
}
|
|
78
167
|
|
|
79
|
-
const
|
|
168
|
+
const ext = osName === "win32" ? ".exe" : "";
|
|
169
|
+
const binaryFileName = `${BIN_NAME}-${binaryTarget}${ext}`;
|
|
80
170
|
const url = `https://github.com/${REPO}/releases/latest/download/${binaryFileName}`;
|
|
81
171
|
const localPath = join(BIN_DIR, binaryFileName);
|
|
82
|
-
const genericPath = join(
|
|
83
|
-
|
|
84
|
-
|
|
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}`,
|
|
85
176
|
);
|
|
177
|
+
log.info(`Binary : ${c.yellow}${binaryFileName}${c.reset}`);
|
|
178
|
+
log.info(`Target : ${c.yellow}${BIN_DIR}${c.reset}`);
|
|
179
|
+
log.blank();
|
|
86
180
|
|
|
181
|
+
// Skip if already installed
|
|
87
182
|
if (fs.existsSync(genericPath)) {
|
|
88
|
-
|
|
183
|
+
log.success(`XSYS is already installed → ${genericPath}`);
|
|
184
|
+
log.blank();
|
|
89
185
|
return;
|
|
90
186
|
}
|
|
91
187
|
|
|
92
|
-
|
|
188
|
+
// Download
|
|
189
|
+
log.step("Downloading XSYS binary…");
|
|
190
|
+
log.link("GitHub", url);
|
|
93
191
|
|
|
94
192
|
try {
|
|
95
193
|
await downloadFile(url, localPath);
|
|
96
194
|
|
|
195
|
+
// Set executable bit on Unix
|
|
97
196
|
if (osName !== "win32") {
|
|
98
197
|
fs.chmodSync(localPath, 0o755);
|
|
198
|
+
log.detail("Executable permission set (chmod 755).");
|
|
99
199
|
}
|
|
100
200
|
|
|
101
|
-
//
|
|
201
|
+
// Create generic alias (symlink on Unix, copy on Windows)
|
|
102
202
|
if (osName === "win32") {
|
|
103
203
|
fs.copyFileSync(localPath, genericPath);
|
|
204
|
+
log.detail(`Copied binary → ${genericPath}`);
|
|
104
205
|
} else {
|
|
105
206
|
if (fs.existsSync(genericPath)) fs.unlinkSync(genericPath);
|
|
106
207
|
fs.symlinkSync(basename(localPath), genericPath);
|
|
208
|
+
log.detail(`Symlink created → ${genericPath}`);
|
|
107
209
|
}
|
|
108
210
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
`❌ Échec de l'acquisition du binaire XSYS : ${err.message}`,
|
|
211
|
+
log.blank();
|
|
212
|
+
log.success(
|
|
213
|
+
`XSYS successfully installed at: ${c.bold}${genericPath}${c.reset}`,
|
|
113
214
|
);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
log.blank();
|
|
217
|
+
log.error(`XSYS installation failed: ${err.message}`);
|
|
114
218
|
}
|
|
219
|
+
|
|
220
|
+
log.blank();
|
|
221
|
+
log.divider();
|
|
222
|
+
log.blank();
|
|
115
223
|
}
|
|
116
224
|
|
|
225
|
+
// ─────────────────────────────────────────────
|
|
226
|
+
// Entry Point
|
|
227
|
+
// ─────────────────────────────────────────────
|
|
228
|
+
|
|
117
229
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
118
230
|
installXsys().catch(() => process.exit(0));
|
|
119
231
|
}
|
|
120
232
|
|
|
121
233
|
export { installXsys };
|
|
122
|
-
|
package/scripts/postinstall.js
CHANGED
|
@@ -2,42 +2,132 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* XyPriss Post-Install Script
|
|
5
|
-
* Runs after npm install to set up platform-specific binaries
|
|
5
|
+
* Runs after `npm install` to set up all platform-specific binaries.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { installMemoryCLI } from "./install-memory-cli.js";
|
|
9
9
|
import { installXems } from "./install-xems.js";
|
|
10
10
|
import { installXsys } from "./postinstall-xsys.js";
|
|
11
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
|
+
// ─────────────────────────────────────────────
|
|
12
67
|
async function postInstall() {
|
|
13
|
-
|
|
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();
|
|
14
73
|
|
|
15
|
-
|
|
16
|
-
// 1. Install Memory CLI
|
|
17
|
-
await installMemoryCLI();
|
|
74
|
+
const results = [];
|
|
18
75
|
|
|
19
|
-
|
|
20
|
-
|
|
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
|
+
}
|
|
21
90
|
|
|
22
|
-
|
|
23
|
-
|
|
91
|
+
// ── Summary ──────────────────────────────────
|
|
92
|
+
log.divider();
|
|
93
|
+
console.log(`${c.cyan}${c.bold} Setup Summary${c.reset}`);
|
|
94
|
+
log.divider();
|
|
24
95
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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.",
|
|
30
116
|
);
|
|
31
|
-
console.log("📝 XyPriss will continue to work with fallback mode.");
|
|
32
117
|
}
|
|
118
|
+
|
|
119
|
+
log.blank();
|
|
120
|
+
log.divider();
|
|
121
|
+
log.blank();
|
|
33
122
|
}
|
|
34
123
|
|
|
35
|
-
//
|
|
124
|
+
// ─────────────────────────────────────────────
|
|
125
|
+
// Entry Point
|
|
126
|
+
// ─────────────────────────────────────────────
|
|
36
127
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
37
128
|
postInstall().catch((error) => {
|
|
38
|
-
|
|
39
|
-
// Don't
|
|
40
|
-
process.exit(0);
|
|
129
|
+
log.error(`Fatal error during post-install: ${error.message}`);
|
|
130
|
+
process.exit(0); // Don't break `npm install`
|
|
41
131
|
});
|
|
42
132
|
}
|
|
43
133
|
|
|
@@ -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
|
+
|