@robineb/project-cli 1.0.1 → 1.1.0
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/dist/index.js +32 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -95,7 +95,10 @@ async function ask(message) {
|
|
|
95
95
|
return answer;
|
|
96
96
|
}
|
|
97
97
|
async function askText(message) {
|
|
98
|
-
const answer = await p.text({
|
|
98
|
+
const answer = await p.text({
|
|
99
|
+
message,
|
|
100
|
+
validate: (value) => (value?.trim() ? undefined : "Darf nicht leer sein."),
|
|
101
|
+
});
|
|
99
102
|
if (p.isCancel(answer))
|
|
100
103
|
throw new Error("Abgebrochen.");
|
|
101
104
|
return answer;
|
|
@@ -109,12 +112,14 @@ async function resolveGitHubToken() {
|
|
|
109
112
|
return token;
|
|
110
113
|
}
|
|
111
114
|
async function resolveGiteaCredentials() {
|
|
112
|
-
|
|
115
|
+
// Leerer String zählt als "nicht vorhanden" (z.B. ein früherer Lauf hat
|
|
116
|
+
// versehentlich "" gespeichert) -> nicht nur auf null/undefined prüfen.
|
|
117
|
+
const existingUrl = process.env.GITEA_URL || config.get("giteaUrl") || undefined;
|
|
113
118
|
const baseUrl = existingUrl ??
|
|
114
119
|
(await askText("Gitea-URL (z.B. https://gitea.example.com)"));
|
|
115
120
|
if (!existingUrl)
|
|
116
121
|
config.set("giteaUrl", baseUrl);
|
|
117
|
-
const existingToken = process.env.GITEA_TOKEN
|
|
122
|
+
const existingToken = process.env.GITEA_TOKEN || getStoredSecret("gitea-token") || undefined;
|
|
118
123
|
const token = existingToken ?? (await ask("Gitea Access Token (write:repository-Scope)"));
|
|
119
124
|
if (!existingToken)
|
|
120
125
|
setStoredSecret("gitea-token", token);
|
|
@@ -123,6 +128,19 @@ async function resolveGiteaCredentials() {
|
|
|
123
128
|
// ---------------------------------------------------------------------------
|
|
124
129
|
// 3. Die einzelnen Arbeitsschritte
|
|
125
130
|
// ---------------------------------------------------------------------------
|
|
131
|
+
// Deckt sowohl Gitea (Regel "AlphaDashDot") als auch GitHub ab: nur
|
|
132
|
+
// alphanumerische Zeichen, "-", "_" und ".", muss mit alphanumerisch
|
|
133
|
+
// beginnen und enden. Leerzeichen wie in "esp 32" fallen damit sofort auf,
|
|
134
|
+
// statt erst nach Scaffold + erstem Commit bei der Remote-Erstellung.
|
|
135
|
+
const PROJECT_NAME_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
136
|
+
function validateProjectName(name) {
|
|
137
|
+
if (!name?.trim())
|
|
138
|
+
return "Name darf nicht leer sein";
|
|
139
|
+
if (!PROJECT_NAME_PATTERN.test(name)) {
|
|
140
|
+
return "Name darf nur Buchstaben, Ziffern, '-', '_' und '.' enthalten (muss mit Buchstabe/Ziffer beginnen und enden)";
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
126
144
|
async function scaffold(stack, targetDir, name) {
|
|
127
145
|
if (stack.command) {
|
|
128
146
|
const { file, args } = stack.command(name);
|
|
@@ -254,10 +272,20 @@ async function run(nameArg, opts) {
|
|
|
254
272
|
const name = nameArg ??
|
|
255
273
|
(await p.text({
|
|
256
274
|
message: "Wie soll das Projekt heißen?",
|
|
257
|
-
validate: (v) => (v
|
|
275
|
+
validate: (v) => validateProjectName(v),
|
|
258
276
|
}));
|
|
259
277
|
if (p.isCancel(name))
|
|
260
278
|
return p.cancel("Abgebrochen.");
|
|
279
|
+
// nameArg kommt am Prompt vorbei (CLI-Argument statt p.text) -> hier
|
|
280
|
+
// nochmal prüfen. Sonst scheitert erst die Remote-Erstellung nach
|
|
281
|
+
// Scaffold + erstem Commit (Gitea/GitHub lehnen z.B. Leerzeichen im
|
|
282
|
+
// Namen mit "AlphaDashDot" bzw. 422 ab), und die lokale Arbeit ist
|
|
283
|
+
// bereits passiert, ohne dass ein Remote konfiguriert wurde.
|
|
284
|
+
const nameError = validateProjectName(name);
|
|
285
|
+
if (nameError) {
|
|
286
|
+
p.cancel(nameError);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
261
289
|
const stackId = await p.select({
|
|
262
290
|
message: "Welcher Stack?",
|
|
263
291
|
options: STACKS.map((s) => ({ value: s.id, label: s.label })),
|