onflyt-cli 1.0.1-beta.1 → 1.0.1-beta.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.
Potentially problematic release.
This version of onflyt-cli might be problematic. Click here for more details.
- package/dist/App.d.ts +3 -0
- package/dist/App.js +8 -0
- package/dist/commands/credits.d.ts +3 -0
- package/dist/commands/credits.js +101 -0
- package/dist/commands/delete.d.ts +7 -0
- package/dist/commands/delete.js +220 -0
- package/dist/commands/deploy.d.ts +6 -0
- package/dist/commands/deploy.js +715 -0
- package/dist/commands/deployments.d.ts +6 -0
- package/dist/commands/deployments.js +225 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.js +76 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.js +422 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.js +150 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.js +19 -0
- package/dist/commands/logs.d.ts +7 -0
- package/dist/commands/logs.js +307 -0
- package/dist/commands/projects.d.ts +3 -0
- package/dist/commands/projects.js +203 -0
- package/dist/commands/rollback.d.ts +6 -0
- package/dist/commands/rollback.js +316 -0
- package/dist/commands/teams.d.ts +3 -0
- package/dist/commands/teams.js +81 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.js +34 -0
- package/dist/components/Loading.d.ts +13 -0
- package/dist/components/Loading.js +42 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +107 -442
- package/dist/lib/api.d.ts +27 -0
- package/dist/lib/api.js +109 -0
- package/dist/lib/config.d.ts +32 -0
- package/dist/lib/config.js +52 -0
- package/dist/lib/deploy-api.d.ts +97 -0
- package/dist/lib/deploy-api.js +335 -0
- package/dist/lib/deploy.d.ts +36 -0
- package/dist/lib/deploy.js +181 -0
- package/dist/lib/framework.d.ts +27 -0
- package/dist/lib/framework.js +184 -0
- package/dist/lib/git.d.ts +25 -0
- package/dist/lib/git.js +149 -0
- package/dist/lib/scaffold.d.ts +21 -0
- package/dist/lib/scaffold.js +190 -0
- package/dist/shared/frameworks/registry.d.ts +21 -0
- package/dist/shared/frameworks/registry.js +196 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/limits.d.ts +16 -0
- package/dist/shared/limits.js +44 -0
- package/dist/shared/pricing.d.ts +2 -0
- package/dist/shared/pricing.js +7 -0
- package/dist/shared/templates/registry.d.ts +9 -0
- package/dist/shared/templates/registry.js +47 -0
- package/onflyt.json +10 -0
- package/package.json +5 -7
- package/src/App.tsx +13 -0
- package/src/commands/credits.tsx +151 -0
- package/src/commands/delete.tsx +315 -0
- package/src/commands/deploy.tsx +1039 -0
- package/src/commands/deployments.tsx +331 -0
- package/src/commands/help.tsx +79 -0
- package/src/commands/init.tsx +587 -0
- package/src/commands/login.tsx +207 -0
- package/src/commands/logout.tsx +31 -0
- package/src/commands/logs.tsx +447 -0
- package/src/commands/projects.tsx +287 -0
- package/src/commands/rollback.tsx +455 -0
- package/src/commands/teams.tsx +113 -0
- package/src/commands/whoami.tsx +48 -0
- package/src/components/Loading.tsx +74 -0
- package/src/index.tsx +130 -0
- package/src/lib/api.ts +152 -0
- package/src/lib/config.ts +90 -0
- package/src/lib/deploy-api.ts +511 -0
- package/src/lib/deploy.ts +260 -0
- package/src/lib/framework.ts +227 -0
- package/src/lib/git.ts +179 -0
- package/src/lib/scaffold.ts +225 -0
- package/src/lib/shared.ts +350 -0
- package/src/types.d.ts +5 -0
- package/tsconfig.json +17 -0
- package/README.md +0 -338
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { Text, Box, useInput } from "ink";
|
|
3
|
+
import { isLoggedIn, getConfig } from "../lib/config.js";
|
|
4
|
+
import { api } from "../lib/api.js";
|
|
5
|
+
import { Logo } from "../components/Loading.js";
|
|
6
|
+
import Spinner from "ink-spinner";
|
|
7
|
+
const Rollback = ({ deploymentId }) => {
|
|
8
|
+
const [step, setStep] = useState("loading");
|
|
9
|
+
const [teams, setTeams] = useState([]);
|
|
10
|
+
const [projects, setProjects] = useState([]);
|
|
11
|
+
const [deployments, setDeployments] = useState([]);
|
|
12
|
+
const [selectedTeamIndex, setSelectedTeamIndex] = useState(0);
|
|
13
|
+
const [selectedProjectIndex, setSelectedProjectIndex] = useState(0);
|
|
14
|
+
const [selectedDeployIndex, setSelectedDeployIndex] = useState(0);
|
|
15
|
+
const [targetProject, setTargetProject] = useState(null);
|
|
16
|
+
const [targetDeployment, setTargetDeployment] = useState(null);
|
|
17
|
+
const [errorMsg, setErrorMsg] = useState("");
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const handleSigInt = () => process.exit(0);
|
|
20
|
+
process.on("SIGINT", handleSigInt);
|
|
21
|
+
return () => {
|
|
22
|
+
process.off("SIGINT", handleSigInt);
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (step === "done" || step === "error") {
|
|
27
|
+
const timer = setTimeout(() => process.exit(0), 500);
|
|
28
|
+
return () => clearTimeout(timer);
|
|
29
|
+
}
|
|
30
|
+
}, [step]);
|
|
31
|
+
useInput((input, key) => {
|
|
32
|
+
if (input === "q" || input === "Q" || (key.ctrl && input === "c")) {
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
if (step === "team") {
|
|
36
|
+
if (key.upArrow) {
|
|
37
|
+
setSelectedTeamIndex((i) => Math.max(0, i - 1));
|
|
38
|
+
}
|
|
39
|
+
else if (key.downArrow) {
|
|
40
|
+
setSelectedTeamIndex((i) => Math.min(teams.length - 1, i + 1));
|
|
41
|
+
}
|
|
42
|
+
else if (key.return) {
|
|
43
|
+
setStep("loading-projects");
|
|
44
|
+
loadProjects(teams[selectedTeamIndex].team.id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (step === "project") {
|
|
48
|
+
if (key.upArrow) {
|
|
49
|
+
setSelectedProjectIndex((i) => Math.max(0, i - 1));
|
|
50
|
+
}
|
|
51
|
+
else if (key.downArrow) {
|
|
52
|
+
setSelectedProjectIndex((i) => Math.min(projects.length - 1, i + 1));
|
|
53
|
+
}
|
|
54
|
+
else if (key.return) {
|
|
55
|
+
setStep("loading-deployments");
|
|
56
|
+
loadDeploymentsForProject(projects[selectedProjectIndex]);
|
|
57
|
+
}
|
|
58
|
+
else if (key.escape) {
|
|
59
|
+
setStep("team");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (step === "deploy") {
|
|
63
|
+
if (key.upArrow) {
|
|
64
|
+
setSelectedDeployIndex((i) => Math.max(0, i - 1));
|
|
65
|
+
}
|
|
66
|
+
else if (key.downArrow) {
|
|
67
|
+
setSelectedDeployIndex((i) => Math.min(deployments.length - 1, i + 1));
|
|
68
|
+
}
|
|
69
|
+
else if (key.return) {
|
|
70
|
+
setTargetDeployment(deployments[selectedDeployIndex]);
|
|
71
|
+
setStep("confirm");
|
|
72
|
+
}
|
|
73
|
+
else if (key.escape) {
|
|
74
|
+
setStep("project");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (step === "confirm") {
|
|
78
|
+
if (input === "y" || input === "Y" || key.return) {
|
|
79
|
+
performRollback(targetDeployment.id, targetProject.id);
|
|
80
|
+
}
|
|
81
|
+
else if (input === "n" || input === "N" || key.escape) {
|
|
82
|
+
setStep("deploy");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (!isLoggedIn()) {
|
|
88
|
+
setErrorMsg("Not logged in. Run 'onflyt login' first.");
|
|
89
|
+
setStep("error");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (deploymentId) {
|
|
93
|
+
setErrorMsg("Direct deployment rollback not yet supported. Please select from list.");
|
|
94
|
+
setStep("error");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
loadTeams();
|
|
98
|
+
}, []);
|
|
99
|
+
const loadTeams = async () => {
|
|
100
|
+
try {
|
|
101
|
+
const config = getConfig();
|
|
102
|
+
api.setToken(config.token);
|
|
103
|
+
const meData = await api.get("/auth/me");
|
|
104
|
+
const userTeams = meData.teams || [];
|
|
105
|
+
if (userTeams.length === 0) {
|
|
106
|
+
setErrorMsg("No teams found");
|
|
107
|
+
setStep("error");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
setTeams(userTeams);
|
|
111
|
+
if (userTeams.length === 1) {
|
|
112
|
+
setSelectedTeamIndex(0);
|
|
113
|
+
setStep("loading-projects");
|
|
114
|
+
loadProjects(userTeams[0].team.id);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
setStep("team");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
setErrorMsg(err.message);
|
|
122
|
+
setStep("error");
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const loadProjects = async (teamId) => {
|
|
126
|
+
try {
|
|
127
|
+
const projectsRes = await api.get(`/projects/team/${teamId}`);
|
|
128
|
+
const teamProjects = projectsRes.projects || [];
|
|
129
|
+
if (teamProjects.length === 0) {
|
|
130
|
+
setErrorMsg("No projects found in this team");
|
|
131
|
+
setStep("error");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
setProjects(teamProjects);
|
|
135
|
+
setSelectedProjectIndex(0);
|
|
136
|
+
setStep("project");
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
setErrorMsg(err.message);
|
|
140
|
+
setStep("error");
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const loadDeploymentsForProject = async (project) => {
|
|
144
|
+
try {
|
|
145
|
+
setTargetProject(project);
|
|
146
|
+
const depsRes = await api.get(`/deployments/${project.id}?limit=50`);
|
|
147
|
+
const allDeployments = depsRes.deployments || [];
|
|
148
|
+
if (allDeployments.length === 0) {
|
|
149
|
+
setErrorMsg("No deployments found for this project");
|
|
150
|
+
setStep("error");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
setDeployments(allDeployments);
|
|
154
|
+
setSelectedDeployIndex(0);
|
|
155
|
+
setStep("deploy");
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
setErrorMsg(err.message);
|
|
159
|
+
setStep("error");
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const performRollback = async (depId, projectId) => {
|
|
163
|
+
setStep("rolling");
|
|
164
|
+
try {
|
|
165
|
+
await api.post(`/deployments/${projectId}/${depId}/activate`);
|
|
166
|
+
setStep("done");
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
setErrorMsg(err.message);
|
|
170
|
+
setStep("error");
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
if (step === "loading") {
|
|
174
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
175
|
+
React.createElement(Logo, null),
|
|
176
|
+
React.createElement(Box, { marginTop: 1 },
|
|
177
|
+
React.createElement(Text, null, "Loading..."))));
|
|
178
|
+
}
|
|
179
|
+
if (step === "loading-projects") {
|
|
180
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
181
|
+
React.createElement(Logo, null),
|
|
182
|
+
React.createElement(Box, { marginTop: 1 },
|
|
183
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
184
|
+
React.createElement(Box, { marginTop: 1 },
|
|
185
|
+
React.createElement(Text, { dimColor: true }, "Loading projects...")),
|
|
186
|
+
React.createElement(Box, { marginTop: 1 },
|
|
187
|
+
React.createElement(Spinner, null))));
|
|
188
|
+
}
|
|
189
|
+
if (step === "loading-deployments") {
|
|
190
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
191
|
+
React.createElement(Logo, null),
|
|
192
|
+
React.createElement(Box, { marginTop: 1 },
|
|
193
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
194
|
+
React.createElement(Box, { marginTop: 1 },
|
|
195
|
+
React.createElement(Text, { dimColor: true }, "Loading deployments...")),
|
|
196
|
+
React.createElement(Box, { marginTop: 1 },
|
|
197
|
+
React.createElement(Spinner, null))));
|
|
198
|
+
}
|
|
199
|
+
if (step === "error") {
|
|
200
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
201
|
+
React.createElement(Logo, null),
|
|
202
|
+
React.createElement(Box, { marginTop: 1 },
|
|
203
|
+
React.createElement(Text, { bold: true, color: "red" }, "\u2716 Error")),
|
|
204
|
+
React.createElement(Box, { marginTop: 1 },
|
|
205
|
+
React.createElement(Text, { color: "red" }, errorMsg))));
|
|
206
|
+
}
|
|
207
|
+
if (step === "rolling") {
|
|
208
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
209
|
+
React.createElement(Logo, null),
|
|
210
|
+
React.createElement(Box, { marginTop: 1 },
|
|
211
|
+
React.createElement(Text, null, "Rolling back deployment..."))));
|
|
212
|
+
}
|
|
213
|
+
if (step === "done") {
|
|
214
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
215
|
+
React.createElement(Logo, null),
|
|
216
|
+
React.createElement(Box, { marginTop: 1 },
|
|
217
|
+
React.createElement(Text, { bold: true, color: "green" }, "\u2713 Rollback successful")),
|
|
218
|
+
React.createElement(Box, { marginTop: 1 },
|
|
219
|
+
React.createElement(Text, { dimColor: true }, "Run 'onflyt logs' to monitor progress"))));
|
|
220
|
+
}
|
|
221
|
+
if (step === "team") {
|
|
222
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
223
|
+
React.createElement(Logo, null),
|
|
224
|
+
React.createElement(Box, { marginTop: 1 },
|
|
225
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
226
|
+
React.createElement(Box, { marginTop: 1 },
|
|
227
|
+
React.createElement(Text, { dimColor: true }, "Step 1/3: Select Team (\u2191\u2193 navigate, Enter select)")),
|
|
228
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, teams.map((t, idx) => (React.createElement(Box, { key: t.team.id, marginTop: 1 },
|
|
229
|
+
React.createElement(Text, { color: idx === selectedTeamIndex ? "cyan" : "gray" }, idx === selectedTeamIndex ? "▶ " : " "),
|
|
230
|
+
React.createElement(Text, { bold: idx === selectedTeamIndex }, t.team.name)))))));
|
|
231
|
+
}
|
|
232
|
+
if (step === "project") {
|
|
233
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
234
|
+
React.createElement(Logo, null),
|
|
235
|
+
React.createElement(Box, { marginTop: 1 },
|
|
236
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
237
|
+
React.createElement(Box, { marginTop: 1 },
|
|
238
|
+
React.createElement(Text, { dimColor: true },
|
|
239
|
+
"Step 2/3: Select Project - ",
|
|
240
|
+
teams[selectedTeamIndex]?.team.name)),
|
|
241
|
+
React.createElement(Box, { marginTop: 1 },
|
|
242
|
+
React.createElement(Text, { dimColor: true }, "(\u2191\u2193 navigate, Enter select, Esc go back)")),
|
|
243
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, projects.map((p, idx) => (React.createElement(Box, { key: p.id, marginTop: 1 },
|
|
244
|
+
React.createElement(Text, { color: idx === selectedProjectIndex ? "cyan" : "gray" }, idx === selectedProjectIndex ? "▶ " : " "),
|
|
245
|
+
React.createElement(Text, { bold: idx === selectedProjectIndex }, p.name)))))));
|
|
246
|
+
}
|
|
247
|
+
if (step === "deploy") {
|
|
248
|
+
const formatDate = (dateStr) => {
|
|
249
|
+
const date = new Date(dateStr);
|
|
250
|
+
return date.toLocaleDateString() + " " + date.toLocaleTimeString();
|
|
251
|
+
};
|
|
252
|
+
const activeDepId = targetProject?.activeDeploymentId;
|
|
253
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
254
|
+
React.createElement(Logo, null),
|
|
255
|
+
React.createElement(Box, { marginTop: 1 },
|
|
256
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
257
|
+
React.createElement(Box, { marginTop: 1 },
|
|
258
|
+
React.createElement(Text, { dimColor: true },
|
|
259
|
+
"Step 3/3: Select Deployment - ",
|
|
260
|
+
targetProject?.name)),
|
|
261
|
+
React.createElement(Box, { marginTop: 1 },
|
|
262
|
+
React.createElement(Text, { dimColor: true }, "(\u2191\u2193 navigate, Enter select, Esc go back)")),
|
|
263
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, deployments.map((dep, idx) => {
|
|
264
|
+
const isActive = dep.id === activeDepId;
|
|
265
|
+
const statusColor = isActive
|
|
266
|
+
? "green"
|
|
267
|
+
: dep.status === "live"
|
|
268
|
+
? "cyan"
|
|
269
|
+
: "gray";
|
|
270
|
+
const statusLabel = isActive
|
|
271
|
+
? " [ACTIVE]"
|
|
272
|
+
: dep.status === "live"
|
|
273
|
+
? " [DEPLOYED]"
|
|
274
|
+
: dep.status === "failed"
|
|
275
|
+
? " [FAILED]"
|
|
276
|
+
: ` [${dep.status.toUpperCase()}]`;
|
|
277
|
+
return (React.createElement(Box, { key: dep.id, marginTop: 1, flexDirection: "column" },
|
|
278
|
+
React.createElement(Box, null,
|
|
279
|
+
React.createElement(Text, { color: idx === selectedDeployIndex ? "cyan" : "gray" }, idx === selectedDeployIndex ? "▶ " : " "),
|
|
280
|
+
React.createElement(Text, { bold: idx === selectedDeployIndex }, dep.commitMessage || "Manual Upload"),
|
|
281
|
+
React.createElement(Text, { color: statusColor }, statusLabel)),
|
|
282
|
+
React.createElement(Box, { marginLeft: 2 },
|
|
283
|
+
React.createElement(Text, { dimColor: true },
|
|
284
|
+
"ID: ",
|
|
285
|
+
dep.id)),
|
|
286
|
+
React.createElement(Box, { marginLeft: 2 },
|
|
287
|
+
React.createElement(Text, { dimColor: true }, formatDate(dep.createdAt)))));
|
|
288
|
+
}))));
|
|
289
|
+
}
|
|
290
|
+
if (step === "confirm") {
|
|
291
|
+
const isActive = targetDeployment?.id === targetProject?.activeDeploymentId;
|
|
292
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
293
|
+
React.createElement(Logo, null),
|
|
294
|
+
React.createElement(Box, { marginTop: 1 },
|
|
295
|
+
React.createElement(Text, { bold: true, color: "yellow" }, "\u26A0 Confirm Rollback")),
|
|
296
|
+
React.createElement(Box, { marginTop: 1 },
|
|
297
|
+
React.createElement(Text, null,
|
|
298
|
+
"Project: ",
|
|
299
|
+
React.createElement(Text, { bold: true }, targetProject?.name))),
|
|
300
|
+
React.createElement(Box, { marginTop: 1 },
|
|
301
|
+
React.createElement(Text, null,
|
|
302
|
+
"Deployment:",
|
|
303
|
+
" ",
|
|
304
|
+
React.createElement(Text, { bold: true }, targetDeployment?.commitMessage || "Manual Upload"))),
|
|
305
|
+
React.createElement(Box, { marginTop: 1 },
|
|
306
|
+
React.createElement(Text, { dimColor: true },
|
|
307
|
+
"ID: ",
|
|
308
|
+
targetDeployment?.id)),
|
|
309
|
+
isActive && (React.createElement(Box, { marginTop: 1 },
|
|
310
|
+
React.createElement(Text, { color: "yellow" }, "\u26A0 This is the currently active deployment"))),
|
|
311
|
+
React.createElement(Box, { marginTop: 2 },
|
|
312
|
+
React.createElement(Text, null, "[Y] Yes, rollback [N] Cancel"))));
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
};
|
|
316
|
+
export default Rollback;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { api } from "../lib/api.js";
|
|
3
|
+
import { getConfig, isLoggedIn } from "../lib/config.js";
|
|
4
|
+
import { ErrorDisplay } from "../components/Loading.js";
|
|
5
|
+
const MAX_RETRIES = 3;
|
|
6
|
+
const Teams = () => {
|
|
7
|
+
const [state, setState] = useState("loading");
|
|
8
|
+
const [errorMsg, setErrorMsg] = useState("");
|
|
9
|
+
const [retryCount, setRetryCount] = useState(0);
|
|
10
|
+
const [teams, setTeams] = useState([]);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (state !== "done")
|
|
13
|
+
return;
|
|
14
|
+
console.log("\n");
|
|
15
|
+
console.log(" Your Teams\n");
|
|
16
|
+
console.log(" " + "─".repeat(50));
|
|
17
|
+
if (teams.length === 0) {
|
|
18
|
+
console.log(" No teams found. Create a team from the dashboard.");
|
|
19
|
+
console.log("");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
teams.forEach((team, index) => {
|
|
23
|
+
const isDefault = index === 0;
|
|
24
|
+
console.log(` ${index + 1}. ${team.team.name} ${isDefault ? "(default)" : ""}`);
|
|
25
|
+
console.log(` Role: ${team.role}`);
|
|
26
|
+
console.log(` ID: ${team.team.id}`);
|
|
27
|
+
console.log(` Slug: ${team.team.slug}`);
|
|
28
|
+
console.log(` Plan: ${team.team.plan}`);
|
|
29
|
+
console.log(` Created: ${new Date(team.team.createdAt).toLocaleDateString()}`);
|
|
30
|
+
console.log("");
|
|
31
|
+
});
|
|
32
|
+
console.log(" " + "─".repeat(50));
|
|
33
|
+
console.log("\n Use --team flag: onflyt deploy --team tm_xxx\n");
|
|
34
|
+
}, [state, teams]);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!isLoggedIn()) {
|
|
37
|
+
setErrorMsg("Not logged in. Run 'onflyt login' first.");
|
|
38
|
+
setState("error");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const fetchTeams = async () => {
|
|
42
|
+
let attempt = 0;
|
|
43
|
+
const attemptFetch = async () => {
|
|
44
|
+
attempt++;
|
|
45
|
+
try {
|
|
46
|
+
console.log(`\n Fetching teams...${attempt > 1 ? ` (retry ${attempt}/${MAX_RETRIES})` : ""}\n`);
|
|
47
|
+
const config = getConfig();
|
|
48
|
+
api.setToken(config.token);
|
|
49
|
+
const meData = await api.get("/auth/me");
|
|
50
|
+
const userTeams = meData.teams || [];
|
|
51
|
+
setTeams(userTeams);
|
|
52
|
+
setState("done");
|
|
53
|
+
return meData;
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (attempt < MAX_RETRIES) {
|
|
57
|
+
setRetryCount(attempt);
|
|
58
|
+
return attemptFetch();
|
|
59
|
+
}
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
try {
|
|
64
|
+
await attemptFetch();
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
setErrorMsg(err.message || "Failed to fetch teams");
|
|
68
|
+
setState("error");
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
fetchTeams();
|
|
72
|
+
}, []);
|
|
73
|
+
if (state === "loading") {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (state === "error") {
|
|
77
|
+
return React.createElement(ErrorDisplay, { message: errorMsg });
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
};
|
|
81
|
+
export default Teams;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text, Box } from "ink";
|
|
3
|
+
import { getConfig, isLoggedIn } from "../lib/config.js";
|
|
4
|
+
import { Logo, ErrorDisplay } from "../components/Loading.js";
|
|
5
|
+
const WhoAmI = () => {
|
|
6
|
+
const config = getConfig();
|
|
7
|
+
if (!isLoggedIn()) {
|
|
8
|
+
return React.createElement(ErrorDisplay, { message: "Not logged in. Run 'onflyt login' first." });
|
|
9
|
+
}
|
|
10
|
+
const { user, token, lastLogin } = config;
|
|
11
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
12
|
+
React.createElement(Logo, null),
|
|
13
|
+
React.createElement(Box, { marginTop: 1 },
|
|
14
|
+
React.createElement(Text, { bold: true }, "Logged in as:")),
|
|
15
|
+
React.createElement(Box, { marginTop: 1 },
|
|
16
|
+
React.createElement(Text, null, "Name: "),
|
|
17
|
+
React.createElement(Text, { bold: true }, user?.name || "Unknown")),
|
|
18
|
+
React.createElement(Box, { marginTop: 1 },
|
|
19
|
+
React.createElement(Text, null, "Email: "),
|
|
20
|
+
React.createElement(Text, null, user?.email)),
|
|
21
|
+
user?.avatar && (React.createElement(Box, { marginTop: 1 },
|
|
22
|
+
React.createElement(Text, { dimColor: true },
|
|
23
|
+
"Avatar: ",
|
|
24
|
+
user.avatar))),
|
|
25
|
+
React.createElement(Box, { marginTop: 1 },
|
|
26
|
+
React.createElement(Text, { dimColor: true },
|
|
27
|
+
"User ID: ",
|
|
28
|
+
user?.id)),
|
|
29
|
+
lastLogin && (React.createElement(Box, { marginTop: 1 },
|
|
30
|
+
React.createElement(Text, { dimColor: true },
|
|
31
|
+
"Last login: ",
|
|
32
|
+
new Date(lastLogin).toLocaleString())))));
|
|
33
|
+
};
|
|
34
|
+
export default WhoAmI;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export declare const Logo: React.FC;
|
|
3
|
+
interface LoadingProps {
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const Loading: React.FC<LoadingProps>;
|
|
7
|
+
export declare const ErrorDisplay: React.FC<{
|
|
8
|
+
message: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const Success: React.FC<{
|
|
11
|
+
message: string;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text, Box } from "ink";
|
|
3
|
+
const bigText = (str) => {
|
|
4
|
+
return str
|
|
5
|
+
.split("")
|
|
6
|
+
.map((c) => {
|
|
7
|
+
const code = c.toUpperCase().charCodeAt(0);
|
|
8
|
+
if (code >= 65 && code <= 90) {
|
|
9
|
+
return String.fromCharCode(0xff21 + code - 65);
|
|
10
|
+
}
|
|
11
|
+
return c;
|
|
12
|
+
})
|
|
13
|
+
.join("");
|
|
14
|
+
};
|
|
15
|
+
export const Logo = () => (React.createElement(Box, { flexDirection: "column" },
|
|
16
|
+
React.createElement(Box, { alignItems: "center" },
|
|
17
|
+
React.createElement(Box, { flexDirection: "column", marginRight: 0.5 },
|
|
18
|
+
React.createElement(Text, { color: "rgb(255,191,0)" }, " \u2B21 ")),
|
|
19
|
+
React.createElement(Text, { bold: true, color: "rgb(255,191,0)" }, bigText("Onflyt")),
|
|
20
|
+
React.createElement(Text, null, " "),
|
|
21
|
+
React.createElement(Text, { bold: true, color: "black", backgroundColor: "rgb(255,191,0)" },
|
|
22
|
+
" ",
|
|
23
|
+
"v1.0.1-beta.1",
|
|
24
|
+
" ")),
|
|
25
|
+
React.createElement(Box, { marginTop: 1 },
|
|
26
|
+
React.createElement(Text, { dimColor: true }, "─".repeat(30)))));
|
|
27
|
+
export const Loading = ({ message }) => (React.createElement(Box, { flexDirection: "column" },
|
|
28
|
+
React.createElement(Logo, null),
|
|
29
|
+
React.createElement(Box, { marginTop: 1 },
|
|
30
|
+
React.createElement(Text, null, message))));
|
|
31
|
+
export const ErrorDisplay = ({ message }) => (React.createElement(Box, { flexDirection: "column" },
|
|
32
|
+
React.createElement(Logo, null),
|
|
33
|
+
React.createElement(Box, { marginTop: 1 },
|
|
34
|
+
React.createElement(Text, { bold: true, color: "red" }, "\u2716 Error")),
|
|
35
|
+
React.createElement(Box, { marginTop: 1 },
|
|
36
|
+
React.createElement(Text, { color: "red" }, message))));
|
|
37
|
+
export const Success = ({ message }) => (React.createElement(Box, { flexDirection: "column" },
|
|
38
|
+
React.createElement(Logo, null),
|
|
39
|
+
React.createElement(Box, { marginTop: 1 },
|
|
40
|
+
React.createElement(Text, { bold: true, color: "green" },
|
|
41
|
+
"\u2713 ",
|
|
42
|
+
message))));
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|