@qpfai/pf-gate-cli 1.0.1 → 1.0.2
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.
|
Binary file
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-02-
|
|
3
|
+
"generatedAt": "2026-02-16T19:11:19.187Z",
|
|
4
4
|
"pythonPackage": "persons-field",
|
|
5
5
|
"pythonPackageVersion": "1.0.0",
|
|
6
6
|
"wheel": "persons_field-1.0.0-py3-none-any.whl",
|
|
7
|
-
"sha256": "
|
|
7
|
+
"sha256": "30ef4c0fdd6ada01a9edcdffbacf3a6a3d7c0e676ab1e13670362594caa84b7f"
|
|
8
8
|
}
|
package/lib/main.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import https from "node:https";
|
|
4
5
|
import os from "node:os";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import process from "node:process";
|
|
8
|
+
import readline from "node:readline/promises";
|
|
7
9
|
import { fileURLToPath } from "node:url";
|
|
8
10
|
|
|
9
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -12,6 +14,7 @@ const PACKAGE_ROOT = path.resolve(__dirname, "..");
|
|
|
12
14
|
const ARTIFACT_MANIFEST_PATH = path.join(PACKAGE_ROOT, "artifacts", "python-wheel.json");
|
|
13
15
|
const INSTALL_STATE_NAME = "install-state.json";
|
|
14
16
|
const PYTHON_CANDIDATES = ["python3.13", "python3", "python"];
|
|
17
|
+
const NPM_REGISTRY = "https://registry.npmjs.org";
|
|
15
18
|
|
|
16
19
|
function isWindows() {
|
|
17
20
|
return process.platform === "win32";
|
|
@@ -83,6 +86,139 @@ function runCapture(command, args) {
|
|
|
83
86
|
};
|
|
84
87
|
}
|
|
85
88
|
|
|
89
|
+
function parseVersionTriplet(version) {
|
|
90
|
+
const text = String(version || "").trim();
|
|
91
|
+
const [core] = text.split("-");
|
|
92
|
+
const pieces = core.split(".");
|
|
93
|
+
const numbers = [];
|
|
94
|
+
for (let index = 0; index < 3; index += 1) {
|
|
95
|
+
const value = Number.parseInt(pieces[index] || "0", 10);
|
|
96
|
+
numbers.push(Number.isFinite(value) ? value : 0);
|
|
97
|
+
}
|
|
98
|
+
return numbers;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function compareVersions(left, right) {
|
|
102
|
+
const lhs = parseVersionTriplet(left);
|
|
103
|
+
const rhs = parseVersionTriplet(right);
|
|
104
|
+
for (let index = 0; index < 3; index += 1) {
|
|
105
|
+
if (lhs[index] > rhs[index]) {
|
|
106
|
+
return 1;
|
|
107
|
+
}
|
|
108
|
+
if (lhs[index] < rhs[index]) {
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function fetchJson(url, timeoutMs = 2500) {
|
|
116
|
+
return new Promise((resolve) => {
|
|
117
|
+
const request = https.get(
|
|
118
|
+
url,
|
|
119
|
+
{
|
|
120
|
+
headers: {
|
|
121
|
+
"User-Agent": "pf-gate-cli",
|
|
122
|
+
Accept: "application/json",
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
(response) => {
|
|
126
|
+
let body = "";
|
|
127
|
+
response.on("data", (chunk) => {
|
|
128
|
+
body += String(chunk);
|
|
129
|
+
});
|
|
130
|
+
response.on("end", () => {
|
|
131
|
+
if ((response.statusCode || 500) >= 400) {
|
|
132
|
+
resolve(null);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
resolve(JSON.parse(body));
|
|
137
|
+
} catch (_error) {
|
|
138
|
+
resolve(null);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
request.setTimeout(timeoutMs, () => {
|
|
144
|
+
request.destroy(new Error("timeout"));
|
|
145
|
+
resolve(null);
|
|
146
|
+
});
|
|
147
|
+
request.on("error", () => resolve(null));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function fetchLatestVersion(packageName) {
|
|
152
|
+
const encoded = encodeURIComponent(packageName);
|
|
153
|
+
const url = `${NPM_REGISTRY}/-/package/${encoded}/dist-tags`;
|
|
154
|
+
const payload = await fetchJson(url);
|
|
155
|
+
if (!payload || typeof payload !== "object") {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const latest = String(payload.latest || "").trim();
|
|
159
|
+
if (!latest) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return latest;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function canPrompt() {
|
|
166
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function promptYesNo(question, defaultYes = true) {
|
|
170
|
+
if (!canPrompt()) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
const prompt = defaultYes ? `${question} [Y/n] ` : `${question} [y/N] `;
|
|
174
|
+
const rl = readline.createInterface({
|
|
175
|
+
input: process.stdin,
|
|
176
|
+
output: process.stdout,
|
|
177
|
+
});
|
|
178
|
+
try {
|
|
179
|
+
const answer = (await rl.question(prompt)).trim().toLowerCase();
|
|
180
|
+
if (!answer) {
|
|
181
|
+
return defaultYes;
|
|
182
|
+
}
|
|
183
|
+
return answer === "y" || answer === "yes";
|
|
184
|
+
} finally {
|
|
185
|
+
rl.close();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function maybeOfferCliUpdate(metadata) {
|
|
190
|
+
if (String(process.env.PF_GATE_DISABLE_UPDATE_CHECK || "").trim() === "1") {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
const latestVersion = await fetchLatestVersion(metadata.name);
|
|
194
|
+
if (!latestVersion) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
if (compareVersions(latestVersion, metadata.version) <= 0) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
console.log(
|
|
201
|
+
`Update available: ${metadata.name} ${metadata.version} -> ${latestVersion}`
|
|
202
|
+
);
|
|
203
|
+
const wantsUpdate = await promptYesNo("Install update now?", true);
|
|
204
|
+
if (!wantsUpdate) {
|
|
205
|
+
console.log(`Continue with ${metadata.version}.`);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
console.log(`Updating ${metadata.name}...`);
|
|
209
|
+
const result = spawnSync(
|
|
210
|
+
"npm",
|
|
211
|
+
["i", "-g", `${metadata.name}@latest`, "--registry", NPM_REGISTRY],
|
|
212
|
+
{ stdio: "inherit" }
|
|
213
|
+
);
|
|
214
|
+
if (result.error || (result.status ?? 1) !== 0) {
|
|
215
|
+
console.log("Update failed. Continuing with current version.");
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
console.log("Update installed. Restart PF Gate to use the new version.");
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
|
|
86
222
|
function resolvePython() {
|
|
87
223
|
const envPython = (process.env.PF_GATE_PYTHON || "").trim();
|
|
88
224
|
const candidates = envPython ? [envPython, ...PYTHON_CANDIDATES] : PYTHON_CANDIDATES;
|
|
@@ -213,6 +349,7 @@ function installRuntime(runtimeRoot, source, cliVersion) {
|
|
|
213
349
|
...runtimePipArgs(runtimeRoot),
|
|
214
350
|
"install",
|
|
215
351
|
"--upgrade",
|
|
352
|
+
"--force-reinstall",
|
|
216
353
|
source.wheelPath,
|
|
217
354
|
]);
|
|
218
355
|
} else {
|
|
@@ -261,6 +398,10 @@ export async function runCli(args) {
|
|
|
261
398
|
console.log(`args: ${JSON.stringify(args)}`);
|
|
262
399
|
return;
|
|
263
400
|
}
|
|
401
|
+
const updated = await maybeOfferCliUpdate(metadata);
|
|
402
|
+
if (updated) {
|
|
403
|
+
process.exit(0);
|
|
404
|
+
}
|
|
264
405
|
const runtimeRoot = ensureRuntimeInstalled(metadata.version);
|
|
265
406
|
const pythonPath = runtimePythonPath(runtimeRoot);
|
|
266
407
|
const resolvedArgs = args.length === 0 ? ["Gate"] : args;
|