@capawesome/cli 1.14.0-dev.1f912c9.1755635879 → 1.14.0-dev.3b0fc7e.1755934102

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 (38) hide show
  1. package/README.md +4 -0
  2. package/dist/commands/apps/bundles/create.js +12 -10
  3. package/dist/commands/apps/bundles/create.test.js +20 -18
  4. package/dist/commands/apps/bundles/delete.js +13 -16
  5. package/dist/commands/apps/bundles/delete.test.js +4 -5
  6. package/dist/commands/apps/bundles/update.js +13 -21
  7. package/dist/commands/apps/bundles/update.test.js +7 -8
  8. package/dist/commands/apps/channels/create.js +16 -6
  9. package/dist/commands/apps/channels/create.test.js +12 -8
  10. package/dist/commands/apps/channels/delete.js +15 -18
  11. package/dist/commands/apps/channels/delete.test.js +7 -6
  12. package/dist/commands/apps/channels/get.js +34 -42
  13. package/dist/commands/apps/channels/get.test.js +20 -21
  14. package/dist/commands/apps/channels/list.js +20 -28
  15. package/dist/commands/apps/channels/list.test.js +9 -11
  16. package/dist/commands/apps/channels/update.js +10 -18
  17. package/dist/commands/apps/channels/update.test.js +7 -8
  18. package/dist/commands/apps/create.js +11 -14
  19. package/dist/commands/apps/create.test.js +8 -8
  20. package/dist/commands/apps/delete.js +10 -13
  21. package/dist/commands/apps/delete.test.js +7 -6
  22. package/dist/commands/apps/devices/delete.js +13 -16
  23. package/dist/commands/apps/devices/delete.test.js +4 -5
  24. package/dist/commands/login.js +11 -11
  25. package/dist/commands/login.test.js +8 -14
  26. package/dist/commands/logout.js +1 -1
  27. package/dist/commands/logout.test.js +2 -2
  28. package/dist/commands/manifests/generate.test.js +5 -5
  29. package/dist/commands/organizations/create.js +25 -0
  30. package/dist/commands/organizations/create.test.js +80 -0
  31. package/dist/commands/whoami.js +10 -4
  32. package/dist/commands/whoami.test.js +2 -2
  33. package/dist/index.js +4 -0
  34. package/dist/services/authorization-service.js +1 -1
  35. package/dist/services/organizations.js +8 -0
  36. package/dist/utils/private-key.js +23 -0
  37. package/package.json +2 -2
  38. /package/dist/utils/{userConfig.js → user-config.js} +0 -0
@@ -1,9 +1,8 @@
1
+ import appChannelsService from '../../../services/app-channels.js';
2
+ import authorizationService from '../../../services/authorization-service.js';
1
3
  import { defineCommand, defineOptions } from '@robingenz/zli';
2
4
  import consola from 'consola';
3
5
  import { z } from 'zod';
