@nexical/cli 0.1.6 → 0.10.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 (236) hide show
  1. package/.github/workflows/deploy.yml +3 -3
  2. package/README.md +317 -104
  3. package/dist/chunk-JYASTIIW.js +42 -0
  4. package/dist/chunk-JYASTIIW.js.map +1 -0
  5. package/dist/chunk-LZ3YQWAR.js +2204 -0
  6. package/dist/chunk-LZ3YQWAR.js.map +1 -0
  7. package/dist/chunk-OKXOCNXP.js +105 -0
  8. package/dist/chunk-OKXOCNXP.js.map +1 -0
  9. package/dist/chunk-OYFWMYPG.js +52 -0
  10. package/dist/chunk-OYFWMYPG.js.map +1 -0
  11. package/dist/chunk-WKERTCM6.js +74 -0
  12. package/dist/chunk-WKERTCM6.js.map +1 -0
  13. package/dist/index.js +33 -6
  14. package/dist/index.js.map +1 -1
  15. package/dist/src/commands/init.d.ts +11 -0
  16. package/dist/src/commands/init.js +88 -0
  17. package/dist/src/commands/init.js.map +1 -0
  18. package/dist/src/commands/module/add.d.ts +14 -0
  19. package/dist/src/commands/module/add.js +136 -0
  20. package/dist/src/commands/module/add.js.map +1 -0
  21. package/dist/src/commands/module/list.d.ts +10 -0
  22. package/dist/src/commands/module/list.js +73 -0
  23. package/dist/src/commands/module/list.js.map +1 -0
  24. package/dist/src/commands/module/remove.d.ts +12 -0
  25. package/dist/src/commands/module/remove.js +71 -0
  26. package/dist/src/commands/module/remove.js.map +1 -0
  27. package/dist/src/commands/module/update.d.ts +11 -0
  28. package/dist/src/commands/module/update.js +52 -0
  29. package/dist/src/commands/module/update.js.map +1 -0
  30. package/dist/src/commands/run.d.ts +11 -0
  31. package/dist/src/commands/run.js +93 -0
  32. package/dist/src/commands/run.js.map +1 -0
  33. package/dist/src/utils/discovery.d.ts +13 -0
  34. package/dist/src/utils/discovery.js +9 -0
  35. package/dist/src/utils/git.d.ts +16 -0
  36. package/dist/src/utils/git.js +29 -0
  37. package/dist/src/utils/git.js.map +1 -0
  38. package/dist/src/utils/url-resolver.d.ts +15 -0
  39. package/dist/src/utils/url-resolver.js +9 -0
  40. package/dist/src/utils/url-resolver.js.map +1 -0
  41. package/index.ts +29 -5
  42. package/package.json +32 -30
  43. package/src/commands/init.ts +85 -0
  44. package/src/commands/module/add.ts +169 -0
  45. package/src/commands/module/list.ts +69 -0
  46. package/src/commands/module/remove.ts +74 -0
  47. package/src/commands/module/update.ts +50 -0
  48. package/src/commands/run.ts +98 -0
  49. package/src/utils/discovery.ts +134 -0
  50. package/src/utils/git.ts +65 -0
  51. package/src/utils/url-resolver.ts +57 -0
  52. package/test/e2e/lifecycle.e2e.test.ts +152 -0
  53. package/test/integration/commands/init.integration.test.ts +82 -0
  54. package/test/integration/commands/module.integration.test.ts +144 -0
  55. package/test/integration/commands/run.integration.test.ts +90 -0
  56. package/test/integration/utils/command-loading.integration.test.ts +80 -0
  57. package/test/unit/commands/init.test.ts +153 -0
  58. package/test/unit/commands/module/add.test.ts +262 -0
  59. package/test/unit/commands/module/list.test.ts +115 -0
  60. package/test/unit/commands/module/remove.test.ts +89 -0
  61. package/test/unit/commands/module/update.test.ts +91 -0
  62. package/test/unit/commands/run.test.ts +252 -0
  63. package/test/unit/utils/command-discovery.test.ts +176 -0
  64. package/test/unit/utils/git.test.ts +152 -0
  65. package/test/unit/utils/integration-helpers.test.ts +72 -0
  66. package/test/unit/utils/url-resolver.test.ts +39 -0
  67. package/test/utils/integration-helpers.ts +66 -0
  68. package/vitest.e2e.config.ts +0 -1
  69. package/dist/chunk-JDRAVUKK.js +0 -48
  70. package/dist/chunk-JDRAVUKK.js.map +0 -1
  71. package/dist/src/commands/admin/create-user.d.ts +0 -15
  72. package/dist/src/commands/admin/create-user.js +0 -49
  73. package/dist/src/commands/admin/create-user.js.map +0 -1
  74. package/dist/src/commands/branch/create.d.ts +0 -19
  75. package/dist/src/commands/branch/create.js +0 -59
  76. package/dist/src/commands/branch/create.js.map +0 -1
  77. package/dist/src/commands/branch/delete.d.ts +0 -15
  78. package/dist/src/commands/branch/delete.js +0 -50
  79. package/dist/src/commands/branch/delete.js.map +0 -1
  80. package/dist/src/commands/branch/get.d.ts +0 -15
  81. package/dist/src/commands/branch/get.js +0 -53
  82. package/dist/src/commands/branch/get.js.map +0 -1
  83. package/dist/src/commands/branch/list.d.ts +0 -15
  84. package/dist/src/commands/branch/list.js +0 -51
  85. package/dist/src/commands/branch/list.js.map +0 -1
  86. package/dist/src/commands/job/get.d.ts +0 -15
  87. package/dist/src/commands/job/get.js +0 -62
  88. package/dist/src/commands/job/get.js.map +0 -1
  89. package/dist/src/commands/job/list.d.ts +0 -15
  90. package/dist/src/commands/job/list.js +0 -57
  91. package/dist/src/commands/job/list.js.map +0 -1
  92. package/dist/src/commands/job/logs.d.ts +0 -15
  93. package/dist/src/commands/job/logs.js +0 -67
  94. package/dist/src/commands/job/logs.js.map +0 -1
  95. package/dist/src/commands/job/trigger.d.ts +0 -19
  96. package/dist/src/commands/job/trigger.js +0 -74
  97. package/dist/src/commands/job/trigger.js.map +0 -1
  98. package/dist/src/commands/login.d.ts +0 -8
  99. package/dist/src/commands/login.js +0 -31
  100. package/dist/src/commands/login.js.map +0 -1
  101. package/dist/src/commands/project/create.d.ts +0 -24
  102. package/dist/src/commands/project/create.js +0 -63
  103. package/dist/src/commands/project/create.js.map +0 -1
  104. package/dist/src/commands/project/delete.d.ts +0 -20
  105. package/dist/src/commands/project/delete.js +0 -58
  106. package/dist/src/commands/project/delete.js.map +0 -1
  107. package/dist/src/commands/project/get.d.ts +0 -15
  108. package/dist/src/commands/project/get.js +0 -49
  109. package/dist/src/commands/project/get.js.map +0 -1
  110. package/dist/src/commands/project/list.d.ts +0 -15
  111. package/dist/src/commands/project/list.js +0 -45
  112. package/dist/src/commands/project/list.js.map +0 -1
  113. package/dist/src/commands/project/update.d.ts +0 -19
  114. package/dist/src/commands/project/update.js +0 -66
  115. package/dist/src/commands/project/update.js.map +0 -1
  116. package/dist/src/commands/team/create.d.ts +0 -19
  117. package/dist/src/commands/team/create.js +0 -45
  118. package/dist/src/commands/team/create.js.map +0 -1
  119. package/dist/src/commands/team/delete.d.ts +0 -20
  120. package/dist/src/commands/team/delete.js +0 -52
  121. package/dist/src/commands/team/delete.js.map +0 -1
  122. package/dist/src/commands/team/get.d.ts +0 -15
  123. package/dist/src/commands/team/get.js +0 -42
  124. package/dist/src/commands/team/get.js.map +0 -1
  125. package/dist/src/commands/team/list.d.ts +0 -8
  126. package/dist/src/commands/team/list.js +0 -30
  127. package/dist/src/commands/team/list.js.map +0 -1
  128. package/dist/src/commands/team/member/invite.d.ts +0 -20
  129. package/dist/src/commands/team/member/invite.js +0 -54
  130. package/dist/src/commands/team/member/invite.js.map +0 -1
  131. package/dist/src/commands/team/member/remove.d.ts +0 -15
  132. package/dist/src/commands/team/member/remove.js +0 -43
  133. package/dist/src/commands/team/member/remove.js.map +0 -1
  134. package/dist/src/commands/team/update.d.ts +0 -19
  135. package/dist/src/commands/team/update.js +0 -55
  136. package/dist/src/commands/team/update.js.map +0 -1
  137. package/dist/src/commands/token/generate.d.ts +0 -19
  138. package/dist/src/commands/token/generate.js +0 -48
  139. package/dist/src/commands/token/generate.js.map +0 -1
  140. package/dist/src/commands/token/list.d.ts +0 -8
  141. package/dist/src/commands/token/list.js +0 -31
  142. package/dist/src/commands/token/list.js.map +0 -1
  143. package/dist/src/commands/token/revoke.d.ts +0 -15
  144. package/dist/src/commands/token/revoke.js +0 -38
  145. package/dist/src/commands/token/revoke.js.map +0 -1
  146. package/dist/src/commands/whoami.d.ts +0 -8
  147. package/dist/src/commands/whoami.js +0 -26
  148. package/dist/src/commands/whoami.js.map +0 -1
  149. package/dist/src/utils/nexical-client.d.ts +0 -10
  150. package/dist/src/utils/nexical-client.js +0 -12
  151. package/src/commands/admin/create-user.ts +0 -46
  152. package/src/commands/branch/create.ts +0 -57
  153. package/src/commands/branch/delete.ts +0 -47
  154. package/src/commands/branch/get.ts +0 -50
  155. package/src/commands/branch/list.ts +0 -50
  156. package/src/commands/job/get.ts +0 -59
  157. package/src/commands/job/list.ts +0 -56
  158. package/src/commands/job/logs.ts +0 -67
  159. package/src/commands/job/trigger.ts +0 -73
  160. package/src/commands/login.ts +0 -31
  161. package/src/commands/project/create.ts +0 -61
  162. package/src/commands/project/delete.ts +0 -56
  163. package/src/commands/project/get.ts +0 -46
  164. package/src/commands/project/list.ts +0 -44
  165. package/src/commands/project/update.ts +0 -63
  166. package/src/commands/team/create.ts +0 -43
  167. package/src/commands/team/delete.ts +0 -50
  168. package/src/commands/team/get.ts +0 -39
  169. package/src/commands/team/list.ts +0 -26
  170. package/src/commands/team/member/invite.ts +0 -56
  171. package/src/commands/team/member/remove.ts +0 -40
  172. package/src/commands/team/update.ts +0 -53
  173. package/src/commands/token/generate.ts +0 -45
  174. package/src/commands/token/list.ts +0 -27
  175. package/src/commands/token/revoke.ts +0 -35
  176. package/src/commands/whoami.ts +0 -21
  177. package/src/utils/nexical-client.ts +0 -47
  178. package/test/e2e/auth.e2e.test.ts +0 -46
  179. package/test/e2e/job-workflow.e2e.test.ts +0 -33
  180. package/test/e2e/project-lifecycle.e2e.test.ts +0 -48
  181. package/test/e2e/setup.ts +0 -237
  182. package/test/e2e/utils.ts +0 -33
  183. package/test/integration/commands/admin/create-user.test.ts +0 -51
  184. package/test/integration/commands/branch/create.test.ts +0 -51
  185. package/test/integration/commands/branch/delete.test.ts +0 -43
  186. package/test/integration/commands/branch/get.test.ts +0 -49
  187. package/test/integration/commands/branch/list.test.ts +0 -47
  188. package/test/integration/commands/job/get.test.ts +0 -54
  189. package/test/integration/commands/job/list.test.ts +0 -47
  190. package/test/integration/commands/job/logs.test.ts +0 -47
  191. package/test/integration/commands/job/trigger.test.ts +0 -57
  192. package/test/integration/commands/login.test.ts +0 -62
  193. package/test/integration/commands/project/create.test.ts +0 -53
  194. package/test/integration/commands/project/delete.test.ts +0 -43
  195. package/test/integration/commands/project/get.test.ts +0 -51
  196. package/test/integration/commands/project/list.test.ts +0 -47
  197. package/test/integration/commands/project/update.test.ts +0 -53
  198. package/test/integration/commands/team/create.test.ts +0 -53
  199. package/test/integration/commands/team/delete.test.ts +0 -43
  200. package/test/integration/commands/team/get.test.ts +0 -50
  201. package/test/integration/commands/team/list.test.ts +0 -47
  202. package/test/integration/commands/team/member/invite.test.ts +0 -46
  203. package/test/integration/commands/team/member/remove.test.ts +0 -43
  204. package/test/integration/commands/team/update.test.ts +0 -50
  205. package/test/integration/commands/token/generate.test.ts +0 -51
  206. package/test/integration/commands/token/list.test.ts +0 -47
  207. package/test/integration/commands/token/revoke.test.ts +0 -43
  208. package/test/integration/commands/whoami.test.ts +0 -49
  209. package/test/unit/commands/admin/create-user.test.ts +0 -51
  210. package/test/unit/commands/branch/create.test.ts +0 -57
  211. package/test/unit/commands/branch/delete.test.ts +0 -49
  212. package/test/unit/commands/branch/get.test.ts +0 -67
  213. package/test/unit/commands/branch/list.test.ts +0 -62
  214. package/test/unit/commands/job/get.test.ts +0 -76
  215. package/test/unit/commands/job/list.test.ts +0 -62
  216. package/test/unit/commands/job/logs.test.ts +0 -60
  217. package/test/unit/commands/job/trigger.test.ts +0 -75
  218. package/test/unit/commands/login.test.ts +0 -64
  219. package/test/unit/commands/project/create.test.ts +0 -64
  220. package/test/unit/commands/project/delete.test.ts +0 -72
  221. package/test/unit/commands/project/get.test.ts +0 -73
  222. package/test/unit/commands/project/list.test.ts +0 -62
  223. package/test/unit/commands/project/update.test.ts +0 -58
  224. package/test/unit/commands/team/create.test.ts +0 -68
  225. package/test/unit/commands/team/delete.test.ts +0 -71
  226. package/test/unit/commands/team/get.test.ts +0 -70
  227. package/test/unit/commands/team/list.test.ts +0 -56
  228. package/test/unit/commands/team/member/invite.test.ts +0 -52
  229. package/test/unit/commands/team/member/remove.test.ts +0 -49
  230. package/test/unit/commands/team/update.test.ts +0 -63
  231. package/test/unit/commands/token/generate.test.ts +0 -65
  232. package/test/unit/commands/token/list.test.ts +0 -58
  233. package/test/unit/commands/token/revoke.test.ts +0 -49
  234. package/test/unit/commands/whoami.test.ts +0 -49
  235. package/test/unit/utils/nexical-client.test.ts +0 -113
  236. /package/dist/src/utils/{nexical-client.js.map → discovery.js.map} +0 -0
