@nexical/cli 0.1.7 → 0.11.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.
Files changed (241) hide show
  1. package/.github/workflows/deploy.yml +3 -3
  2. package/GEMINI.md +193 -0
  3. package/README.md +317 -104
  4. package/dist/chunk-JYASTIIW.js +42 -0
  5. package/dist/chunk-JYASTIIW.js.map +1 -0
  6. package/dist/chunk-LZ3YQWAR.js +2204 -0
  7. package/dist/chunk-LZ3YQWAR.js.map +1 -0
  8. package/dist/chunk-OKXOCNXP.js +105 -0
  9. package/dist/chunk-OKXOCNXP.js.map +1 -0
  10. package/dist/chunk-OYFWMYPG.js +52 -0
  11. package/dist/chunk-OYFWMYPG.js.map +1 -0
  12. package/dist/chunk-WKERTCM6.js +74 -0
  13. package/dist/chunk-WKERTCM6.js.map +1 -0
  14. package/dist/index.js +32 -5
  15. package/dist/index.js.map +1 -1
  16. package/dist/src/commands/init.d.ts +11 -0
  17. package/dist/src/commands/init.js +89 -0
  18. package/dist/src/commands/init.js.map +1 -0
  19. package/dist/src/commands/module/add.d.ts +14 -0
  20. package/dist/src/commands/module/add.js +136 -0
  21. package/dist/src/commands/module/add.js.map +1 -0
  22. package/dist/src/commands/module/list.d.ts +10 -0
  23. package/dist/src/commands/module/list.js +73 -0
  24. package/dist/src/commands/module/list.js.map +1 -0
  25. package/dist/src/commands/module/remove.d.ts +12 -0
  26. package/dist/src/commands/module/remove.js +71 -0
  27. package/dist/src/commands/module/remove.js.map +1 -0
  28. package/dist/src/commands/module/update.d.ts +11 -0
  29. package/dist/src/commands/module/update.js +52 -0
  30. package/dist/src/commands/module/update.js.map +1 -0
  31. package/dist/src/commands/run.d.ts +11 -0
  32. package/dist/src/commands/run.js +93 -0
  33. package/dist/src/commands/run.js.map +1 -0
  34. package/dist/src/commands/{login.d.ts → setup.d.ts} +2 -2
  35. package/dist/src/commands/setup.js +62 -0
  36. package/dist/src/commands/setup.js.map +1 -0
  37. package/dist/src/utils/discovery.d.ts +13 -0
  38. package/dist/src/utils/discovery.js +9 -0
  39. package/dist/src/utils/git.d.ts +16 -0
  40. package/dist/src/utils/git.js +29 -0
  41. package/dist/src/utils/git.js.map +1 -0
  42. package/dist/src/utils/url-resolver.d.ts +15 -0
  43. package/dist/src/utils/url-resolver.js +9 -0
  44. package/dist/src/utils/url-resolver.js.map +1 -0
  45. package/index.ts +29 -5
  46. package/package.json +32 -30
  47. package/src/commands/init.ts +86 -0
  48. package/src/commands/module/add.ts +169 -0
  49. package/src/commands/module/list.ts +69 -0
  50. package/src/commands/module/remove.ts +74 -0
  51. package/src/commands/module/update.ts +50 -0
  52. package/src/commands/run.ts +98 -0
  53. package/src/commands/setup.ts +74 -0
  54. package/src/utils/discovery.ts +134 -0
  55. package/src/utils/git.ts +65 -0
  56. package/src/utils/url-resolver.ts +57 -0
  57. package/test/e2e/lifecycle.e2e.test.ts +153 -0
  58. package/test/integration/commands/init.integration.test.ts +85 -0
  59. package/test/integration/commands/module.integration.test.ts +144 -0
  60. package/test/integration/commands/run.integration.test.ts +90 -0
  61. package/test/integration/utils/command-loading.integration.test.ts +80 -0
  62. package/test/unit/commands/init.test.ts +153 -0
  63. package/test/unit/commands/module/add.test.ts +262 -0
  64. package/test/unit/commands/module/list.test.ts +115 -0
  65. package/test/unit/commands/module/remove.test.ts +89 -0
  66. package/test/unit/commands/module/update.test.ts +91 -0
  67. package/test/unit/commands/run.test.ts +252 -0
  68. package/test/unit/commands/setup.test.ts +169 -0
  69. package/test/unit/utils/command-discovery.test.ts +176 -0
  70. package/test/unit/utils/git.test.ts +152 -0
  71. package/test/unit/utils/integration-helpers.test.ts +72 -0
  72. package/test/unit/utils/url-resolver.test.ts +39 -0
  73. package/test/utils/integration-helpers.ts +66 -0
  74. package/vitest.e2e.config.ts +0 -1
  75. package/dist/chunk-JDRAVUKK.js +0 -48
  76. package/dist/chunk-JDRAVUKK.js.map +0 -1
  77. package/dist/src/commands/admin/create-user.d.ts +0 -15
  78. package/dist/src/commands/admin/create-user.js +0 -49
  79. package/dist/src/commands/admin/create-user.js.map +0 -1
  80. package/dist/src/commands/branch/create.d.ts +0 -19
  81. package/dist/src/commands/branch/create.js +0 -59
  82. package/dist/src/commands/branch/create.js.map +0 -1
  83. package/dist/src/commands/branch/delete.d.ts +0 -15
  84. package/dist/src/commands/branch/delete.js +0 -50
  85. package/dist/src/commands/branch/delete.js.map +0 -1
  86. package/dist/src/commands/branch/get.d.ts +0 -15
  87. package/dist/src/commands/branch/get.js +0 -53
  88. package/dist/src/commands/branch/get.js.map +0 -1
  89. package/dist/src/commands/branch/list.d.ts +0 -15
  90. package/dist/src/commands/branch/list.js +0 -51
  91. package/dist/src/commands/branch/list.js.map +0 -1
  92. package/dist/src/commands/job/get.d.ts +0 -15
  93. package/dist/src/commands/job/get.js +0 -62
  94. package/dist/src/commands/job/get.js.map +0 -1
  95. package/dist/src/commands/job/list.d.ts +0 -15
  96. package/dist/src/commands/job/list.js +0 -57
  97. package/dist/src/commands/job/list.js.map +0 -1
  98. package/dist/src/commands/job/logs.d.ts +0 -15
  99. package/dist/src/commands/job/logs.js +0 -67
  100. package/dist/src/commands/job/logs.js.map +0 -1
  101. package/dist/src/commands/job/trigger.d.ts +0 -19
  102. package/dist/src/commands/job/trigger.js +0 -74
  103. package/dist/src/commands/job/trigger.js.map +0 -1
  104. package/dist/src/commands/login.js +0 -31
  105. package/dist/src/commands/login.js.map +0 -1
  106. package/dist/src/commands/project/create.d.ts +0 -24
  107. package/dist/src/commands/project/create.js +0 -63
  108. package/dist/src/commands/project/create.js.map +0 -1
  109. package/dist/src/commands/project/delete.d.ts +0 -20
  110. package/dist/src/commands/project/delete.js +0 -58
  111. package/dist/src/commands/project/delete.js.map +0 -1
  112. package/dist/src/commands/project/get.d.ts +0 -15
  113. package/dist/src/commands/project/get.js +0 -49
  114. package/dist/src/commands/project/get.js.map +0 -1
  115. package/dist/src/commands/project/list.d.ts +0 -15
  116. package/dist/src/commands/project/list.js +0 -45
  117. package/dist/src/commands/project/list.js.map +0 -1
  118. package/dist/src/commands/project/update.d.ts +0 -19
  119. package/dist/src/commands/project/update.js +0 -66
  120. package/dist/src/commands/project/update.js.map +0 -1
  121. package/dist/src/commands/team/create.d.ts +0 -19
  122. package/dist/src/commands/team/create.js +0 -45
  123. package/dist/src/commands/team/create.js.map +0 -1
  124. package/dist/src/commands/team/delete.d.ts +0 -20
  125. package/dist/src/commands/team/delete.js +0 -52
  126. package/dist/src/commands/team/delete.js.map +0 -1
  127. package/dist/src/commands/team/get.d.ts +0 -15
  128. package/dist/src/commands/team/get.js +0 -42
  129. package/dist/src/commands/team/get.js.map +0 -1
  130. package/dist/src/commands/team/list.d.ts +0 -8
  131. package/dist/src/commands/team/list.js +0 -30
  132. package/dist/src/commands/team/list.js.map +0 -1
  133. package/dist/src/commands/team/member/invite.d.ts +0 -20
  134. package/dist/src/commands/team/member/invite.js +0 -54
  135. package/dist/src/commands/team/member/invite.js.map +0 -1
  136. package/dist/src/commands/team/member/remove.d.ts +0 -15
  137. package/dist/src/commands/team/member/remove.js +0 -43
  138. package/dist/src/commands/team/member/remove.js.map +0 -1
  139. package/dist/src/commands/team/update.d.ts +0 -19
  140. package/dist/src/commands/team/update.js +0 -55
  141. package/dist/src/commands/team/update.js.map +0 -1
  142. package/dist/src/commands/token/generate.d.ts +0 -19
  143. package/dist/src/commands/token/generate.js +0 -48
  144. package/dist/src/commands/token/generate.js.map +0 -1
  145. package/dist/src/commands/token/list.d.ts +0 -8
  146. package/dist/src/commands/token/list.js +0 -31
  147. package/dist/src/commands/token/list.js.map +0 -1
  148. package/dist/src/commands/token/revoke.d.ts +0 -15
  149. package/dist/src/commands/token/revoke.js +0 -38
  150. package/dist/src/commands/token/revoke.js.map +0 -1
  151. package/dist/src/commands/whoami.d.ts +0 -8
  152. package/dist/src/commands/whoami.js +0 -26
  153. package/dist/src/commands/whoami.js.map +0 -1
  154. package/dist/src/utils/nexical-client.d.ts +0 -10
  155. package/dist/src/utils/nexical-client.js +0 -12
  156. package/src/commands/admin/create-user.ts +0 -46
  157. package/src/commands/branch/create.ts +0 -57
  158. package/src/commands/branch/delete.ts +0 -47
  159. package/src/commands/branch/get.ts +0 -50
  160. package/src/commands/branch/list.ts +0 -50
  161. package/src/commands/job/get.ts +0 -59
  162. package/src/commands/job/list.ts +0 -56
  163. package/src/commands/job/logs.ts +0 -67
  164. package/src/commands/job/trigger.ts +0 -73
  165. package/src/commands/login.ts +0 -31
  166. package/src/commands/project/create.ts +0 -61
  167. package/src/commands/project/delete.ts +0 -56
  168. package/src/commands/project/get.ts +0 -46
  169. package/src/commands/project/list.ts +0 -44
  170. package/src/commands/project/update.ts +0 -63
  171. package/src/commands/team/create.ts +0 -43
  172. package/src/commands/team/delete.ts +0 -50
  173. package/src/commands/team/get.ts +0 -39
  174. package/src/commands/team/list.ts +0 -26
  175. package/src/commands/team/member/invite.ts +0 -56
  176. package/src/commands/team/member/remove.ts +0 -40
  177. package/src/commands/team/update.ts +0 -53
  178. package/src/commands/token/generate.ts +0 -45
  179. package/src/commands/token/list.ts +0 -27
  180. package/src/commands/token/revoke.ts +0 -35
  181. package/src/commands/whoami.ts +0 -21
  182. package/src/utils/nexical-client.ts +0 -47
  183. package/test/e2e/auth.e2e.test.ts +0 -46
  184. package/test/e2e/job-workflow.e2e.test.ts +0 -33
  185. package/test/e2e/project-lifecycle.e2e.test.ts +0 -48
  186. package/test/e2e/setup.ts +0 -237
  187. package/test/e2e/utils.ts +0 -33
  188. package/test/integration/commands/admin/create-user.test.ts +0 -51
  189. package/test/integration/commands/branch/create.test.ts +0 -51
  190. package/test/integration/commands/branch/delete.test.ts +0 -43
  191. package/test/integration/commands/branch/get.test.ts +0 -49
  192. package/test/integration/commands/branch/list.test.ts +0 -47
  193. package/test/integration/commands/job/get.test.ts +0 -54
  194. package/test/integration/commands/job/list.test.ts +0 -47
  195. package/test/integration/commands/job/logs.test.ts +0 -47
  196. package/test/integration/commands/job/trigger.test.ts +0 -57
  197. package/test/integration/commands/login.test.ts +0 -62
  198. package/test/integration/commands/project/create.test.ts +0 -53
  199. package/test/integration/commands/project/delete.test.ts +0 -43
  200. package/test/integration/commands/project/get.test.ts +0 -51
  201. package/test/integration/commands/project/list.test.ts +0 -47
  202. package/test/integration/commands/project/update.test.ts +0 -53
  203. package/test/integration/commands/team/create.test.ts +0 -53
  204. package/test/integration/commands/team/delete.test.ts +0 -43
  205. package/test/integration/commands/team/get.test.ts +0 -50
  206. package/test/integration/commands/team/list.test.ts +0 -47
  207. package/test/integration/commands/team/member/invite.test.ts +0 -46
  208. package/test/integration/commands/team/member/remove.test.ts +0 -43
  209. package/test/integration/commands/team/update.test.ts +0 -50
  210. package/test/integration/commands/token/generate.test.ts +0 -51
  211. package/test/integration/commands/token/list.test.ts +0 -47
  212. package/test/integration/commands/token/revoke.test.ts +0 -43
  213. package/test/integration/commands/whoami.test.ts +0 -49
  214. package/test/unit/commands/admin/create-user.test.ts +0 -51
  215. package/test/unit/commands/branch/create.test.ts +0 -57
  216. package/test/unit/commands/branch/delete.test.ts +0 -49
  217. package/test/unit/commands/branch/get.test.ts +0 -67
  218. package/test/unit/commands/branch/list.test.ts +0 -62
  219. package/test/unit/commands/job/get.test.ts +0 -76
  220. package/test/unit/commands/job/list.test.ts +0 -62
  221. package/test/unit/commands/job/logs.test.ts +0 -60
  222. package/test/unit/commands/job/trigger.test.ts +0 -75
  223. package/test/unit/commands/login.test.ts +0 -64
  224. package/test/unit/commands/project/create.test.ts +0 -64
  225. package/test/unit/commands/project/delete.test.ts +0 -72
  226. package/test/unit/commands/project/get.test.ts +0 -73
  227. package/test/unit/commands/project/list.test.ts +0 -62
  228. package/test/unit/commands/project/update.test.ts +0 -58
  229. package/test/unit/commands/team/create.test.ts +0 -68
  230. package/test/unit/commands/team/delete.test.ts +0 -71
  231. package/test/unit/commands/team/get.test.ts +0 -70
  232. package/test/unit/commands/team/list.test.ts +0 -56
  233. package/test/unit/commands/team/member/invite.test.ts +0 -52
  234. package/test/unit/commands/team/member/remove.test.ts +0 -49
  235. package/test/unit/commands/team/update.test.ts +0 -63
  236. package/test/unit/commands/token/generate.test.ts +0 -65
  237. package/test/unit/commands/token/list.test.ts +0 -58
  238. package/test/unit/commands/token/revoke.test.ts +0 -49
  239. package/test/unit/commands/whoami.test.ts +0 -49
  240. package/test/unit/utils/nexical-client.test.ts +0 -113
  241. /package/dist/src/utils/{nexical-client.js.map → discovery.js.map} +0 -0
