@suronai/cli 0.1.34 → 0.1.35
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 +1 -1
- package/src/commands/init.js +17 -6
- package/src/commands/recover.js +18 -5
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { existsSync, writeFileSync, readFileSync } from "fs";
|
|
3
|
-
import { join, basename } from "path";
|
|
3
|
+
import { join, basename, relative } from "path";
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
5
|
import { requireApiUrl, prompt } from "../utils/config.js";
|
|
6
6
|
import { encryptDotenv, readPrivateKey } from "../utils/dotenvx.js";
|
|
@@ -30,7 +30,8 @@ export const initCommand = new Command("init")
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// ── App name ──────────────────────────────────────────────────────────────
|
|
33
|
-
|
|
33
|
+
// Preserve the folder's original casing as the default suggestion.
|
|
34
|
+
const suggested = sanitiseName(basename(cwd) || "myapp");
|
|
34
35
|
let appName;
|
|
35
36
|
|
|
36
37
|
if (opts.name) {
|
|
@@ -40,6 +41,12 @@ export const initCommand = new Command("init")
|
|
|
40
41
|
appName = sanitiseName(raw || suggested);
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
if (!appName) {
|
|
45
|
+
console.error(" " + c.red("✗") + " App name is required and must contain at least one letter or digit.");
|
|
46
|
+
console.error(" Example: suron init --name MyApp\n");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
console.log(" App name " + c.dim("·") + " " + c.cyan(appName));
|
|
44
51
|
console.log(HR);
|
|
45
52
|
|
|
@@ -118,8 +125,9 @@ export const initCommand = new Command("init")
|
|
|
118
125
|
printSteps();
|
|
119
126
|
console.log(HR);
|
|
120
127
|
if (res.status === 409) {
|
|
121
|
-
|
|
122
|
-
console.error("
|
|
128
|
+
const canonical = body?.existing_name ?? appName;
|
|
129
|
+
console.error("\n " + c.red("✗") + ` An app named "${c.cyan(String(canonical))}" is already registered (case-insensitive match).`);
|
|
130
|
+
console.error(" If you lost .suron.json, run: " + c.bold("suron recover --name " + String(canonical)) + "\n");
|
|
123
131
|
} else {
|
|
124
132
|
console.error("\n " + c.red("✗") + ` ${body?.error ?? `register-app failed (${res.status})`}\n`);
|
|
125
133
|
}
|
|
@@ -225,11 +233,14 @@ function pmAddCmd(pm) {
|
|
|
225
233
|
}
|
|
226
234
|
|
|
227
235
|
/**
|
|
236
|
+
* Strips everything except letters and digits while preserving the original case.
|
|
237
|
+
* The backend stores names case-sensitively for display but compares lowercase
|
|
238
|
+
* for uniqueness, so "DataHaven" and "datahaven" are the same app.
|
|
228
239
|
* @param {string} name
|
|
229
240
|
* @returns {string}
|
|
230
241
|
*/
|
|
231
242
|
function sanitiseName(name) {
|
|
232
|
-
return name.
|
|
243
|
+
return name.replace(/[^a-zA-Z0-9]/g, "");
|
|
233
244
|
}
|
|
234
245
|
|
|
235
246
|
/**
|
|
@@ -309,7 +320,7 @@ async function patchEntryPoint(cwd, isEsm) {
|
|
|
309
320
|
return;
|
|
310
321
|
}
|
|
311
322
|
|
|
312
|
-
const relEntry =
|
|
323
|
+
const relEntry = relative(cwd, entryPath);
|
|
313
324
|
|
|
314
325
|
// ── Diff preview ───────────────────────────────────────────────────────────
|
|
315
326
|
console.log(" " + c.dim("▎"));
|
package/src/commands/recover.js
CHANGED
|
@@ -23,18 +23,21 @@ export const recoverCommand = new Command("recover")
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// ── App name ──────────────────────────────────────────────────────────────
|
|
26
|
+
// Names are case-insensitive for lookup — "datahaven" finds "DataHaven".
|
|
27
|
+
// We preserve the input casing here; the backend returns the canonical name.
|
|
26
28
|
let appName;
|
|
27
29
|
if (opts.name) {
|
|
28
|
-
|
|
30
|
+
// Strip non-alphanumeric but preserve case — backend does case-insensitive match.
|
|
31
|
+
appName = opts.name.replace(/[^a-zA-Z0-9]/g, "");
|
|
29
32
|
console.log(" App name " + c.cyan(appName));
|
|
30
33
|
} else {
|
|
31
|
-
const suggested = basename(cwd) || "
|
|
34
|
+
const suggested = sanitiseName(basename(cwd) || "myapp");
|
|
32
35
|
const raw = await prompt(` App name [${c.dim(suggested)}] › `);
|
|
33
|
-
appName = (raw || suggested)
|
|
36
|
+
appName = sanitiseName(raw || suggested);
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
if (!appName) {
|
|
37
|
-
console.error(" " + c.red("✗") + " App name is required.\n");
|
|
40
|
+
console.error(" " + c.red("✗") + " App name is required and must contain at least one letter or digit.\n");
|
|
38
41
|
process.exit(1);
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -58,7 +61,7 @@ export const recoverCommand = new Command("recover")
|
|
|
58
61
|
try { body = await res.json(); } catch { /* ignore */ }
|
|
59
62
|
if (res.status === 404) {
|
|
60
63
|
console.error("\n " + c.red("✗") + ` No app named "${c.cyan(appName)}" found.`);
|
|
61
|
-
console.error("
|
|
64
|
+
console.error(" Lookup is case-insensitive — check spelling (letters and numbers only).\n");
|
|
62
65
|
} else {
|
|
63
66
|
console.error("\n " + c.red("✗") + ` ${body?.error ?? `recover-app failed (${res.status})`}\n`);
|
|
64
67
|
}
|
|
@@ -68,6 +71,7 @@ export const recoverCommand = new Command("recover")
|
|
|
68
71
|
const { app_id, name } = await res.json();
|
|
69
72
|
|
|
70
73
|
// ── Write .suron.json ─────────────────────────────────────────────────────
|
|
74
|
+
// Use the canonical name returned by the server (original registration casing).
|
|
71
75
|
writeFileSync(
|
|
72
76
|
join(cwd, ".suron.json"),
|
|
73
77
|
JSON.stringify({ app: name, id: app_id, api_url: apiUrl }, null, 2) + "\n",
|
|
@@ -80,3 +84,12 @@ export const recoverCommand = new Command("recover")
|
|
|
80
84
|
console.log(" " + c.dim(" id: ") + c.cyan(app_id));
|
|
81
85
|
console.log();
|
|
82
86
|
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Strips non-alphanumeric characters while preserving case.
|
|
90
|
+
* @param {string} name
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
93
|
+
function sanitiseName(name) {
|
|
94
|
+
return name.replace(/[^a-zA-Z0-9]/g, "");
|
|
95
|
+
}
|