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.

Files changed (85) hide show
  1. package/dist/App.d.ts +3 -0
  2. package/dist/App.js +8 -0
  3. package/dist/commands/credits.d.ts +3 -0
  4. package/dist/commands/credits.js +101 -0
  5. package/dist/commands/delete.d.ts +7 -0
  6. package/dist/commands/delete.js +220 -0
  7. package/dist/commands/deploy.d.ts +6 -0
  8. package/dist/commands/deploy.js +715 -0
  9. package/dist/commands/deployments.d.ts +6 -0
  10. package/dist/commands/deployments.js +225 -0
  11. package/dist/commands/help.d.ts +3 -0
  12. package/dist/commands/help.js +76 -0
  13. package/dist/commands/init.d.ts +11 -0
  14. package/dist/commands/init.js +422 -0
  15. package/dist/commands/login.d.ts +6 -0
  16. package/dist/commands/login.js +150 -0
  17. package/dist/commands/logout.d.ts +3 -0
  18. package/dist/commands/logout.js +19 -0
  19. package/dist/commands/logs.d.ts +7 -0
  20. package/dist/commands/logs.js +307 -0
  21. package/dist/commands/projects.d.ts +3 -0
  22. package/dist/commands/projects.js +203 -0
  23. package/dist/commands/rollback.d.ts +6 -0
  24. package/dist/commands/rollback.js +316 -0
  25. package/dist/commands/teams.d.ts +3 -0
  26. package/dist/commands/teams.js +81 -0
  27. package/dist/commands/whoami.d.ts +3 -0
  28. package/dist/commands/whoami.js +34 -0
  29. package/dist/components/Loading.d.ts +13 -0
  30. package/dist/components/Loading.js +42 -0
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +107 -442
  33. package/dist/lib/api.d.ts +27 -0
  34. package/dist/lib/api.js +109 -0
  35. package/dist/lib/config.d.ts +32 -0
  36. package/dist/lib/config.js +52 -0
  37. package/dist/lib/deploy-api.d.ts +97 -0
  38. package/dist/lib/deploy-api.js +335 -0
  39. package/dist/lib/deploy.d.ts +36 -0
  40. package/dist/lib/deploy.js +181 -0
  41. package/dist/lib/framework.d.ts +27 -0
  42. package/dist/lib/framework.js +184 -0
  43. package/dist/lib/git.d.ts +25 -0
  44. package/dist/lib/git.js +149 -0
  45. package/dist/lib/scaffold.d.ts +21 -0
  46. package/dist/lib/scaffold.js +190 -0
  47. package/dist/shared/frameworks/registry.d.ts +21 -0
  48. package/dist/shared/frameworks/registry.js +196 -0
  49. package/dist/shared/index.d.ts +4 -0
  50. package/dist/shared/index.js +4 -0
  51. package/dist/shared/limits.d.ts +16 -0
  52. package/dist/shared/limits.js +44 -0
  53. package/dist/shared/pricing.d.ts +2 -0
  54. package/dist/shared/pricing.js +7 -0
  55. package/dist/shared/templates/registry.d.ts +9 -0
  56. package/dist/shared/templates/registry.js +47 -0
  57. package/onflyt.json +10 -0
  58. package/package.json +5 -7
  59. package/src/App.tsx +13 -0
  60. package/src/commands/credits.tsx +151 -0
  61. package/src/commands/delete.tsx +315 -0
  62. package/src/commands/deploy.tsx +1039 -0
  63. package/src/commands/deployments.tsx +331 -0
  64. package/src/commands/help.tsx +79 -0
  65. package/src/commands/init.tsx +587 -0
  66. package/src/commands/login.tsx +207 -0
  67. package/src/commands/logout.tsx +31 -0
  68. package/src/commands/logs.tsx +447 -0
  69. package/src/commands/projects.tsx +287 -0
  70. package/src/commands/rollback.tsx +455 -0
  71. package/src/commands/teams.tsx +113 -0
  72. package/src/commands/whoami.tsx +48 -0
  73. package/src/components/Loading.tsx +74 -0
  74. package/src/index.tsx +130 -0
  75. package/src/lib/api.ts +152 -0
  76. package/src/lib/config.ts +90 -0
  77. package/src/lib/deploy-api.ts +511 -0
  78. package/src/lib/deploy.ts +260 -0
  79. package/src/lib/framework.ts +227 -0
  80. package/src/lib/git.ts +179 -0
  81. package/src/lib/scaffold.ts +225 -0
  82. package/src/lib/shared.ts +350 -0
  83. package/src/types.d.ts +5 -0
  84. package/tsconfig.json +17 -0
  85. package/README.md +0 -338
