@uetuluk/create-cli 0.0.1 → 0.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.
- package/dist/cli.js +59 -17
- package/package.json +52 -47
package/dist/cli.js
CHANGED
|
@@ -101,6 +101,33 @@ function requireAuth() {
|
|
|
101
101
|
}
|
|
102
102
|
return c;
|
|
103
103
|
}
|
|
104
|
+
async function apiAuth(path, init = {}) {
|
|
105
|
+
const creds = requireAuth();
|
|
106
|
+
const url = init.server ?? creds.serverUrl;
|
|
107
|
+
const { server, ...rest } = init;
|
|
108
|
+
try {
|
|
109
|
+
return await api(url, path, { ...rest, token: creds.token });
|
|
110
|
+
} catch (e) {
|
|
111
|
+
if (!(e instanceof ApiError) || e.status !== 401 || !creds.refreshToken) throw e;
|
|
112
|
+
let refreshed;
|
|
113
|
+
try {
|
|
114
|
+
refreshed = await api(url, "/auth/refresh-token", {
|
|
115
|
+
method: "POST",
|
|
116
|
+
body: JSON.stringify({ refresh_token: creds.refreshToken })
|
|
117
|
+
});
|
|
118
|
+
} catch {
|
|
119
|
+
throw e;
|
|
120
|
+
}
|
|
121
|
+
if (url === creds.serverUrl) {
|
|
122
|
+
saveCredentials({
|
|
123
|
+
...creds,
|
|
124
|
+
token: refreshed.token,
|
|
125
|
+
refreshToken: refreshed.refresh_token
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return await api(url, path, { ...rest, token: refreshed.token });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
104
131
|
function wrap(fn) {
|
|
105
132
|
return async (...args) => {
|
|
106
133
|
try {
|
|
@@ -109,7 +136,15 @@ function wrap(fn) {
|
|
|
109
136
|
if (e instanceof ApiError) {
|
|
110
137
|
console.error(colors.red(`${e.status} ${e.message}`));
|
|
111
138
|
} else {
|
|
112
|
-
|
|
139
|
+
const err = e;
|
|
140
|
+
let msg = err.message || String(e);
|
|
141
|
+
if (msg === "fetch failed" && err.cause) {
|
|
142
|
+
const cause = err.cause;
|
|
143
|
+
const code = cause.code ? ` [${cause.code}]` : "";
|
|
144
|
+
msg = `fetch failed: ${cause.message ?? cause}${code}`;
|
|
145
|
+
}
|
|
146
|
+
console.error(colors.red(msg));
|
|
147
|
+
if (process.env.TEENY_DEBUG) console.error(err.stack ?? err);
|
|
113
148
|
}
|
|
114
149
|
process.exit(1);
|
|
115
150
|
}
|
|
@@ -168,19 +203,15 @@ cli.command("whoami", "show current user").action(wrap(async () => {
|
|
|
168
203
|
cli.command("create", "provision a new instance").action(wrap(async (opts) => {
|
|
169
204
|
const c = requireAuth();
|
|
170
205
|
const url = opts.server ? serverUrl(opts) : c.serverUrl;
|
|
171
|
-
const r = await
|
|
172
|
-
method: "POST",
|
|
173
|
-
token: c.token
|
|
174
|
-
});
|
|
206
|
+
const r = await apiAuth("/platform/instances", { method: "POST" });
|
|
175
207
|
saveInstance({ name: r.name, url: r.url, adminToken: r.admin_token, serverUrl: url });
|
|
176
208
|
console.log(colors.green(`created ${colors.bold(r.name)}`));
|
|
177
209
|
console.log(` url: ${r.url}`);
|
|
178
210
|
console.log(` admin token saved to local store (only shown once)`);
|
|
179
211
|
}));
|
|
180
212
|
cli.command("list", "list your instances").action(wrap(async (opts) => {
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
const r = await api(url, "/platform/instances", { token: c.token });
|
|
213
|
+
const url = opts.server ? serverUrl(opts) : void 0;
|
|
214
|
+
const r = await apiAuth("/platform/instances", { server: url });
|
|
184
215
|
if (!r.result.length) {
|
|
185
216
|
console.log("no instances. run `teeny create`");
|
|
186
217
|
return;
|
|
@@ -191,16 +222,14 @@ cli.command("list", "list your instances").action(wrap(async (opts) => {
|
|
|
191
222
|
}
|
|
192
223
|
}));
|
|
193
224
|
cli.command("status <name>", "show instance details").action(wrap(async (name, opts) => {
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const r = await api(url, `/platform/instances/${encodeURIComponent(name)}`, { token: c.token });
|
|
225
|
+
const url = opts.server ? serverUrl(opts) : void 0;
|
|
226
|
+
const r = await apiAuth(`/platform/instances/${encodeURIComponent(name)}`, { server: url });
|
|
197
227
|
console.log(colors.bold(r.result.name));
|
|
198
228
|
console.log(` url: ${r.result.url}`);
|
|
199
229
|
console.log(` created: ${r.result.created_at}`);
|
|
200
230
|
}));
|
|
201
231
|
cli.command("delete <name>", "tear down an instance").option("-y, --yes", "[boolean] skip confirmation").action(wrap(async (name, opts) => {
|
|
202
|
-
const
|
|
203
|
-
const url = opts.server ? serverUrl(opts) : c.serverUrl;
|
|
232
|
+
const url = opts.server ? serverUrl(opts) : void 0;
|
|
204
233
|
if (!opts.yes) {
|
|
205
234
|
const r = await prompts({ type: "confirm", name: "v", message: `delete ${name}? this is permanent`, initial: false });
|
|
206
235
|
if (!r.v) {
|
|
@@ -208,7 +237,7 @@ cli.command("delete <name>", "tear down an instance").option("-y, --yes", "[bool
|
|
|
208
237
|
return;
|
|
209
238
|
}
|
|
210
239
|
}
|
|
211
|
-
await
|
|
240
|
+
await apiAuth(`/platform/instances/${encodeURIComponent(name)}`, { method: "DELETE", server: url });
|
|
212
241
|
deleteInstance(name);
|
|
213
242
|
console.log(colors.green(`deleted ${name}`));
|
|
214
243
|
}));
|
|
@@ -245,9 +274,22 @@ cli.command("logs <name>", "stream live logs from an instance").option("--tail <
|
|
|
245
274
|
const c = requireAuth();
|
|
246
275
|
const url = opts.server ? serverUrl(opts) : c.serverUrl;
|
|
247
276
|
const tail = opts.tail || "200";
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
277
|
+
const streamUrl = `${url}/platform/instances/${encodeURIComponent(name)}/logs?tail=${tail}`;
|
|
278
|
+
const open = (token) => fetch(streamUrl, { headers: { authorization: `Bearer ${token}` } });
|
|
279
|
+
let res = await open(c.token);
|
|
280
|
+
if (res.status === 401 && c.refreshToken) {
|
|
281
|
+
try {
|
|
282
|
+
const refreshed = await api(url, "/auth/refresh-token", {
|
|
283
|
+
method: "POST",
|
|
284
|
+
body: JSON.stringify({ refresh_token: c.refreshToken })
|
|
285
|
+
});
|
|
286
|
+
if (url === c.serverUrl) {
|
|
287
|
+
saveCredentials({ ...c, token: refreshed.token, refreshToken: refreshed.refresh_token });
|
|
288
|
+
}
|
|
289
|
+
res = await open(refreshed.token);
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
}
|
|
251
293
|
if (!res.ok || !res.body) {
|
|
252
294
|
console.error(colors.red(`failed to stream: ${res.status}`));
|
|
253
295
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,49 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
2
|
+
"name": "@uetuluk/create-cli",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "CLI for the create.ritsdev.top platform — register, provision, and deploy teenybase instances.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"teeny": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=20"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"teenybase",
|
|
21
|
+
"platform",
|
|
22
|
+
"cli",
|
|
23
|
+
"ritsdev"
|
|
24
|
+
],
|
|
25
|
+
"author": "uetuluk",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/uetuluk/create-ritsdev-platform.git",
|
|
30
|
+
"directory": "cli"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/uetuluk/create-ritsdev-platform/tree/main/cli#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/uetuluk/create-ritsdev-platform/issues"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "esbuild src/cli.ts --bundle --outfile=dist/cli.js --platform=node --format=esm --packages=external --banner:js=\"#!/usr/bin/env node\" && chmod +x dist/cli.js",
|
|
38
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
39
|
+
"dev": "tsx src/cli.ts",
|
|
40
|
+
"prepublishOnly": "npm run check && npm run build"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"cac": "^6.7.14",
|
|
44
|
+
"picocolors": "^1.1.1",
|
|
45
|
+
"prompts": "^2.4.2"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"@types/prompts": "^2.4.9",
|
|
50
|
+
"esbuild": "^0.24.0",
|
|
51
|
+
"tsx": "^4.19.0",
|
|
52
|
+
"typescript": "^5.6.0"
|
|
53
|
+
}
|
|
49
54
|
}
|