@@ -1,49 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import TeamsMembersRemoveCommand from '../../../../../src/commands/team/member/remove.js';
4
- import { getClient } from '../../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../../src/utils/nexical-client.js');
7
-
8
- describe('TeamsMembersRemoveCommand', () => {
9
- let command: TeamsMembersRemoveCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- teams: {
17
- removeMember: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new TeamsMembersRemoveCommand([], {} as any);
23
- vi.spyOn(command, 'success').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should remove member successfully', async () => {
28
- mockClient.teams.removeMember.mockResolvedValue({});
29
-
30
- await command.run({ teamId: '1', userId: 'user-123' });
31
-
32
- expect(mockClient.teams.removeMember).toHaveBeenCalledWith(1, 'user-123');
33
- expect(command.success).toHaveBeenCalledWith('User user-123 removed from team 1.');
34
- });
35
-
36
- it('should validate Team ID', async () => {
37
- await command.run({ teamId: 'invalid', userId: 'user-123' });
38
- expect(command.error).toHaveBeenCalledWith('Team ID must be a number.');
39
- expect(mockClient.teams.removeMember).not.toHaveBeenCalled();
40
- });
41
-
42
- it('should handle removal failure', async () => {
43
- mockClient.teams.removeMember.mockRejectedValue(new Error('User not found'));
44
-
45
- await command.run({ teamId: '1', userId: 'user-123' });
46
-
47
- expect(command.error).toHaveBeenCalledWith('Failed to remove member: User not found');
48
- });
49
- });
@@ -1,63 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import TeamsUpdateCommand from '../../../../src/commands/team/update.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('TeamsUpdateCommand', () => {
9
- let command: TeamsUpdateCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- teams: {
17
- update: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new TeamsUpdateCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'success').mockImplementation(() => { });
25
- vi.spyOn(command, 'warn').mockImplementation(() => { });
26
- vi.spyOn(command, 'error').mockImplementation(() => { });
27
- });
28
-
29
- it('should update team successfully', async () => {
30
- mockClient.teams.update.mockResolvedValue({
31
- id: '1',
32
- name: 'New Name'
33
- });
34
-
35
- await command.run({ teamId: '1', name: 'New Name' });
36
-
37
- expect(mockClient.teams.update).toHaveBeenCalledWith(1, {
38
- name: 'New Name',
39
- });
40
- expect(command.success).toHaveBeenCalledWith('Team 1 updated!');
41
- expect(command.info).toHaveBeenCalledWith('Name: New Name');
42
- });
43
-
44
- it('should warn if no updates provided', async () => {
45
- await command.run({ teamId: '1' });
46
- expect(command.warn).toHaveBeenCalledWith('No updates provided. Use --name or --slug.');
47
- expect(mockClient.teams.update).not.toHaveBeenCalled();
48
- });
49
-
50
- it('should validate Team ID', async () => {
51
- await command.run({ teamId: 'invalid' });
52
- expect(command.error).toHaveBeenCalledWith('Team ID must be a number.');
53
- expect(mockClient.teams.update).not.toHaveBeenCalled();
54
- });
55
-
56
- it('should handle update failure', async () => {
57
- mockClient.teams.update.mockRejectedValue(new Error('Update failed'));
58
-
59
- await command.run({ teamId: '1', name: 'N' });
60
-
61
- expect(command.error).toHaveBeenCalledWith('Failed to update team: Update failed');
62
- });
63
- });
@@ -1,65 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import AuthTokensGenerateCommand from '../../../../src/commands/token/generate.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('AuthTokensGenerateCommand', () => {
9
- let command: AuthTokensGenerateCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- auth: {
17
- generateToken: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new AuthTokensGenerateCommand([], {} as any);
23
- vi.spyOn(command, 'success').mockImplementation(() => { });
24
- vi.spyOn(command, 'warn').mockImplementation(() => { });
25
- vi.spyOn(command, 'error').mockImplementation(() => { });
26
- });
27
-
28
- it('should generate token successfully', async () => {
29
- mockClient.auth.generateToken.mockResolvedValue({
30
- name: 'My Token',
31
- token: 'secret-token-value'
32
- });
33
-
34
- await command.run({ name: 'My Token', scopes: 'read,write' });
35
-
36
- expect(mockClient.auth.generateToken).toHaveBeenCalledWith({
37
- name: 'My Token',
38
- scopes: ['read', 'write'],
39
- });
40
- expect(command.success).toHaveBeenCalledWith('Token "My Token" generated!');
41
- expect(command.warn).toHaveBeenCalledWith('Token: secret-token-value');
42
- });
43
-
44
- it('should generate token without scopes', async () => {
45
- mockClient.auth.generateToken.mockResolvedValue({
46
- name: 'My Token',
47
- token: 'secret-token-value'
48
- });
49
-
50
- await command.run({ name: 'My Token' });
51
-
52
- expect(mockClient.auth.generateToken).toHaveBeenCalledWith({
53
- name: 'My Token',
54
- scopes: undefined,
55
- });
56
- });
57
-
58
- it('should handle generation failure', async () => {
59
- mockClient.auth.generateToken.mockRejectedValue(new Error('Limit reached'));
60
-
61
- await command.run({ name: 'My Token' });
62
-
63
- expect(command.error).toHaveBeenCalledWith('Failed to generate token: Limit reached');
64
- });
65
- });
@@ -1,58 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import AuthTokensListCommand from '../../../../src/commands/token/list.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('AuthTokensListCommand', () => {
9
- let command: AuthTokensListCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- auth: {
17
- listTokens: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new AuthTokensListCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should list tokens successfully', async () => {
28
- mockClient.auth.listTokens.mockResolvedValue({
29
- tokens: [
30
- { name: 'Token 1', tokenPrefix: 'abc', expiresAt: '2023-01-01' },
31
- { name: 'Token 2', tokenPrefix: 'def' }
32
- ]
33
- });
34
-
35
- await command.run();
36
-
37
- expect(mockClient.auth.listTokens).toHaveBeenCalled();
38
- expect(command.info).toHaveBeenCalledWith('Your API Tokens:');
39
- expect(command.info).toHaveBeenCalledWith('- Token 1 (abc...) [Expires: 2023-01-01]');
40
- expect(command.info).toHaveBeenCalledWith('- Token 2 (def...) [Expires: Never]');
41
- });
42
-
43
- it('should handle empty list', async () => {
44
- mockClient.auth.listTokens.mockResolvedValue({ tokens: [] });
45
-
46
- await command.run();
47
-
48
- expect(command.info).toHaveBeenCalledWith('No API tokens found.');
49
- });
50
-
51
- it('should handle list failure', async () => {
52
- mockClient.auth.listTokens.mockRejectedValue(new Error('Network error'));
53
-
54
- await command.run();
55
-
56
- expect(command.error).toHaveBeenCalledWith('Failed to list tokens: Network error');
57
- });
58
- });
@@ -1,49 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import AuthTokensRevokeCommand from '../../../../src/commands/token/revoke.js';
4
- import { getClient } from '../../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../../src/utils/nexical-client.js');
7
-
8
- describe('AuthTokensRevokeCommand', () => {
9
- let command: AuthTokensRevokeCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- auth: {
17
- revokeToken: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new AuthTokensRevokeCommand([], {} as any);
23
- vi.spyOn(command, 'success').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should revoke token successfully', async () => {
28
- mockClient.auth.revokeToken.mockResolvedValue({});
29
-
30
- await command.run({ id: '123' });
31
-
32
- expect(mockClient.auth.revokeToken).toHaveBeenCalledWith(123);
33
- expect(command.success).toHaveBeenCalledWith('Token 123 revoked.');
34
- });
35
-
36
- it('should validate ID', async () => {
37
- await command.run({ id: 'invalid' });
38
- expect(command.error).toHaveBeenCalledWith('Token ID must be a number.');
39
- expect(mockClient.auth.revokeToken).not.toHaveBeenCalled();
40
- });
41
-
42
- it('should handle revocation failure', async () => {
43
- mockClient.auth.revokeToken.mockRejectedValue(new Error('Token not found'));
44
-
45
- await command.run({ id: '123' });
46
-
47
- expect(command.error).toHaveBeenCalledWith('Failed to revoke token: Token not found');
48
- });
49
- });
@@ -1,49 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import WhoamiCommand from '../../../src/commands/whoami.js';
4
- import { getClient } from '../../../src/utils/nexical-client.js';
5
-
6
- vi.mock('../../../src/utils/nexical-client.js');
7
-
8
- describe('WhoamiCommand', () => {
9
- let command: WhoamiCommand;
10
- let mockClient: any;
11
-
12
- beforeEach(() => {
13
- vi.resetAllMocks();
14
-
15
- mockClient = {
16
- users: {
17
- me: vi.fn(),
18
- },
19
- };
20
- vi.mocked(getClient).mockReturnValue(mockClient);
21
-
22
- command = new WhoamiCommand([], {} as any);
23
- vi.spyOn(command, 'info').mockImplementation(() => { });
24
- vi.spyOn(command, 'error').mockImplementation(() => { });
25
- });
26
-
27
- it('should display user info when logged in', async () => {
28
- mockClient.users.me.mockResolvedValue({
29
- fullName: 'Test User',
30
- email: 'test@example.com',
31
- id: 'user-123'
32
- });
33
-
34
- await command.run();
35
-
36
- expect(command.info).toHaveBeenCalledWith('Logged in as:');
37
- expect(command.info).toHaveBeenCalledWith(' Name: Test User');
38
- expect(command.info).toHaveBeenCalledWith(' Email: test@example.com');
39
- expect(command.info).toHaveBeenCalledWith(' ID: user-123');
40
- });
41
-
42
- it('should display error when not logged in', async () => {
43
- mockClient.users.me.mockRejectedValue(new Error('Unauthorized'));
44
-
45
- await command.run();
46
-
47
- expect(command.error).toHaveBeenCalledWith('Not logged in or token expired. Run `astrical login`.');
48
- });
49
- });
@@ -1,113 +0,0 @@
1
-
2
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
- import { getConfig, saveToken, getClient } from '../../../src/utils/nexical-client.js';
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import os from 'node:os';
7
- import { NexicalClient } from '@nexical/sdk';
8
-
9
- vi.mock('node:fs');
10
- vi.mock('node:fs');
11
- vi.mock('node:os', () => ({
12
- default: {
13
- homedir: vi.fn(() => '/home/user')
14
- }
15
- }));
16
- vi.mock('@nexical/sdk');
17
-
18
- describe('nexical-client', () => {
19
- const mockHomeDir = '/home/user';
20
- const configDir = path.join(mockHomeDir, '.nexical');
21
- const configFile = path.join(configDir, 'config.json');
22
-
23
- beforeEach(() => {
24
- vi.resetAllMocks();
25
- vi.stubEnv('HOME', '/home/user');
26
- // os.homedir is already mocked by factory
27
- });
28
-
29
- afterEach(() => {
30
- vi.unstubAllEnvs();
31
- });
32
-
33
- it('should use os.homedir() if HOME env var is not set', () => {
34
- vi.unstubAllEnvs();
35
- vi.stubEnv('HOME', '');
36
-
37
- // Trigger path resolution
38
- getConfig();
39
-
40
- expect(os.homedir).toHaveBeenCalled();
41
- });
42
-
43
- describe('getConfig', () => {
44
- it('should return empty object if config file does not exist', () => {
45
- vi.mocked(fs.existsSync).mockReturnValue(false);
46
- expect(getConfig()).toEqual({});
47
- expect(fs.existsSync).toHaveBeenCalledWith(configFile);
48
- });
49
-
50
- it('should return parsed config if file exists', () => {
51
- vi.mocked(fs.existsSync).mockReturnValue(true);
52
- vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({ token: 'test-token' }));
53
- expect(getConfig()).toEqual({ token: 'test-token' });
54
- expect(fs.readFileSync).toHaveBeenCalledWith(configFile, 'utf-8');
55
- });
56
-
57
- it('should return empty object on JSON parse error', () => {
58
- vi.mocked(fs.existsSync).mockReturnValue(true);
59
- vi.mocked(fs.readFileSync).mockReturnValue('invalid-json');
60
- expect(getConfig()).toEqual({});
61
- });
62
- });
63
-
64
- describe('saveToken', () => {
65
- it('should create directory if it does not exist', () => {
66
- vi.mocked(fs.existsSync)
67
- .mockReturnValueOnce(false) // config dir check
68
- .mockReturnValueOnce(false); // config file check (inside getConfig)
69
-
70
- saveToken('new-token');
71
-
72
- expect(fs.mkdirSync).toHaveBeenCalledWith(configDir, { recursive: true });
73
- expect(fs.writeFileSync).toHaveBeenCalledWith(
74
- configFile,
75
- JSON.stringify({ token: 'new-token' }, null, 2)
76
- );
77
- });
78
-
79
- it('should update existing config', () => {
80
- vi.mocked(fs.existsSync)
81
- .mockReturnValueOnce(true) // config dir check
82
- .mockReturnValueOnce(true); // config file check (inside getConfig)
83
- vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({ other: 'value' }));
84
-
85
- saveToken('new-token');
86
-
87
- expect(fs.mkdirSync).not.toHaveBeenCalled();
88
- expect(fs.writeFileSync).toHaveBeenCalledWith(
89
- configFile,
90
- JSON.stringify({ other: 'value', token: 'new-token' }, null, 2)
91
- );
92
- });
93
- });
94
-
95
- describe('getClient', () => {
96
- it('should return NexicalClient instance with token from config', () => {
97
- vi.mocked(fs.existsSync).mockReturnValue(true);
98
- vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({ token: 'saved-token' }));
99
-
100
- getClient();
101
-
102
- expect(NexicalClient).toHaveBeenCalledWith({ token: 'saved-token' });
103
- });
104
-
105
- it('should return NexicalClient instance without token if config missing', () => {
106
- vi.mocked(fs.existsSync).mockReturnValue(false);
107
-
108
- getClient();
109
-
110
- expect(NexicalClient).toHaveBeenCalledWith({ token: undefined });
111
- });
112
- });
113
- });