4
- import appChannelsService from '../../../services/app-channels.js';
5
- import authorizationService from '../../../services/authorization-service.js';
6
- import { getMessageFromUnknownError } from '../../../utils/error.js';
7
6
  export default defineCommand({
8
7
  description: 'Get an existing app channel.',
9
8
  options: defineOptions(z.object({
@@ -26,47 +25,40 @@ export default defineCommand({
26
25
  consola.error('You must provide a channel ID or name.');
27
26
  process.exit(1);
28
27
  }
29
- try {
30
- let channel;
31
- if (channelId) {
32
- channel = await appChannelsService.findOneById({
33
- appId,
34
- id: channelId,
35
- });
36
- }
37
- else if (name) {
38
- const foundChannels = await appChannelsService.findAll({
39
- appId,
40
- name,
41
- });
42
- channel = foundChannels[0];
43
- }
44
- if (!channel) {
45
- consola.error('Channel not found.');
46
- process.exit(1);
47
- }
48
- if (json) {
49
- console.log(JSON.stringify({
50
- id: channel.id,
51
- name: channel.name,
52
- totalAppBundleLimit: channel.totalAppBundleLimit,
53
- appId: channel.appId,
54
- }, null, 2));
55
- }
56
- else {
57
- console.table({
58
- id: channel.id,
59
- name: channel.name,
60
- totalAppBundleLimit: channel.totalAppBundleLimit,
61
- appId: channel.appId,
62
- });
63
- consola.success('Channel retrieved successfully.');
64
- }
28
+ let channel;
29
+ if (channelId) {
30
+ channel = await appChannelsService.findOneById({
31
+ appId,
32
+ id: channelId,
33
+ });
65
34
  }
66
- catch (error) {
67
- const message = getMessageFromUnknownError(error);
68
- consola.error(message);
35
+ else if (name) {
36
+ const foundChannels = await appChannelsService.findAll({
37
+ appId,
38
+ name,
39
+ });
40
+ channel = foundChannels[0];
41
+ }
42
+ if (!channel) {
43
+ consola.error('Channel not found.');
69
44
  process.exit(1);
70
45
  }
46
+ if (json) {
47
+ console.log(JSON.stringify({
48
+ id: channel.id,
49
+ name: channel.name,
50
+ totalAppBundleLimit: channel.totalAppBundleLimit,
51
+ appId: channel.appId,
52
+ }, null, 2));
53
+ }
54
+ else {
55
+ console.table({
56
+ id: channel.id,
57
+ name: channel.name,
58
+ totalAppBundleLimit: channel.totalAppBundleLimit,
59
+ appId: channel.appId,
60
+ });
61
+ consola.success('Channel retrieved successfully.');
62
+ }
71
63
  },
72
64
  });
@@ -1,12 +1,12 @@
1
1
  import { DEFAULT_API_BASE_URL } from '../../../config/consts.js';
2
2
  import authorizationService from '../../../services/authorization-service.js';
3
- import userConfig from '../../../utils/userConfig.js';
3
+ import userConfig from '../../../utils/user-config.js';
4
4
  import consola from 'consola';
5
5
  import nock from 'nock';
6
6
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
7
  import getChannelCommand from './get.js';
8
8
  // Mock dependencies
9
- vi.mock('@/utils/userConfig.js');
9
+ vi.mock('@/utils/user-config.js');
10
10
  vi.mock('@/services/authorization-service.js');
11
11
  vi.mock('consola');
12
12
  describe('apps-channels-get', () => {
@@ -18,7 +18,9 @@ describe('apps-channels-get', () => {
18
18
  mockUserConfig.read.mockReturnValue({ token: 'test-token' });
19
19
  mockAuthorizationService.hasAuthorizationToken.mockReturnValue(true);
20
20
  mockAuthorizationService.getCurrentAuthorizationToken.mockReturnValue('test-token');
21
- vi.spyOn(process, 'exit').mockImplementation(() => undefined);
21
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
22
+ throw new Error(`Process exited with code ${code}`);
23
+ });
22
24
  vi.spyOn(console, 'log').mockImplementation(() => { });
23
25
  vi.spyOn(console, 'table').mockImplementation(() => { });
24
26
  });
@@ -30,24 +32,26 @@ describe('apps-channels-get', () => {
30
32
  const appId = 'app-123';
31
33
  const channelId = 'channel-456';
32
34
  const options = { appId, channelId };
33
- mockAuthorizationService.hasAuthorizationToken.mockReturnValue(false);
34
- await getChannelCommand.action(options, undefined);
35
- expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.');
36
- expect(process.exit).toHaveBeenCalledWith(1);
35
+ // Mock no authentication token
36
+ mockAuthorizationService.getCurrentAuthorizationToken.mockReturnValue(null);
37
+ const scope = nock(DEFAULT_API_BASE_URL)
38
+ .get(`/v1/apps/${appId}/channels/${channelId}`)
39
+ .matchHeader('Authorization', 'Bearer null')
40
+ .reply(401, { message: 'Unauthorized' });
41
+ await expect(getChannelCommand.action(options, undefined)).rejects.toThrow();
42
+ expect(scope.isDone()).toBe(true);
37
43
  });
38
44
  it('should require appId', async () => {
39
45
  const channelId = 'channel-456';
40
- const options = { channelId };
41
- await getChannelCommand.action(options, undefined);
46
+ const options = { channelId, appId: undefined };
47
+ await expect(getChannelCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
42
48
  expect(mockConsola.error).toHaveBeenCalledWith('You must provide an app ID.');
43
- expect(process.exit).toHaveBeenCalledWith(1);
44
49
  });
45
50
  it('should require channelId or name', async () => {
46
51
  const appId = 'app-123';
47
- const options = { appId };
48
- await getChannelCommand.action(options, undefined);
52
+ const options = { appId, channelId: undefined, name: undefined };
53
+ await expect(getChannelCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
49
54
  expect(mockConsola.error).toHaveBeenCalledWith('You must provide a channel ID or name.');
50
- expect(process.exit).toHaveBeenCalledWith(1);
51
55
  });
52
56
  it('should get channel by channelId and display table format', async () => {
53
57
  const appId = 'app-123';
@@ -99,10 +103,8 @@ describe('apps-channels-get', () => {
99
103
  .get(`/v1/apps/${appId}/channels/${channelId}`)
100
104
  .matchHeader('Authorization', `Bearer ${testToken}`)
101
105
  .reply(404, { message: 'Channel not found' });
102
- await getChannelCommand.action(options, undefined);
106
+ await expect(getChannelCommand.action(options, undefined)).rejects.toThrow();
103
107
  expect(scope.isDone()).toBe(true);
104
- expect(mockConsola.error).toHaveBeenCalled();
105
- expect(process.exit).toHaveBeenCalledWith(1);
106
108
  });
107
109
  it('should handle channel not found by name', async () => {
108
110
  const appId = 'app-123';
@@ -114,10 +116,9 @@ describe('apps-channels-get', () => {
114
116
  .query({ name: channelName })
115
117
  .matchHeader('Authorization', `Bearer ${testToken}`)
116
118
  .reply(200, []);
117
- await getChannelCommand.action(options, undefined);
119
+ await expect(getChannelCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
118
120
  expect(scope.isDone()).toBe(true);
119
121
  expect(mockConsola.error).toHaveBeenCalledWith('Channel not found.');
120
- expect(process.exit).toHaveBeenCalledWith(1);
121
122
  });
122
123
  it('should handle API error', async () => {
123
124
  const appId = 'app-123';
@@ -128,9 +129,7 @@ describe('apps-channels-get', () => {
128
129
  .get(`/v1/apps/${appId}/channels/${channelId}`)
129
130
  .matchHeader('Authorization', `Bearer ${testToken}`)
130
131
  .reply(500, { message: 'Internal server error' });
131
- await getChannelCommand.action(options, undefined);
132
+ await expect(getChannelCommand.action(options, undefined)).rejects.toThrow();
132
133
  expect(scope.isDone()).toBe(true);
133
- expect(mockConsola.error).toHaveBeenCalled();
134
- expect(process.exit).toHaveBeenCalledWith(1);
135
134
  });
136
135
  });
@@ -1,9 +1,8 @@
1
+ import appChannelsService from '../../../services/app-channels.js';
2
+ import authorizationService from '../../../services/authorization-service.js';
1
3
  import { defineCommand, defineOptions } from '@robingenz/zli';
2
4
  import consola from 'consola';
3
5
  import { z } from 'zod';
4
- import appChannelsService from '../../../services/app-channels.js';
5
- import authorizationService from '../../../services/authorization-service.js';
6
- import { getMessageFromUnknownError } from '../../../utils/error.js';
7
6
  export default defineCommand({
8
7
  description: 'Retrieve a list of existing app channels.',
9
8
  options: defineOptions(z.object({
@@ -22,32 +21,25 @@ export default defineCommand({
22
21
  consola.error('You must provide an app ID.');
23
22
  process.exit(1);
24
23
  }
25
- try {
26
- const foundChannels = await appChannelsService.findAll({
27
- appId,
28
- limit,
29
- offset,
30
- });
31
- const logData = foundChannels.map((channel) => ({
32
- id: channel.id,
33
- name: channel.name,
34
- totalAppBundleLimit: channel.totalAppBundleLimit,
35
- appId: channel.appId,
36
- createdAt: channel.createdAt,
37
- updatedAt: channel.updatedAt,
38
- }));
39
- if (json) {
40
- console.log(JSON.stringify(logData, null, 2));
41
- }
42
- else {
43
- console.table(logData);
44
- consola.success('Channels retrieved successfully.');
45
- }
24
+ const foundChannels = await appChannelsService.findAll({
25
+ appId,
26
+ limit,
27
+ offset,
28
+ });
29
+ const logData = foundChannels.map((channel) => ({
30
+ id: channel.id,
31
+ name: channel.name,
32
+ totalAppBundleLimit: channel.totalAppBundleLimit,
33
+ appId: channel.appId,
34
+ createdAt: channel.createdAt,
35
+ updatedAt: channel.updatedAt,
36
+ }));
37
+ if (json) {
38
+ console.log(JSON.stringify(logData, null, 2));
46
39
  }
47
- catch (error) {
48
- const message = getMessageFromUnknownError(error);
49
- consola.error(message);
50
- process.exit(1);
40
+ else {
41
+ console.table(logData);
42
+ consola.success('Channels retrieved successfully.');
51
43
  }
52
44
  },
53
45
  });
@@ -1,12 +1,12 @@
1
1
  import { DEFAULT_API_BASE_URL } from '../../../config/consts.js';
2
2
  import authorizationService from '../../../services/authorization-service.js';
3
- import userConfig from '../../../utils/userConfig.js';
3
+ import userConfig from '../../../utils/user-config.js';
4
4
  import consola from 'consola';
5
5
  import nock from 'nock';
6
6
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
7
  import listChannelsCommand from './list.js';
8
8
  // Mock dependencies
9
- vi.mock('@/utils/userConfig.js');
9
+ vi.mock('@/utils/user-config.js');
10
10
  vi.mock('@/services/authorization-service.js');
11
11
  vi.mock('consola');
12
12
  describe('apps-channels-list', () => {
@@ -18,7 +18,9 @@ describe('apps-channels-list', () => {
18
18
  mockUserConfig.read.mockReturnValue({ token: 'test-token' });
19
19
  mockAuthorizationService.hasAuthorizationToken.mockReturnValue(true);
20
20
  mockAuthorizationService.getCurrentAuthorizationToken.mockReturnValue('test-token');
21
- vi.spyOn(process, 'exit').mockImplementation(() => undefined);
21
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
22
+ throw new Error(`Process exited with code ${code}`);
23
+ });
22
24
  vi.spyOn(console, 'log').mockImplementation(() => { });
23
25
  vi.spyOn(console, 'table').mockImplementation(() => { });
24
26
  });
@@ -30,15 +32,13 @@ describe('apps-channels-list', () => {
30
32
  const appId = 'app-123';
31
33
  const options = { appId };
32
34
  mockAuthorizationService.hasAuthorizationToken.mockReturnValue(false);
33
- await listChannelsCommand.action(options, undefined);
35
+ await expect(listChannelsCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
34
36
  expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.');
35
- expect(process.exit).toHaveBeenCalledWith(1);
36
37
  });
37
38
  it('should require appId', async () => {
38
- const options = {};
39
- await listChannelsCommand.action(options, undefined);
39
+ const options = { appId: undefined };
40
+ await expect(listChannelsCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
40
41
  expect(mockConsola.error).toHaveBeenCalledWith('You must provide an app ID.');
41
- expect(process.exit).toHaveBeenCalledWith(1);
42
42
  });
43
43
  it('should list channels and display table format', async () => {
44
44
  const appId = 'app-123';
@@ -115,9 +115,7 @@ describe('apps-channels-list', () => {
115
115
  .get(`/v1/apps/${appId}/channels`)
116
116
  .matchHeader('Authorization', `Bearer ${testToken}`)
117
117
  .reply(500, { message: 'Internal server error' });
118
- await listChannelsCommand.action(options, undefined);
118
+ await expect(listChannelsCommand.action(options, undefined)).rejects.toThrow();
119
119
  expect(scope.isDone()).toBe(true);
120
- expect(mockConsola.error).toHaveBeenCalled();
121
- expect(process.exit).toHaveBeenCalledWith(1);
122
120
  });
123
121
  });
@@ -1,12 +1,11 @@
1
- import { defineCommand, defineOptions } from '@robingenz/zli';
2
- import consola from 'consola';
3
- import { z } from 'zod';
4
1
  import appChannelsService from '../../../services/app-channels.js';
5
2
  import appsService from '../../../services/apps.js';
6
3
  import authorizationService from '../../../services/authorization-service.js';
7
4
  import organizationsService from '../../../services/organizations.js';
8
- import { getMessageFromUnknownError } from '../../../utils/error.js';
9
5
  import { prompt } from '../../../utils/prompt.js';
6
+ import { defineCommand, defineOptions } from '@robingenz/zli';
7
+ import consola from 'consola';
8
+ import { z } from 'zod';
10
9
  export default defineCommand({
11
10
  description: 'Update an existing app channel.',
12
11
  options: defineOptions(z.object({
@@ -58,19 +57,12 @@ export default defineCommand({
58
57
  });
59
58
  }
60
59
  // Update channel
61
- try {
62
- await appChannelsService.update({
63
- appId,
64
- appChannelId: channelId,
65
- name,
66
- totalAppBundleLimit: bundleLimit,
67
- });
68
- consola.success('Channel updated successfully.');
69
- }
70
- catch (error) {
71
- const message = getMessageFromUnknownError(error);
72
- consola.error(message);
73
- process.exit(1);
74
- }
60
+ await appChannelsService.update({
61
+ appId,
62
+ appChannelId: channelId,
63
+ name,
64
+ totalAppBundleLimit: bundleLimit,
65
+ });
66
+ consola.success('Channel updated successfully.');
75
67
  },
76
68
  });
@@ -1,13 +1,13 @@
1
1
  import { DEFAULT_API_BASE_URL } from '../../../config/consts.js';
2
2
  import authorizationService from '../../../services/authorization-service.js';
3
3
  import { prompt } from '../../../utils/prompt.js';
4
- import userConfig from '../../../utils/userConfig.js';
4
+ import userConfig from '../../../utils/user-config.js';
5
5
  import consola from 'consola';
6
6
  import nock from 'nock';
7
7
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
8
8
  import updateChannelCommand from './update.js';
9
9
  // Mock dependencies
10
- vi.mock('@/utils/userConfig.js');
10
+ vi.mock('@/utils/user-config.js');
11
11
  vi.mock('@/utils/prompt.js');
12
12
  vi.mock('@/services/authorization-service.js');
13
13
  vi.mock('consola');
@@ -21,7 +21,9 @@ describe('apps-channels-update', () => {
21
21
  mockUserConfig.read.mockReturnValue({ token: 'test-token' });
22
22
  mockAuthorizationService.hasAuthorizationToken.mockReturnValue(true);
23
23
  mockAuthorizationService.getCurrentAuthorizationToken.mockReturnValue('test-token');
24
- vi.spyOn(process, 'exit').mockImplementation(() => undefined);
24
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
25
+ throw new Error(`Process exited with code ${code}`);
26
+ });
25
27
  });
26
28
  afterEach(() => {
27
29
  nock.cleanAll();
@@ -32,9 +34,8 @@ describe('apps-channels-update', () => {
32
34
  const channelId = 'channel-456';
33
35
  const options = { appId, channelId };
34
36
  mockAuthorizationService.hasAuthorizationToken.mockReturnValue(false);
35
- await updateChannelCommand.action(options, undefined);
37
+ await expect(updateChannelCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
36
38
  expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.');
37
- expect(process.exit).toHaveBeenCalledWith(1);
38
39
  });
39
40
  it('should update channel with provided options', async () => {
40
41
  const appId = 'app-123';
@@ -111,10 +112,8 @@ describe('apps-channels-update', () => {
111
112
  .patch(`/v1/apps/${appId}/channels/${channelId}`)
112
113
  .matchHeader('Authorization', `Bearer ${testToken}`)
113
114
  .reply(404, { message: 'Channel not found' });
114
- await updateChannelCommand.action(options, undefined);
115
+ await expect(updateChannelCommand.action(options, undefined)).rejects.toThrow();
115
116
  expect(scope.isDone()).toBe(true);
116
- expect(mockConsola.error).toHaveBeenCalled();
117
- expect(process.exit).toHaveBeenCalledWith(1);
118
117
  });
119
118
  it('should handle error when no organizations exist', async () => {
120
119
  const testToken = 'test-token';
@@ -1,10 +1,10 @@
1
- import { defineCommand, defineOptions } from '@robingenz/zli';
2
- import consola from 'consola';
3
- import { z } from 'zod';
4
1
  import appsService from '../../services/apps.js';
2
+ import authorizationService from '../../services/authorization-service.js';
5
3
  import organizationsService from '../../services/organizations.js';
6
- import { getMessageFromUnknownError } from '../../utils/error.js';
7
4
  import { prompt } from '../../utils/prompt.js';
5
+ import { defineCommand, defineOptions } from '@robingenz/zli';
6
+ import consola from 'consola';
7
+ import { z } from 'zod';
8
8
  export default defineCommand({
9
9
  description: 'Create a new app.',
10
10
  options: defineOptions(z.object({
@@ -13,6 +13,10 @@ export default defineCommand({
13
13
  })),
14
14
  action: async (options, args) => {
15
15
  let { name, organizationId } = options;
16
+ if (!authorizationService.hasAuthorizationToken()) {
17
+ consola.error('You must be logged in to run this command.');
18
+ process.exit(1);
19
+ }
16
20
  if (!organizationId) {
17
21
  const organizations = await organizationsService.findAll();
18
22
  if (organizations.length === 0) {
@@ -32,15 +36,8 @@ export default defineCommand({
32
36
  if (!name) {
33
37
  name = await prompt('Enter the name of the app:', { type: 'text' });
34
38
  }
35
- try {
36
- const response = await appsService.create({ name, organizationId });
37
- consola.success('App created successfully.');
38
- consola.info(`App ID: ${response.id}`);
39
- }
40
- catch (error) {
41
- const message = getMessageFromUnknownError(error);
42
- consola.error(message);
43
- process.exit(1);
44
- }
39
+ const response = await appsService.create({ name, organizationId });
40
+ consola.success('App created successfully.');
41
+ consola.info(`App ID: ${response.id}`);
45
42
  },
46
43
  });
@@ -1,13 +1,13 @@
1
1
  import { DEFAULT_API_BASE_URL } from '../../config/consts.js';
2
2
  import authorizationService from '../../services/authorization-service.js';
3
3
  import { prompt } from '../../utils/prompt.js';
4
- import userConfig from '../../utils/userConfig.js';
4
+ import userConfig from '../../utils/user-config.js';
5
5
  import consola from 'consola';
6
6
  import nock from 'nock';
7
7
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
8
8
  import createAppCommand from './create.js';
9
9
  // Mock dependencies
10
- vi.mock('@/utils/userConfig.js');
10
+ vi.mock('@/utils/user-config.js');
11
11
  vi.mock('@/utils/prompt.js');
12
12
  vi.mock('@/services/authorization-service.js');
13
13
  vi.mock('consola');
@@ -20,7 +20,10 @@ describe('apps-create', () => {
20
20
  vi.clearAllMocks();
21
21
  mockUserConfig.read.mockReturnValue({ token: 'test-token' });
22
22
  mockAuthorizationService.getCurrentAuthorizationToken.mockReturnValue('test-token');
23
- vi.spyOn(process, 'exit').mockImplementation(() => undefined);
23
+ mockAuthorizationService.hasAuthorizationToken.mockReturnValue(true);
24
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
25
+ throw new Error(`Process exited with code ${code}`);
26
+ });
24
27
  });
25
28
  afterEach(() => {
26
29
  nock.cleanAll();
@@ -95,10 +98,9 @@ describe('apps-create', () => {
95
98
  .get('/v1/organizations')
96
99
  .matchHeader('Authorization', `Bearer ${testToken}`)
97
100
  .reply(200, []);
98
- await createAppCommand.action(options, undefined);
101
+ await expect(createAppCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
99
102
  expect(scope.isDone()).toBe(true);
100
103
  expect(mockConsola.error).toHaveBeenCalledWith('You must create an organization before creating an app.');
101
- expect(process.exit).toHaveBeenCalledWith(1);
102
104
  });
103
105
  it('should handle API error during creation', async () => {
104
106
  const appName = 'Test App';
@@ -109,9 +111,7 @@ describe('apps-create', () => {
109
111
  .post(`/v1/apps?organizationId=${organizationId}`, { name: appName })
110
112
  .matchHeader('Authorization', `Bearer ${testToken}`)
111
113
  .reply(400, { message: 'App name already exists' });
112
- await createAppCommand.action(options, undefined);
114
+ await expect(createAppCommand.action(options, undefined)).rejects.toThrow();
113
115
  expect(scope.isDone()).toBe(true);
114
- expect(mockConsola.error).toHaveBeenCalled();
115
- expect(process.exit).toHaveBeenCalledWith(1);
116
116
  });
117
117
  });
@@ -1,10 +1,10 @@
1
- import { defineCommand, defineOptions } from '@robingenz/zli';
2
- import consola from 'consola';
3
- import { z } from 'zod';
4
1
  import appsService from '../../services/apps.js';
2
+ import authorizationService from '../../services/authorization-service.js';
5
3
  import organizationsService from '../../services/organizations.js';
6
- import { getMessageFromUnknownError } from '../../utils/error.js';
7
4
  import { prompt } from '../../utils/prompt.js';
5
+ import { defineCommand, defineOptions } from '@robingenz/zli';
6
+ import consola from 'consola';
7
+ import { z } from 'zod';
8
8
  export default defineCommand({
9
9
  description: 'Delete an app.',
10
10
  options: defineOptions(z.object({
@@ -12,6 +12,10 @@ export default defineCommand({
12
12
  })),
13
13
  action: async (options, args) => {
14
14
  let { appId } = options;
15
+ if (!authorizationService.hasAuthorizationToken()) {
16
+ consola.error('You must be logged in to run this command.');
17
+ process.exit(1);
18
+ }
15
19
  if (!appId) {
16
20
  const organizations = await organizationsService.findAll();
17
21
  if (organizations.length === 0) {
@@ -46,14 +50,7 @@ export default defineCommand({
46
50
  if (!confirmed) {
47
51
  return;
48
52
  }
49
- try {
50
- await appsService.delete({ id: appId });
51
- consola.success('App deleted successfully.');
52
- }
53
- catch (error) {
54
- const message = getMessageFromUnknownError(error);
55
- consola.error(message);
56
- process.exit(1);
57
- }
53
+ await appsService.delete({ id: appId });
54
+ consola.success('App deleted successfully.');
58
55
  },
59
56
  });
@@ -1,13 +1,13 @@
1
1
  import { DEFAULT_API_BASE_URL } from '../../config/consts.js';
2
2
  import authorizationService from '../../services/authorization-service.js';
3
3
  import { prompt } from '../../utils/prompt.js';
4
- import userConfig from '../../utils/userConfig.js';
4
+ import userConfig from '../../utils/user-config.js';
5
5
  import consola from 'consola';
6
6
  import nock from 'nock';
7
7
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
8
8
  import deleteAppCommand from './delete.js';
9
9
  // Mock dependencies
10
- vi.mock('@/utils/userConfig.js');
10
+ vi.mock('@/utils/user-config.js');
11
11
  vi.mock('@/utils/prompt.js');
12
12
  vi.mock('@/services/authorization-service.js');
13
13
  vi.mock('consola');
@@ -20,7 +20,10 @@ describe('apps-delete', () => {
20
20
  vi.clearAllMocks();
21
21
  mockUserConfig.read.mockReturnValue({ token: 'test-token' });
22
22
  mockAuthorizationService.getCurrentAuthorizationToken.mockReturnValue('test-token');
23
- vi.spyOn(process, 'exit').mockImplementation(() => undefined);
23
+ mockAuthorizationService.hasAuthorizationToken.mockReturnValue(true);
24
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
25
+ throw new Error(`Process exited with code ${code}`);
26
+ });
24
27
  });
25
28
  afterEach(() => {
26
29
  nock.cleanAll();
@@ -111,9 +114,7 @@ describe('apps-delete', () => {
111
114
  .delete(`/v1/apps/${appId}`)
112
115
  .matchHeader('Authorization', `Bearer ${testToken}`)
113
116
  .reply(404, { message: 'App not found' });
114
- await deleteAppCommand.action(options, undefined);
117
+ await expect(deleteAppCommand.action(options, undefined)).rejects.toThrow();
115
118
  expect(scope.isDone()).toBe(true);
116
- expect(mockConsola.error).toHaveBeenCalled();
117
- expect(process.exit).toHaveBeenCalledWith(1);
118
119
  });
119
120
  });
@@ -1,11 +1,11 @@
1
- import { defineCommand, defineOptions } from '@robingenz/zli';
2
- import consola from 'consola';
3
- import { z } from 'zod';
4
1
  import appDevicesService from '../../../services/app-devices.js';
5
2
  import appsService from '../../../services/apps.js';
3
+ import authorizationService from '../../../services/authorization-service.js';
6
4
  import organizationsService from '../../../services/organizations.js';
7
- import { getMessageFromUnknownError } from '../../../utils/error.js';
8
5
  import { prompt } from '../../../utils/prompt.js';
6
+ import { defineCommand, defineOptions } from '@robingenz/zli';
7
+ import consola from 'consola';
8
+ import { z } from 'zod';
9
9
  export default defineCommand({
10
10
  description: 'Delete an app device.',
11
11
  options: defineOptions(z.object({
@@ -14,6 +14,10 @@ export default defineCommand({
14
14
  })),
15
15
  action: async (options, args) => {
16
16
  let { appId, deviceId } = options;
17
+ if (!authorizationService.hasAuthorizationToken()) {
18
+ consola.error('You must be logged in to run this command.');
19
+ process.exit(1);
20
+ }
17
21
  if (!appId) {
18
22
  const organizations = await organizationsService.findAll();
19
23
  if (organizations.length === 0) {
@@ -53,17 +57,10 @@ export default defineCommand({
53
57
  if (!confirmed) {
54
58
  return;
55
59
  }
56
- try {
57
- await appDevicesService.delete({
58
- appId,
59
- deviceId,
60
- });
61
- consola.success('Device deleted successfully.');
62
- }
63
- catch (error) {
64
- const message = getMessageFromUnknownError(error);
65
- consola.error(message);
66
- process.exit(1);
67
- }
60
+ await appDevicesService.delete({
61
+ appId,
62
+ deviceId,
63
+ });
64
+ consola.success('Device deleted successfully.');
68
65
  },
69
66
  });