@@ -0,0 +1,151 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { api } from "../lib/api.js";
3
+ import { getConfig, isLoggedIn } from "../lib/config.js";
4
+ import { Logo, ErrorDisplay } from "../components/Loading.js";
5
+
6
+ interface Team {
7
+ teamId: string;
8
+ role: string;
9
+ team: {
10
+ id: string;
11
+ name: string;
12
+ slug: string;
13
+ plan?: string;
14
+ };
15
+ }
16
+
17
+ interface Balance {
18
+ balanceUSD: number;
19
+ balanceFormatted: string;
20
+ }
21
+
22
+ interface CreditDisplay {
23
+ team: Team;
24
+ balance: Balance;
25
+ }
26
+
27
+ const MAX_RETRIES = 3;
28
+
29
+ const Credits = () => {
30
+ const [state, setState] = useState<"loading" | "error" | "done">("loading");
31
+ const [errorMsg, setErrorMsg] = useState("");
32
+ const [retryCount, setRetryCount] = useState(0);
33
+ const [credits, setCredits] = useState<CreditDisplay[]>([]);
34
+
35
+ useEffect(() => {
36
+ if (state !== "done") return;
37
+
38
+ console.log("\n Credits Balance\n");
39
+ console.log(" " + "─".repeat(50));
40
+
41
+ credits.forEach((item) => {
42
+ const { team, balance } = item;
43
+ const isLow = balance.balanceUSD < 5;
44
+ const plan = team.team.plan || "free";
45
+
46
+ console.log(`\n ${team.team.name} (${plan})`);
47
+
48
+ if (isLow) {
49
+ console.log(
50
+ ` \x1b[33m Credits: ${balance.balanceFormatted} ⚠ Low credits\x1b[0m`,
51
+ );
52
+ } else {
53
+ console.log(
54
+ ` \x1b[32m Credits: ${balance.balanceFormatted} ✓\x1b[0m`,
55
+ );
56
+ }
57
+ });
58
+
59
+ console.log("\n " + "─".repeat(50));
60
+ console.log("\n Run 'onflyt add-credits' to add more credits.\n");
61
+ }, [state, credits]);
62
+
63
+ useEffect(() => {
64
+ if (!isLoggedIn()) {
65
+ setErrorMsg("Not logged in. Run 'onflyt login' first.");
66
+ setState("error");
67
+ return;
68
+ }
69
+
70
+ const fetchCredits = async () => {
71
+ let attempt = 0;
72
+
73
+ const attemptFetch = async () => {
74
+ attempt++;
75
+ try {
76
+ console.log(
77
+ `\n Fetching credits...${attempt > 1 ? ` (retry ${attempt}/${MAX_RETRIES})` : ""}\n`,
78
+ );
79
+
80
+ const config = getConfig();
81
+ api.setToken(config.token!);
82
+
83
+ const meData = await api.get<any>("/auth/me");
84
+ const userTeams: Team[] = meData.teams || [];
85
+
86
+ if (userTeams.length === 0) {
87
+ console.log("\n No teams found.\n");
88
+ console.log(" You don't have any teams yet.\n");
89
+ return;
90
+ }
91
+
92
+ const balancesData: Record<string, Balance> = {};
93
+
94
+ await Promise.all(
95
+ userTeams.map(async (team: Team) => {
96
+ try {
97
+ const balanceData = await api.get<any>(
98
+ `/billing/balance?teamId=${team.team.id}`,
99
+ );
100
+ balancesData[team.team.id] = balanceData.data || balanceData;
101
+ } catch {
102
+ balancesData[team.team.id] = {
103
+ balanceUSD: 0,
104
+ balanceFormatted: "$0.00",
105
+ };
106
+ }
107
+ }),
108
+ );
109
+
110
+ const creditDisplay: CreditDisplay[] = userTeams.map((team) => ({
111
+ team,
112
+ balance: balancesData[team.team.id] || {
113
+ balanceUSD: 0,
114
+ balanceFormatted: "$0.00",
115
+ },
116
+ }));
117
+
118
+ setCredits(creditDisplay);
119
+ setState("done");
120
+ } catch (err) {
121
+ if (attempt < MAX_RETRIES) {
122
+ setRetryCount(attempt);
123
+ return attemptFetch();
124
+ }
125
+ throw err;
126
+ }
127
+ };
128
+
129
+ try {
130
+ await attemptFetch();
131
+ } catch (err: any) {
132
+ setErrorMsg(err.message || "Failed to fetch credits");
133
+ setState("error");
134
+ }
135
+ };
136
+
137
+ fetchCredits();
138
+ }, []);
139
+
140
+ if (state === "loading") {
141
+ return null;
142
+ }
143
+
144
+ if (state === "error") {
145
+ return <ErrorDisplay message={errorMsg} />;
146
+ }
147
+
148
+ return null;
149
+ };
150
+
151
+ export default Credits;
@@ -0,0 +1,315 @@
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
+
8
+ interface DeleteProps {
9
+ projectId?: string;
10
+ projectName?: string;
11
+ }
12
+
13
+ const Delete: React.FC<DeleteProps> = ({ projectId, projectName }) => {
14
+ const [step, setStep] = useState<
15
+ | "loading"
16
+ | "loading-projects"
17
+ | "team"
18
+ | "select"
19
+ | "confirm"
20
+ | "deleting"
21
+ | "done"
22
+ | "error"
23
+ >("loading");
24
+
25
+ const [teams, setTeams] = useState<any[]>([]);
26
+ const [projects, setProjects] = useState<any[]>([]);
27
+ const [selectedTeamIndex, setSelectedTeamIndex] = useState(0);
28
+ const [selectedProjectIndex, setSelectedProjectIndex] = useState(0);
29
+ const [targetProject, setTargetProject] = useState<any>(null);
30
+ const [errorMsg, setErrorMsg] = useState("");
31
+
32
+ useEffect(() => {
33
+ const handleSigInt = () => process.exit(0);
34
+ process.on("SIGINT", handleSigInt);
35
+ return () => {
36
+ process.off("SIGINT", handleSigInt);
37
+ };
38
+ }, []);
39
+
40
+ useEffect(() => {
41
+ if (step === "done" || step === "error") {
42
+ const timer = setTimeout(() => process.exit(0), 500);
43
+ return () => clearTimeout(timer);
44
+ }
45
+ }, [step]);
46
+
47
+ useInput((input, key) => {
48
+ if (input === "q" || input === "Q" || (key.ctrl && input === "c")) {
49
+ process.exit(0);
50
+ }
51
+
52
+ if (step === "team") {
53
+ if (key.upArrow) {
54
+ setSelectedTeamIndex((i) => Math.max(0, i - 1));
55
+ } else if (key.downArrow) {
56
+ setSelectedTeamIndex((i) => Math.min(teams.length - 1, i + 1));
57
+ } else if (key.return) {
58
+ setStep("loading-projects");
59
+ loadProjects(teams[selectedTeamIndex].team.id);
60
+ }
61
+ }
62
+
63
+ if (step === "select") {
64
+ if (key.upArrow) {
65
+ setSelectedProjectIndex((i) => Math.max(0, i - 1));
66
+ } else if (key.downArrow) {
67
+ setSelectedProjectIndex((i) => Math.min(projects.length - 1, i + 1));
68
+ } else if (key.return) {
69
+ setTargetProject(projects[selectedProjectIndex]);
70
+ setStep("confirm");
71
+ } else if (key.escape) {
72
+ setStep("team");
73
+ }
74
+ }
75
+
76
+ if (step === "confirm") {
77
+ if (input === "y" || input === "Y" || key.return) {
78
+ deleteProject(targetProject.id);
79
+ } else if (input === "n" || input === "N" || key.escape) {
80
+ setStep("select");
81
+ }
82
+ }
83
+ });
84
+
85
+ useEffect(() => {
86
+ if (!isLoggedIn()) {
87
+ setErrorMsg("Not logged in. Run 'onflyt login' first.");
88
+ setStep("error");
89
+ return;
90
+ }
91
+
92
+ if (projectId) {
93
+ setTargetProject({ id: projectId, name: projectName || projectId });
94
+ setStep("confirm");
95
+ return;
96
+ }
97
+
98
+ loadTeams();
99
+ }, []);
100
+
101
+ const loadTeams = async () => {
102
+ try {
103
+ const config = getConfig();
104
+ api.setToken(config.token!);
105
+ const meData = await api.get<any>("/auth/me");
106
+ const userTeams = meData.teams || [];
107
+
108
+ if (userTeams.length === 0) {
109
+ setErrorMsg("No teams found");
110
+ setStep("error");
111
+ return;
112
+ }
113
+
114
+ setTeams(userTeams);
115
+
116
+ if (userTeams.length === 1) {
117
+ setSelectedTeamIndex(0);
118
+ setStep("loading-projects");
119
+ loadProjects(userTeams[0].team.id);
120
+ } else {
121
+ setStep("team");
122
+ }
123
+ } catch (err: any) {
124
+ setErrorMsg(err.message);
125
+ setStep("error");
126
+ }
127
+ };
128
+
129
+ const loadProjects = async (teamId: string) => {
130
+ try {
131
+ const projectsRes = await api.get<any>(`/projects/team/${teamId}`);
132
+ const teamProjects = projectsRes.projects || [];
133
+
134
+ if (teamProjects.length === 0) {
135
+ setErrorMsg("No projects found in this team");
136
+ setStep("error");
137
+ return;
138
+ }
139
+
140
+ setProjects(teamProjects);
141
+ setSelectedProjectIndex(0);
142
+ setStep("select");
143
+ } catch (err: any) {
144
+ setErrorMsg(err.message);
145
+ setStep("error");
146
+ }
147
+ };
148
+
149
+ const deleteProject = async (projId: string) => {
150
+ setStep("deleting");
151
+ try {
152
+ await api.delete(`/projects/${projId}`);
153
+ setStep("done");
154
+ } catch (err: any) {
155
+ setErrorMsg(err.message);
156
+ setStep("error");
157
+ }
158
+ };
159
+
160
+ if (step === "loading") {
161
+ return (
162
+ <Box flexDirection="column">
163
+ <Logo />
164
+ <Box marginTop={1}>
165
+ <Text>Loading...</Text>
166
+ </Box>
167
+ </Box>
168
+ );
169
+ }
170
+
171
+ if (step === "loading-projects") {
172
+ return (
173
+ <Box flexDirection="column" padding={1}>
174
+ <Logo />
175
+ <Box marginTop={1}>
176
+ <Text bold>Delete Project</Text>
177
+ </Box>
178
+ <Box marginTop={1}>
179
+ <Text dimColor>Loading projects...</Text>
180
+ </Box>
181
+ <Box marginTop={1}>
182
+ <Text>
183
+ <Spinner />
184
+ </Text>
185
+ </Box>
186
+ </Box>
187
+ );
188
+ }
189
+
190
+ if (step === "error") {
191
+ return (
192
+ <Box flexDirection="column">
193
+ <Logo />
194
+ <Box marginTop={1}>
195
+ <Text bold color="red">
196
+ ✖ Error
197
+ </Text>
198
+ </Box>
199
+ <Box marginTop={1}>
200
+ <Text color="red">{errorMsg}</Text>
201
+ </Box>
202
+ </Box>
203
+ );
204
+ }
205
+
206
+ if (step === "deleting") {
207
+ return (
208
+ <Box flexDirection="column">
209
+ <Logo />
210
+ <Box marginTop={1}>
211
+ <Text>Deleting project...</Text>
212
+ </Box>
213
+ </Box>
214
+ );
215
+ }
216
+
217
+ if (step === "done") {
218
+ return (
219
+ <Box flexDirection="column">
220
+ <Logo />
221
+ <Box marginTop={1}>
222
+ <Text bold color="green">
223
+ ✓ Project deleted successfully
224
+ </Text>
225
+ </Box>
226
+ </Box>
227
+ );
228
+ }
229
+
230
+ if (step === "team") {
231
+ return (
232
+ <Box flexDirection="column" padding={1}>
233
+ <Logo />
234
+ <Box marginTop={1}>
235
+ <Text bold>Delete Project</Text>
236
+ </Box>
237
+ <Box marginTop={1}>
238
+ <Text dimColor>
239
+ Step 1/2: Select Team (↑↓ navigate, Enter select)
240
+ </Text>
241
+ </Box>
242
+
243
+ <Box marginTop={1} flexDirection="column">
244
+ {teams.map((t, idx) => (
245
+ <Box key={t.team.id} marginTop={1}>
246
+ <Text color={idx === selectedTeamIndex ? "cyan" : "gray"}>
247
+ {idx === selectedTeamIndex ? "▶ " : " "}
248
+ </Text>
249
+ <Text bold={idx === selectedTeamIndex}>{t.team.name}</Text>
250
+ </Box>
251
+ ))}
252
+ </Box>
253
+ </Box>
254
+ );
255
+ }
256
+
257
+ if (step === "select") {
258
+ return (
259
+ <Box flexDirection="column" padding={1}>
260
+ <Logo />
261
+ <Box marginTop={1}>
262
+ <Text bold>Delete Project</Text>
263
+ </Box>
264
+ <Box marginTop={1}>
265
+ <Text dimColor>
266
+ Step 2/2: Select Project - {teams[selectedTeamIndex]?.team.name}
267
+ </Text>
268
+ </Box>
269
+ <Box>
270
+ <Text dimColor>(↑↓ navigate, Enter select, Esc go back)</Text>
271
+ </Box>
272
+
273
+ <Box marginTop={1} flexDirection="column">
274
+ {projects.map((p, idx) => (
275
+ <Box key={p.id} marginTop={1}>
276
+ <Text color={idx === selectedProjectIndex ? "cyan" : "gray"}>
277
+ {idx === selectedProjectIndex ? "▶ " : " "}
278
+ </Text>
279
+ <Text bold={idx === selectedProjectIndex}>{p.name}</Text>
280
+ <Text dimColor> ({p.framework})</Text>
281
+ </Box>
282
+ ))}
283
+ </Box>
284
+ </Box>
285
+ );
286
+ }
287
+
288
+ if (step === "confirm") {
289
+ return (
290
+ <Box flexDirection="column" padding={1}>
291
+ <Logo />
292
+ <Box marginTop={1}>
293
+ <Text bold color="red">
294
+ ⚠ Confirm Delete
295
+ </Text>
296
+ </Box>
297
+ <Box marginTop={1}>
298
+ <Text>
299
+ Delete project: <Text bold>{targetProject?.name}</Text>?
300
+ </Text>
301
+ </Box>
302
+ <Box marginTop={1}>
303
+ <Text color="red">This action cannot be undone!</Text>
304
+ </Box>
305
+ <Box marginTop={2}>
306
+ <Text>[Y] Yes, delete [N] Cancel</Text>
307
+ </Box>
308
+ </Box>
309
+ );
310
+ }
311
+
312
+ return null;
313
+ };
314
+
315
+ export default Delete;