package/test/e2e/setup.ts DELETED
@@ -1,237 +0,0 @@
1
- import { beforeAll, afterAll } from 'vitest';
2
- import http from 'http';
3
-
4
- const MOCK_PORT = 3333;
5
- export const TEST_API_URL = `http://localhost:${MOCK_PORT}`;
6
-
7
- // Simple in-memory mock store
8
- export const mockStore = {
9
- users: [] as any[],
10
- tokens: [] as any[],
11
- teams: [] as any[],
12
- projects: [] as any[],
13
- jobs: [] as any[],
14
- };
15
-
16
- export const resetMockStore = () => {
17
- mockStore.users = [];
18
- mockStore.tokens = [];
19
- mockStore.teams = [
20
- { id: 1, name: 'My Team', slug: 'my-team' }
21
- ];
22
- mockStore.projects = [];
23
- mockStore.jobs = [];
24
- };
25
-
26
- const server = http.createServer((req, res) => {
27
- const { method, url } = req;
28
- let body = '';
29
-
30
- req.on('data', chunk => {
31
- body += chunk.toString();
32
- });
33
-
34
- req.on('end', () => {
35
- let parsedBody: any = {};
36
- try {
37
- if (body) parsedBody = JSON.parse(body);
38
- } catch (e) {
39
- // ignore
40
- }
41
-
42
- console.log(`[MOCK API] ${method} ${url}`, parsedBody);
43
-
44
- res.setHeader('Content-Type', 'application/json');
45
-
46
- // --- Mock Routes ---
47
-
48
- // AUTH
49
- if (method === 'POST' && url === '/auth/device') {
50
- res.writeHead(200);
51
- res.end(JSON.stringify({ deviceCode: '1234', userCode: 'ABCD-1234', verificationUrl: 'http://localhost:3000/verify' }));
52
- return;
53
- }
54
-
55
- if (method === 'POST' && url === '/auth/token') {
56
- res.writeHead(200);
57
- res.end(JSON.stringify({ accessToken: 'mock-access-token', refreshToken: 'mock-refresh-token' }));
58
- return;
59
- }
60
-
61
- if (method === 'POST' && url === '/auth/logout') {
62
- res.writeHead(200);
63
- res.end(JSON.stringify({ success: true }));
64
- return;
65
- }
66
-
67
- // Auth
68
- if (method === 'GET' && url === '/users/me') {
69
- const authHeader = req.headers['authorization'];
70
- const token = authHeader?.split(' ')[1];
71
-
72
- if (!token || token === 'expired') {
73
- res.writeHead(401);
74
- res.end(JSON.stringify({ error: 'Unauthorized' }));
75
- return;
76
- }
77
-
78
- const user = mockStore.users[0] || {
79
- id: '123e4567-e89b-12d3-a456-426614174000', // Valid UUID
80
- email: 'test@example.com',
81
- fullName: 'Test User',
82
- avatarUrl: null,
83
- role: 'user',
84
- createdAt: new Date().toISOString(),
85
- updatedAt: new Date().toISOString()
86
- };
87
-
88
- // Wrap in { user: ... }
89
- res.writeHead(200);
90
- res.end(JSON.stringify({ user }));
91
- return;
92
- }
93
-
94
- // PROJECTS
95
- if (method === 'POST' && url === '/teams/1/projects') {
96
- const newProject = {
97
- id: 101, // SDK expects number
98
- teamId: 1,
99
- name: parsedBody.name,
100
- repoUrl: parsedBody.repoUrl || null,
101
- productionUrl: null,
102
- contextHash: null,
103
- mode: 'managed',
104
- createdAt: new Date().toISOString(),
105
- updatedAt: new Date().toISOString(),
106
- };
107
- mockStore.projects.push(newProject);
108
-
109
- // Wrap in { project: ... }
110
- res.writeHead(201);
111
- res.end(JSON.stringify({ project: newProject }));
112
- return;
113
- }
114
-
115
- if (method === 'GET' && url === '/teams/1/projects') {
116
- // Wrap in { projects: ... }
117
- res.writeHead(200);
118
- res.end(JSON.stringify({ projects: mockStore.projects }));
119
- return;
120
- }
121
-
122
- if (method === 'PUT' && url?.match(/\/teams\/1\/projects\/\d+$/)) {
123
- const id = parseInt(url.split('/').pop() || '0');
124
- const project = mockStore.projects.find((p: any) => p.id === id);
125
- if (project) {
126
- // Update logic mimicking body parse (simplification)
127
- // content-length usually small in tests
128
- // For now, return existing or updated stub
129
- project.name = 'Updated Project'; // Hardcode for test expectation
130
- res.writeHead(200);
131
- res.end(JSON.stringify({ project }));
132
- return;
133
- }
134
- res.writeHead(404);
135
- res.end('Not Found');
136
- return;
137
- }
138
-
139
- if (method === 'DELETE' && url?.match(/\/teams\/1\/projects\/\d+$/)) {
140
- const id = parseInt(url.split('/').pop() || '0');
141
- const index = mockStore.projects.findIndex((p: any) => p.id === id);
142
- if (index !== -1) {
143
- mockStore.projects.splice(index, 1);
144
- res.writeHead(200);
145
- res.end(JSON.stringify({ message: 'Project deleted' }));
146
- } else {
147
- res.writeHead(404);
148
- res.end(JSON.stringify({ message: "Not Found" }));
149
- }
150
- return;
151
- }
152
-
153
- // TEAMS
154
- if (method === 'GET' && url === '/teams/1') {
155
- // Return team 1 mock
156
- res.writeHead(200);
157
- res.end(JSON.stringify({
158
- id: 1,
159
- name: 'My Team',
160
- slug: 'my-team',
161
- billingPlan: 'free',
162
- creditsBalance: 100,
163
- createdAt: new Date().toISOString(),
164
- updatedAt: new Date().toISOString(),
165
- role: 'owner'
166
- }));
167
- return;
168
- }
169
-
170
- // Jobs
171
- if (method === 'POST' && url?.includes('/jobs') && !url.includes('/logs')) {
172
- const newJob = {
173
- id: 123,
174
- branchId: 3,
175
- type: 'deploy',
176
- status: 'pending',
177
- queue: 'public',
178
- inputs: null,
179
- outputs: null,
180
- assignedFactoryId: null,
181
- startedAt: null,
182
- completedAt: null,
183
- createdAt: new Date().toISOString(),
184
- };
185
- mockStore.jobs.push(newJob);
186
- // Wrap in { job: ... }
187
- res.writeHead(201);
188
- res.end(JSON.stringify({ job: newJob }));
189
- return;
190
- }
191
-
192
- // Logs
193
- if (method === 'GET' && url?.includes('/logs')) {
194
- const stubLogs = [
195
- {
196
- id: 1,
197
- jobId: 123,
198
- level: 'info',
199
- message: 'Build initialized',
200
- metadata: null,
201
- timestamp: new Date().toISOString()
202
- },
203
- {
204
- id: 2,
205
- jobId: 123,
206
- level: 'info',
207
- message: 'Build successful',
208
- metadata: null,
209
- timestamp: new Date().toISOString()
210
- }
211
- ];
212
- // Wrap in { logs: ... }
213
- res.writeHead(200);
214
- res.end(JSON.stringify({ logs: stubLogs }));
215
- return;
216
- }
217
-
218
- // Default 404
219
- res.writeHead(404);
220
- res.end(JSON.stringify({ message: 'Not Found' }));
221
- });
222
- });
223
-
224
- beforeAll(async () => {
225
- return new Promise<void>((resolve) => {
226
- server.listen(MOCK_PORT, () => {
227
- console.log(`Mock API running on port ${MOCK_PORT}`);
228
- resolve();
229
- });
230
- });
231
- });
232
-
233
- afterAll(async () => {
234
- return new Promise<void>((resolve) => {
235
- server.close(() => resolve());
236
- });
237
- });
package/test/e2e/utils.ts DELETED
@@ -1,33 +0,0 @@
1
- import path from "path";
2
- import { execa } from "execa";
3
- import { fileURLToPath } from "node:url";
4
- import os from 'os';
5
- import fs from 'fs-extra';
6
-
7
- // Constants
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
- const CLI_BIN = path.resolve(__dirname, '../../dist/index.js');
10
- const TEST_API_URL = 'http://localhost:3333';
11
- export const TEST_HOME = path.resolve(__dirname, '../../test-home');
12
-
13
- // Ensure test home exists
14
- if (!fs.existsSync(TEST_HOME)) {
15
- fs.mkdirpSync(TEST_HOME);
16
- }
17
-
18
- /**
19
- * Runs the CLI command against the compiled binary (E2E style)
20
- */
21
- export async function runCLI(args: string[], options: any = {}) {
22
- return execa("node", [CLI_BIN, ...args], {
23
- cwd: options.cwd || process.cwd(),
24
- ...options,
25
- env: {
26
- ...process.env,
27
- NEXICAL_API_URL: TEST_API_URL, // Point to Mock API
28
- HOME: TEST_HOME, // Isolate config
29
- ...options.env,
30
- },
31
- reject: false, // Allow checking exit code in tests
32
- });
33
- }
@@ -1,51 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import AdminUsersCreateSystemCommand from '../../../../src/commands/admin/create-user.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('AdminUsersCreateSystemCommand Integration', () => {
9
- let command: AdminUsersCreateSystemCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- auth: {
17
- createSystemUser: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new AdminUsersCreateSystemCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'success').mockImplementation(() => { });
25
- vi.spyOn(command, 'error').mockImplementation(() => { });
26
- });
27
-
28
- it('should create system user successfully', async () => {
29
- mockClient.auth.createSystemUser.mockResolvedValue({
30
- user: { fullName: 'Integration User', id: 'sys-int' }
31
- });
32
-
33
- await command.run({ name: 'Integration User', email: 'sys-int@example.com', password: 'password123' });
34
-
35
- expect(mockClient.auth.createSystemUser).toHaveBeenCalledWith({
36
- fullName: 'Integration User',
37
- email: 'sys-int@example.com',
38
- password: 'password123'
39
- });
40
- expect(command.success).toHaveBeenCalledWith('System user "Integration User" created!');
41
- expect(command.info).toHaveBeenCalledWith('ID: sys-int');
42
- });
43
-
44
- it('should handle creation failure', async () => {
45
- mockClient.auth.createSystemUser.mockRejectedValue(new Error('Email already exists'));
46
-
47
- await command.run({ name: 'Integration User', email: 'sys-int@example.com', password: 'password123' });
48
-
49
- expect(command.error).toHaveBeenCalledWith('Failed to create system user: Email already exists');
50
- });
51
- });
@@ -1,51 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import BranchesCreateCommand from '../../../../src/commands/branch/create.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('BranchesCreateCommand Integration', () => {
9
- let command: BranchesCreateCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- branches: {
17
- create: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new BranchesCreateCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'success').mockImplementation(() => { });
25
- vi.spyOn(command, 'error').mockImplementation(() => { });
26
- });
27
-
28
- it('should create branch successfully', async () => {
29
- mockClient.branches.create.mockResolvedValue({
30
- name: 'integration-branch',
31
- id: 'br-int'
32
- });
33
-
34
- await command.run({ teamId: '1', projectId: '2', name: 'integration-branch', preview: 'http://int.com' });
35
-
36
- expect(mockClient.branches.create).toHaveBeenCalledWith(1, 2, {
37
- name: 'integration-branch',
38
- previewUrl: 'http://int.com',
39
- });
40
- expect(command.success).toHaveBeenCalledWith('Branch "integration-branch" created!');
41
- expect(command.info).toHaveBeenCalledWith('ID: br-int');
42
- });
43
-
44
- it('should handle creation failure', async () => {
45
- mockClient.branches.create.mockRejectedValue(new Error('Branch exists'));
46
-
47
- await command.run({ teamId: '1', projectId: '2', name: 'main' });
48
-
49
- expect(command.error).toHaveBeenCalledWith('Failed to create branch: Branch exists');
50
- });
51
- });
@@ -1,43 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import BranchesDeleteCommand from '../../../../src/commands/branch/delete.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('BranchesDeleteCommand Integration', () => {
9
- let command: BranchesDeleteCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- branches: {
17
- delete: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new BranchesDeleteCommand([], {} as any);
23
- vi.spyOn(command, 'success').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should delete branch successfully', async () => {
28
- mockClient.branches.delete.mockResolvedValue({});
29
-
30
- await command.run({ teamId: '1', projectId: '2', branchId: '3' });
31
-
32
- expect(mockClient.branches.delete).toHaveBeenCalledWith(1, 2, 3);
33
- expect(command.success).toHaveBeenCalledWith('Branch 3 deleted.');
34
- });
35
-
36
- it('should handle deletion failure', async () => {
37
- mockClient.branches.delete.mockRejectedValue(new Error('Not found'));
38
-
39
- await command.run({ teamId: '1', projectId: '2', branchId: '3' });
40
-
41
- expect(command.error).toHaveBeenCalledWith('Failed to delete branch: Not found');
42
- });
43
- });
@@ -1,49 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import BranchesGetCommand from '../../../../src/commands/branch/get.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('BranchesGetCommand Integration', () => {
9
- let command: BranchesGetCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- branches: {
17
- get: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new BranchesGetCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should get branch details successfully', async () => {
28
- mockClient.branches.get.mockResolvedValue({
29
- id: '100',
30
- name: 'integration-main',
31
- previewUrl: 'http://int.com'
32
- });
33
-
34
- await command.run({ teamId: '1', projectId: '2', branchId: '100' });
35
-
36
- expect(mockClient.branches.get).toHaveBeenCalledWith(1, 2, 100);
37
- expect(command.info).toHaveBeenCalledWith('Branch Details:');
38
- expect(command.info).toHaveBeenCalledWith(' ID: 100');
39
- expect(command.info).toHaveBeenCalledWith(' Name: integration-main');
40
- });
41
-
42
- it('should handle get failure', async () => {
43
- mockClient.branches.get.mockRejectedValue(new Error('Not found'));
44
-
45
- await command.run({ teamId: '1', projectId: '2', branchId: '100' });
46
-
47
- expect(command.error).toHaveBeenCalledWith('Failed to get branch: Not found');
48
- });
49
- });
@@ -1,47 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import BranchesListCommand from '../../../../src/commands/branch/list.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('BranchesListCommand Integration', () => {
9
- let command: BranchesListCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- branches: {
17
- list: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new BranchesListCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should list branches successfully', async () => {
28
- mockClient.branches.list.mockResolvedValue([
29
- { id: '100', name: 'integration-main' },
30
- { id: '101', name: 'integration-dev' }
31
- ]);
32
-
33
- await command.run({ teamId: '1', projectId: '2' });
34
-
35
- expect(mockClient.branches.list).toHaveBeenCalledWith(1, 2);
36
- expect(command.info).toHaveBeenCalledWith('Branches for Project 2:');
37
- expect(command.info).toHaveBeenCalledWith('- integration-main (ID: 100)');
38
- });
39
-
40
- it('should handle list failure', async () => {
41
- mockClient.branches.list.mockRejectedValue(new Error('Network error'));
42
-
43
- await command.run({ teamId: '1', projectId: '2' });
44
-
45
- expect(command.error).toHaveBeenCalledWith('Failed to list branches: Network error');
46
- });
47
- });
@@ -1,54 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import JobsGetCommand from '../../../../src/commands/job/get.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('JobsGetCommand Integration', () => {
9
- let command: JobsGetCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- jobs: {
17
- get: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new JobsGetCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should get job details successfully', async () => {
28
- mockClient.jobs.get.mockResolvedValue({
29
- id: '123',
30
- type: 'build',
31
- status: 'success',
32
- createdAt: '2023-01-01T00:00:00Z',
33
- finishedAt: '2023-01-01T00:05:00Z',
34
- startedAt: '2023-01-01T00:01:00Z',
35
- completedAt: '2023-01-01T00:05:00Z',
36
- queue: 'default'
37
- });
38
-
39
- await command.run({ teamId: '1', projectId: '2', branchId: '3', jobId: '123' });
40
-
41
- expect(mockClient.jobs.get).toHaveBeenCalledWith(1, 2, 3, 123);
42
- expect(command.info).toHaveBeenCalledWith('Job Details:');
43
- expect(command.info).toHaveBeenCalledWith(' ID: 123');
44
- expect(command.info).toHaveBeenCalledWith(' Status: success');
45
- });
46
-
47
- it('should handle get failure', async () => {
48
- mockClient.jobs.get.mockRejectedValue(new Error('Job not found'));
49
-
50
- await command.run({ teamId: '1', projectId: '2', branchId: '3', jobId: '123' });
51
-
52
- expect(command.error).toHaveBeenCalledWith('Failed to get job: Job not found');
53
- });
54
- });
@@ -1,47 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import JobsListCommand from '../../../../src/commands/job/list.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('JobsListCommand Integration', () => {
9
- let command: JobsListCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- jobs: {
17
- list: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new JobsListCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should list jobs successfully', async () => {
28
- mockClient.jobs.list.mockResolvedValue([
29
- { id: '101', status: 'running', type: 'build' },
30
- { id: '102', status: 'pending', type: 'deploy' }
31
- ]);
32
-
33
- await command.run({ teamId: '1', projectId: '2', branchId: '3' });
34
-
35
- expect(mockClient.jobs.list).toHaveBeenCalledWith(1, 2, 3);
36
- expect(command.info).toHaveBeenCalledWith('Jobs for Branch 3:');
37
- expect(command.info).toHaveBeenCalledWith('101 - build [running] (Started: Waiting)');
38
- });
39
-
40
- it('should handle list failure', async () => {
41
- mockClient.jobs.list.mockRejectedValue(new Error('Network error'));
42
-
43
- await command.run({ teamId: '1', projectId: '2', branchId: '3' });
44
-
45
- expect(command.error).toHaveBeenCalledWith('Failed to list jobs: Network error');
46
- });
47
- });
@@ -1,47 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import JobsLogsCommand from '../../../../src/commands/job/logs.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('JobsLogsCommand Integration', () => {
9
- let command: JobsLogsCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- jobs: {
17
- getLogs: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new JobsLogsCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should get job logs successfully', async () => {
28
- mockClient.jobs.getLogs.mockResolvedValue([
29
- { timestamp: '2023T12:00:00', level: 'info', message: 'Build started' },
30
- { timestamp: '2023T12:01:00', level: 'error', message: 'Build failed' }
31
- ]);
32
-
33
- await command.run({ teamId: '1', projectId: '2', branchId: '3', jobId: '123' });
34
-
35
- expect(mockClient.jobs.getLogs).toHaveBeenCalledWith(1, 2, 3, 123);
36
- expect(command.info).toHaveBeenCalledWith(expect.stringContaining('Build started'));
37
- expect(command.error).toHaveBeenCalledWith(expect.stringContaining('Build failed'));
38
- });
39
-
40
- it('should handle log failure', async () => {
41
- mockClient.jobs.getLogs.mockRejectedValue(new Error('Logs unavailable'));
42
-
43
- await command.run({ teamId: '1', projectId: '2', branchId: '3', jobId: '123' });
44
-
45
- expect(command.error).toHaveBeenCalledWith('Failed to get logs: Logs unavailable');
46
- });
47
- });