@capawesome/cli 4.1.0-dev.f5ef8ba.1771047437 → 4.2.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.
- package/CHANGELOG.md +14 -0
- package/dist/commands/apps/builds/cancel.js +6 -41
- package/dist/commands/apps/builds/create.js +10 -55
- package/dist/commands/apps/builds/download.js +6 -41
- package/dist/commands/apps/builds/logs.js +6 -41
- package/dist/commands/apps/channels/create.js +6 -36
- package/dist/commands/apps/channels/create.test.js +5 -15
- package/dist/commands/apps/channels/delete.js +6 -36
- package/dist/commands/apps/channels/delete.test.js +6 -18
- package/dist/commands/apps/channels/get.js +3 -7
- package/dist/commands/apps/channels/list.js +6 -36
- package/dist/commands/apps/channels/list.test.js +4 -1
- package/dist/commands/apps/channels/pause.js +6 -40
- package/dist/commands/apps/channels/resume.js +6 -40
- package/dist/commands/apps/channels/update.js +6 -36
- package/dist/commands/apps/channels/update.test.js +14 -31
- package/dist/commands/apps/create.js +5 -23
- package/dist/commands/apps/create.test.js +13 -31
- package/dist/commands/apps/delete.js +6 -35
- package/dist/commands/apps/delete.test.js +11 -35
- package/dist/commands/apps/deployments/cancel.js +6 -41
- package/dist/commands/apps/deployments/create.js +6 -41
- package/dist/commands/apps/deployments/logs.js +6 -41
- package/dist/commands/apps/devices/delete.js +6 -36
- package/dist/commands/apps/devices/delete.test.js +14 -36
- package/dist/commands/apps/environments/create.js +6 -36
- package/dist/commands/apps/environments/delete.js +6 -36
- package/dist/commands/apps/environments/list.js +6 -36
- package/dist/commands/apps/environments/set.js +6 -36
- package/dist/commands/apps/environments/unset.js +6 -36
- package/dist/commands/apps/liveupdates/register.js +6 -40
- package/dist/commands/apps/liveupdates/register.test.js +2 -1
- package/dist/commands/apps/liveupdates/rollback.js +6 -41
- package/dist/commands/apps/liveupdates/rollout.js +6 -41
- package/dist/commands/apps/liveupdates/set-native-versions.js +3 -7
- package/dist/commands/apps/liveupdates/upload.js +6 -40
- package/dist/commands/apps/liveupdates/upload.test.js +2 -1
- package/dist/commands/organizations/create.js +3 -7
- package/dist/commands/organizations/create.test.js +3 -1
- package/dist/utils/auth.js +27 -0
- package/dist/utils/prompt.js +56 -11
- package/dist/utils/signature.js +2 -1
- package/package.json +6 -2
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import appEnvironmentsService from '../../../services/app-environments.js';
|
|
2
|
-
import appsService from '../../../services/apps.js';
|
|
3
|
-
import authorizationService from '../../../services/authorization-service.js';
|
|
4
|
-
import organizationsService from '../../../services/organizations.js';
|
|
5
2
|
import { parseKeyValuePairs } from '../../../utils/app-environments.js';
|
|
3
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
6
4
|
import { isInteractive } from '../../../utils/environment.js';
|
|
7
|
-
import { prompt } from '../../../utils/prompt.js';
|
|
5
|
+
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
|
|
8
6
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
9
7
|
import consola from 'consola';
|
|
10
8
|
import fs from 'fs';
|
|
@@ -25,43 +23,15 @@ export default defineCommand({
|
|
|
25
23
|
.describe('Environment secret in key=value format. Can be specified multiple times.'),
|
|
26
24
|
secretFile: z.string().optional().describe('Path to a file containing environment secrets in .env format.'),
|
|
27
25
|
})),
|
|
28
|
-
action: async (options, args) => {
|
|
26
|
+
action: withAuth(async (options, args) => {
|
|
29
27
|
let { appId, environmentId, variable, variableFile, secret, secretFile } = options;
|
|
30
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
31
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
28
|
if (!appId) {
|
|
35
29
|
if (!isInteractive()) {
|
|
36
30
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
37
31
|
process.exit(1);
|
|
38
32
|
}
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
consola.error('You must create an organization before setting environment variables or secrets.');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
45
|
-
const organizationId = await prompt('Select the organization of the app for which you want to set environment variables or secrets.', {
|
|
46
|
-
type: 'select',
|
|
47
|
-
options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
|
|
48
|
-
});
|
|
49
|
-
if (!organizationId) {
|
|
50
|
-
consola.error('You must select the organization of an app for which you want to set environment variables or secrets.');
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
const apps = await appsService.findAll({
|
|
54
|
-
organizationId,
|
|
55
|
-
});
|
|
56
|
-
if (!apps.length) {
|
|
57
|
-
consola.error('You must create an app before setting environment variables or secrets.');
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
61
|
-
appId = await prompt('Which app do you want to set the environment variables or secrets for?', {
|
|
62
|
-
type: 'select',
|
|
63
|
-
options: apps.map((app) => ({ label: app.name, value: app.id })),
|
|
64
|
-
});
|
|
33
|
+
const organizationId = await promptOrganizationSelection();
|
|
34
|
+
appId = await promptAppSelection(organizationId);
|
|
65
35
|
}
|
|
66
36
|
if (!environmentId) {
|
|
67
37
|
if (!isInteractive()) {
|
|
@@ -122,5 +92,5 @@ export default defineCommand({
|
|
|
122
92
|
});
|
|
123
93
|
}
|
|
124
94
|
consola.success('Environment variables and secrets set successfully.');
|
|
125
|
-
},
|
|
95
|
+
}),
|
|
126
96
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import appEnvironmentsService from '../../../services/app-environments.js';
|
|
2
|
-
import
|
|
3
|
-
import authorizationService from '../../../services/authorization-service.js';
|
|
4
|
-
import organizationsService from '../../../services/organizations.js';
|
|
2
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
5
3
|
import { isInteractive } from '../../../utils/environment.js';
|
|
6
|
-
import { prompt } from '../../../utils/prompt.js';
|
|
4
|
+
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
|
|
7
5
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
8
6
|
import consola from 'consola';
|
|
9
7
|
import { z } from 'zod';
|
|
@@ -21,43 +19,15 @@ export default defineCommand({
|
|
|
21
19
|
.optional()
|
|
22
20
|
.describe('Key of the environment secret to unset. Can be specified multiple times.'),
|
|
23
21
|
})),
|
|
24
|
-
action: async (options, args) => {
|
|
22
|
+
action: withAuth(async (options, args) => {
|
|
25
23
|
let { appId, environmentId, variable: variableKeys, secret: secretKeys } = options;
|
|
26
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
27
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
24
|
if (!appId) {
|
|
31
25
|
if (!isInteractive()) {
|
|
32
26
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
33
27
|
process.exit(1);
|
|
34
28
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
consola.error('You must create an organization before unsetting environment variables or secrets.');
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
41
|
-
const organizationId = await prompt('Select the organization of the app for which you want to unset environment variables or secrets.', {
|
|
42
|
-
type: 'select',
|
|
43
|
-
options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
|
|
44
|
-
});
|
|
45
|
-
if (!organizationId) {
|
|
46
|
-
consola.error('You must select the organization of an app for which you want to unset environment variables or secrets.');
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
const apps = await appsService.findAll({
|
|
50
|
-
organizationId,
|
|
51
|
-
});
|
|
52
|
-
if (!apps.length) {
|
|
53
|
-
consola.error('You must create an app before unsetting environment variables or secrets.');
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
57
|
-
appId = await prompt('Which app do you want to unset the environment variables or secrets for?', {
|
|
58
|
-
type: 'select',
|
|
59
|
-
options: apps.map((app) => ({ label: app.name, value: app.id })),
|
|
60
|
-
});
|
|
29
|
+
const organizationId = await promptOrganizationSelection();
|
|
30
|
+
appId = await promptAppSelection(organizationId);
|
|
61
31
|
}
|
|
62
32
|
if (!environmentId) {
|
|
63
33
|
if (!isInteractive()) {
|
|
@@ -94,5 +64,5 @@ export default defineCommand({
|
|
|
94
64
|
});
|
|
95
65
|
}
|
|
96
66
|
consola.success('Environment variables and secrets unset successfully.');
|
|
97
|
-
},
|
|
67
|
+
}),
|
|
98
68
|
});
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { DEFAULT_CONSOLE_BASE_URL } from '../../../config/consts.js';
|
|
2
2
|
import appBundlesService from '../../../services/app-bundles.js';
|
|
3
3
|
import appsService from '../../../services/apps.js';
|
|
4
|
-
import
|
|
5
|
-
import organizationsService from '../../../services/organizations.js';
|
|
4
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
6
5
|
import { createBufferFromPath, createBufferFromString, isPrivateKeyContent } from '../../../utils/buffer.js';
|
|
7
6
|
import { isInteractive } from '../../../utils/environment.js';
|
|
8
7
|
import { fileExistsAtPath } from '../../../utils/file.js';
|
|
9
8
|
import { createHash } from '../../../utils/hash.js';
|
|
10
9
|
import { formatPrivateKey } from '../../../utils/private-key.js';
|
|
11
|
-
import { prompt } from '../../../utils/prompt.js';
|
|
10
|
+
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
|
|
12
11
|
import { createSignature } from '../../../utils/signature.js';
|
|
13
12
|
import zip from '../../../utils/zip.js';
|
|
14
13
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
@@ -101,13 +100,8 @@ export default defineCommand({
|
|
|
101
100
|
url: z.string().optional().describe('The url to the self-hosted bundle file.'),
|
|
102
101
|
yes: z.boolean().optional().describe('Skip confirmation prompts.'),
|
|
103
102
|
}), { y: 'yes' }),
|
|
104
|
-
action: async (options, args) => {
|
|
103
|
+
action: withAuth(async (options, args) => {
|
|
105
104
|
let { androidEq, androidMax, androidMin, appId, channel, commitMessage, commitRef, commitSha, customProperty, expiresInDays, gitRef, iosEq, iosMax, iosMin, path, privateKey, rolloutPercentage, url, } = options;
|
|
106
|
-
// Check if the user is logged in
|
|
107
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
108
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
105
|
// Calculate the expiration date
|
|
112
106
|
let expiresAt;
|
|
113
107
|
if (expiresInDays) {
|
|
@@ -137,36 +131,8 @@ export default defineCommand({
|
|
|
137
131
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
138
132
|
process.exit(1);
|
|
139
133
|
}
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
consola.error('You must create an organization before registering a bundle.');
|
|
143
|
-
process.exit(1);
|
|
144
|
-
}
|
|
145
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
146
|
-
const organizationId = await prompt('Select the organization of the app for which you want to register a bundle.', {
|
|
147
|
-
type: 'select',
|
|
148
|
-
options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
|
|
149
|
-
});
|
|
150
|
-
if (!organizationId) {
|
|
151
|
-
consola.error('You must select the organization of an app for which you want to register a bundle.');
|
|
152
|
-
process.exit(1);
|
|
153
|
-
}
|
|
154
|
-
const apps = await appsService.findAll({
|
|
155
|
-
organizationId,
|
|
156
|
-
});
|
|
157
|
-
if (apps.length === 0) {
|
|
158
|
-
consola.error('You must create an app before registering a bundle.');
|
|
159
|
-
process.exit(1);
|
|
160
|
-
}
|
|
161
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
162
|
-
appId = await prompt('Which app do you want to deploy to:', {
|
|
163
|
-
type: 'select',
|
|
164
|
-
options: apps.map((app) => ({ label: app.name, value: app.id })),
|
|
165
|
-
});
|
|
166
|
-
if (!appId) {
|
|
167
|
-
consola.error('You must select an app to deploy to.');
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
134
|
+
const organizationId = await promptOrganizationSelection({ allowCreate: true });
|
|
135
|
+
appId = await promptAppSelection(organizationId, { allowCreate: true });
|
|
170
136
|
}
|
|
171
137
|
// Prompt for channel if interactive
|
|
172
138
|
if (!channel && !options.yes && isInteractive()) {
|
|
@@ -274,7 +240,7 @@ export default defineCommand({
|
|
|
274
240
|
consola.info(`Deployment URL: ${DEFAULT_CONSOLE_BASE_URL}/apps/${appId}/deployments/${response.appDeploymentId}`);
|
|
275
241
|
}
|
|
276
242
|
consola.success('Live Update successfully registered.');
|
|
277
|
-
},
|
|
243
|
+
}),
|
|
278
244
|
});
|
|
279
245
|
const parseCustomProperties = (customProperty) => {
|
|
280
246
|
let customProperties;
|
|
@@ -8,6 +8,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
8
8
|
import registerCommand from './register.js';
|
|
9
9
|
// Mock dependencies
|
|
10
10
|
vi.mock('@/utils/user-config.js');
|
|
11
|
+
vi.mock('@/utils/prompt.js');
|
|
11
12
|
vi.mock('@/services/authorization-service.js');
|
|
12
13
|
vi.mock('@/utils/file.js');
|
|
13
14
|
vi.mock('@/utils/zip.js');
|
|
@@ -40,7 +41,7 @@ describe('apps-liveupdates-register', () => {
|
|
|
40
41
|
const options = { appId, url: bundleUrl, rolloutPercentage: 1 };
|
|
41
42
|
mockAuthorizationService.hasAuthorizationToken.mockReturnValue(false);
|
|
42
43
|
await expect(registerCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
|
|
43
|
-
expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.
|
|
44
|
+
expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command. Set the `CAPAWESOME_TOKEN` environment variable or use the `--token` option.');
|
|
44
45
|
});
|
|
45
46
|
it('should register bundle with self-hosted URL', async () => {
|
|
46
47
|
const appId = 'app-123';
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { DEFAULT_CONSOLE_BASE_URL } from '../../../config/consts.js';
|
|
2
2
|
import appChannelsService from '../../../services/app-channels.js';
|
|
3
3
|
import appDeploymentsService from '../../../services/app-deployments.js';
|
|
4
|
-
import
|
|
5
|
-
import authorizationService from '../../../services/authorization-service.js';
|
|
6
|
-
import organizationsService from '../../../services/organizations.js';
|
|
4
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
7
5
|
import { isInteractive } from '../../../utils/environment.js';
|
|
8
|
-
import { prompt } from '../../../utils/prompt.js';
|
|
6
|
+
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
|
|
9
7
|
import { formatTimeAgo } from '../../../utils/time-format.js';
|
|
10
8
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
11
9
|
import consola from 'consola';
|
|
@@ -34,49 +32,16 @@ export default defineCommand({
|
|
|
34
32
|
.optional()
|
|
35
33
|
.describe('Number of deployments to go back (1-5).'),
|
|
36
34
|
})),
|
|
37
|
-
action: async (options) => {
|
|
35
|
+
action: withAuth(async (options) => {
|
|
38
36
|
let { appId, channel, steps } = options;
|
|
39
|
-
// Check if the user is logged in
|
|
40
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
41
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
37
|
// Prompt for app ID if not provided
|
|
45
38
|
if (!appId) {
|
|
46
39
|
if (!isInteractive()) {
|
|
47
40
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
48
41
|
process.exit(1);
|
|
49
42
|
}
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
consola.error('You must create an organization before rolling back a deployment.');
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
56
|
-
const organizationId = await prompt('Select the organization of the app for which you want to rollback a deployment.', {
|
|
57
|
-
type: 'select',
|
|
58
|
-
options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
|
|
59
|
-
});
|
|
60
|
-
if (!organizationId) {
|
|
61
|
-
consola.error('You must select the organization of an app for which you want to rollback a deployment.');
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
const apps = await appsService.findAll({
|
|
65
|
-
organizationId,
|
|
66
|
-
});
|
|
67
|
-
if (apps.length === 0) {
|
|
68
|
-
consola.error('You must create an app before rolling back a deployment.');
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
72
|
-
appId = await prompt('Which app do you want to rollback a deployment for:', {
|
|
73
|
-
type: 'select',
|
|
74
|
-
options: apps.map((app) => ({ label: app.name, value: app.id })),
|
|
75
|
-
});
|
|
76
|
-
if (!appId) {
|
|
77
|
-
consola.error('You must select an app to rollback a deployment for.');
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
43
|
+
const organizationId = await promptOrganizationSelection();
|
|
44
|
+
appId = await promptAppSelection(organizationId);
|
|
80
45
|
}
|
|
81
46
|
// Prompt for channel name if not provided
|
|
82
47
|
if (!channel) {
|
|
@@ -167,5 +132,5 @@ export default defineCommand({
|
|
|
167
132
|
consola.info(`Deployment ID: ${response.id}`);
|
|
168
133
|
consola.info(`Deployment URL: ${DEFAULT_CONSOLE_BASE_URL}/apps/${appId}/deployments/${response.id}`);
|
|
169
134
|
consola.success(`Rolled back to Build #${selectedAppDeployment.appBuild?.numberAsString} (${selectedIndex} step${selectedIndex === 1 ? '' : 's'} back).`);
|
|
170
|
-
},
|
|
135
|
+
}),
|
|
171
136
|
});
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { DEFAULT_CONSOLE_BASE_URL } from '../../../config/consts.js';
|
|
2
2
|
import appChannelsService from '../../../services/app-channels.js';
|
|
3
3
|
import appDeploymentsService from '../../../services/app-deployments.js';
|
|
4
|
-
import
|
|
5
|
-
import authorizationService from '../../../services/authorization-service.js';
|
|
6
|
-
import organizationsService from '../../../services/organizations.js';
|
|
4
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
7
5
|
import { isInteractive } from '../../../utils/environment.js';
|
|
8
|
-
import { prompt } from '../../../utils/prompt.js';
|
|
6
|
+
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
|
|
9
7
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
10
8
|
import consola from 'consola';
|
|
11
9
|
import { z } from 'zod';
|
|
@@ -33,49 +31,16 @@ export default defineCommand({
|
|
|
33
31
|
.optional()
|
|
34
32
|
.describe('Rollout percentage (0-100).'),
|
|
35
33
|
})),
|
|
36
|
-
action: async (options) => {
|
|
34
|
+
action: withAuth(async (options) => {
|
|
37
35
|
let { appId, channel, percentage } = options;
|
|
38
|
-
// Check if the user is logged in
|
|
39
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
40
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
36
|
// Prompt for app ID if not provided
|
|
44
37
|
if (!appId) {
|
|
45
38
|
if (!isInteractive()) {
|
|
46
39
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
47
40
|
process.exit(1);
|
|
48
41
|
}
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
consola.error('You must create an organization before updating a rollout percentage.');
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
55
|
-
const organizationId = await prompt('Select the organization of the app for which you want to update the rollout percentage.', {
|
|
56
|
-
type: 'select',
|
|
57
|
-
options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
|
|
58
|
-
});
|
|
59
|
-
if (!organizationId) {
|
|
60
|
-
consola.error('You must select the organization of an app for which you want to update the rollout percentage.');
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
const apps = await appsService.findAll({
|
|
64
|
-
organizationId,
|
|
65
|
-
});
|
|
66
|
-
if (apps.length === 0) {
|
|
67
|
-
consola.error('You must create an app before updating a rollout percentage.');
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
70
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
71
|
-
appId = await prompt('Which app do you want to update the rollout percentage for:', {
|
|
72
|
-
type: 'select',
|
|
73
|
-
options: apps.map((app) => ({ label: app.name, value: app.id })),
|
|
74
|
-
});
|
|
75
|
-
if (!appId) {
|
|
76
|
-
consola.error('You must select an app to update the rollout percentage for.');
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
42
|
+
const organizationId = await promptOrganizationSelection();
|
|
43
|
+
appId = await promptAppSelection(organizationId);
|
|
79
44
|
}
|
|
80
45
|
// Prompt for channel name if not provided
|
|
81
46
|
if (!channel) {
|
|
@@ -143,5 +108,5 @@ export default defineCommand({
|
|
|
143
108
|
consola.info(`Deployment ID: ${response.id}`);
|
|
144
109
|
consola.info(`Deployment URL: ${DEFAULT_CONSOLE_BASE_URL}/apps/${appId}/deployments/${response.id}`);
|
|
145
110
|
consola.success(`Rolled out to ${percentage}%.`);
|
|
146
|
-
},
|
|
111
|
+
}),
|
|
147
112
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import appBuildsService from '../../../services/app-builds.js';
|
|
2
|
-
import
|
|
2
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
3
3
|
import { isInteractive } from '../../../utils/environment.js';
|
|
4
4
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
5
5
|
import consola from 'consola';
|
|
@@ -50,12 +50,8 @@ export default defineCommand({
|
|
|
50
50
|
.optional()
|
|
51
51
|
.describe('The minimum iOS bundle version (`CFBundleVersion`) that the build supports.'),
|
|
52
52
|
})),
|
|
53
|
-
action: async (options) => {
|
|
53
|
+
action: withAuth(async (options) => {
|
|
54
54
|
const { appId, buildId, androidEq, androidMax, androidMin, iosEq, iosMax, iosMin } = options;
|
|
55
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
56
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
55
|
if (!appId) {
|
|
60
56
|
if (!isInteractive()) {
|
|
61
57
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
@@ -84,5 +80,5 @@ export default defineCommand({
|
|
|
84
80
|
minIosAppVersionCode: iosMin,
|
|
85
81
|
});
|
|
86
82
|
consola.success('Native version constraints set successfully.');
|
|
87
|
-
},
|
|
83
|
+
}),
|
|
88
84
|
});
|
|
@@ -2,15 +2,14 @@ import { DEFAULT_CONSOLE_BASE_URL, MAX_CONCURRENT_UPLOADS } from '../../../confi
|
|
|
2
2
|
import appBundleFilesService from '../../../services/app-bundle-files.js';
|
|
3
3
|
import appBundlesService from '../../../services/app-bundles.js';
|
|
4
4
|
import appsService from '../../../services/apps.js';
|
|
5
|
-
import
|
|
6
|
-
import organizationsService from '../../../services/organizations.js';
|
|
5
|
+
import { withAuth } from '../../../utils/auth.js';
|
|
7
6
|
import { createBufferFromPath, createBufferFromReadStream, createBufferFromString, isPrivateKeyContent, } from '../../../utils/buffer.js';
|
|
8
7
|
import { isInteractive } from '../../../utils/environment.js';
|
|
9
8
|
import { fileExistsAtPath, getFilesInDirectoryAndSubdirectories, isDirectory } from '../../../utils/file.js';
|
|
10
9
|
import { createHash } from '../../../utils/hash.js';
|
|
11
10
|
import { generateManifestJson } from '../../../utils/manifest.js';
|
|
12
11
|
import { formatPrivateKey } from '../../../utils/private-key.js';
|
|
13
|
-
import { prompt } from '../../../utils/prompt.js';
|
|
12
|
+
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
|
|
14
13
|
import { createSignature } from '../../../utils/signature.js';
|
|
15
14
|
import zip from '../../../utils/zip.js';
|
|
16
15
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
@@ -114,13 +113,8 @@ export default defineCommand({
|
|
|
114
113
|
.describe('The percentage of devices to deploy the bundle to. Must be an integer between 0 and 100.'),
|
|
115
114
|
yes: z.boolean().optional().describe('Skip confirmation prompt.'),
|
|
116
115
|
}), { y: 'yes' }),
|
|
117
|
-
action: async (options, args) => {
|
|
116
|
+
action: withAuth(async (options, args) => {
|
|
118
117
|
let { androidEq, androidMax, androidMin, appId, artifactType, channel, commitMessage, commitRef, commitSha, customProperty, expiresInDays, gitRef, iosEq, iosMax, iosMin, path, privateKey, rolloutPercentage, } = options;
|
|
119
|
-
// Check if the user is logged in
|
|
120
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
121
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
122
|
-
process.exit(1);
|
|
123
|
-
}
|
|
124
118
|
// Calculate the expiration date
|
|
125
119
|
let expiresAt;
|
|
126
120
|
if (expiresInDays) {
|
|
@@ -180,36 +174,8 @@ export default defineCommand({
|
|
|
180
174
|
consola.error('You must provide an app ID when running in non-interactive environment.');
|
|
181
175
|
process.exit(1);
|
|
182
176
|
}
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
consola.error('You must create an organization before creating a bundle.');
|
|
186
|
-
process.exit(1);
|
|
187
|
-
}
|
|
188
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
189
|
-
const organizationId = await prompt('Select the organization of the app for which you want to create a bundle.', {
|
|
190
|
-
type: 'select',
|
|
191
|
-
options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
|
|
192
|
-
});
|
|
193
|
-
if (!organizationId) {
|
|
194
|
-
consola.error('You must select the organization of an app for which you want to create a bundle.');
|
|
195
|
-
process.exit(1);
|
|
196
|
-
}
|
|
197
|
-
const apps = await appsService.findAll({
|
|
198
|
-
organizationId,
|
|
199
|
-
});
|
|
200
|
-
if (apps.length === 0) {
|
|
201
|
-
consola.error('You must create an app before creating a bundle.');
|
|
202
|
-
process.exit(1);
|
|
203
|
-
}
|
|
204
|
-
// @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
|
|
205
|
-
appId = await prompt('Which app do you want to deploy to:', {
|
|
206
|
-
type: 'select',
|
|
207
|
-
options: apps.map((app) => ({ label: app.name, value: app.id })),
|
|
208
|
-
});
|
|
209
|
-
if (!appId) {
|
|
210
|
-
consola.error('You must select an app to deploy to.');
|
|
211
|
-
process.exit(1);
|
|
212
|
-
}
|
|
177
|
+
const organizationId = await promptOrganizationSelection({ allowCreate: true });
|
|
178
|
+
appId = await promptAppSelection(organizationId, { allowCreate: true });
|
|
213
179
|
}
|
|
214
180
|
// Prompt for channel if interactive
|
|
215
181
|
if (!channel && !options.yes && isInteractive()) {
|
|
@@ -311,7 +277,7 @@ export default defineCommand({
|
|
|
311
277
|
consola.info(`Deployment URL: ${DEFAULT_CONSOLE_BASE_URL}/apps/${appId}/deployments/${response.appDeploymentId}`);
|
|
312
278
|
}
|
|
313
279
|
consola.success('Live Update successfully uploaded.');
|
|
314
|
-
},
|
|
280
|
+
}),
|
|
315
281
|
});
|
|
316
282
|
const uploadFile = async (options) => {
|
|
317
283
|
let { appId, appBundleId, buffer, href, mimeType, name, privateKeyBuffer, retryOnFailure } = options;
|
|
@@ -9,6 +9,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
9
9
|
import uploadCommand from './upload.js';
|
|
10
10
|
// Mock dependencies
|
|
11
11
|
vi.mock('@/utils/user-config.js');
|
|
12
|
+
vi.mock('@/utils/prompt.js');
|
|
12
13
|
vi.mock('@/services/authorization-service.js');
|
|
13
14
|
vi.mock('@/utils/file.js');
|
|
14
15
|
vi.mock('@/utils/zip.js');
|
|
@@ -46,7 +47,7 @@ describe('apps-liveupdates-upload', () => {
|
|
|
46
47
|
const options = { appId, path: './dist', artifactType: 'zip', rollout: 1 };
|
|
47
48
|
mockAuthorizationService.hasAuthorizationToken.mockReturnValue(false);
|
|
48
49
|
await expect(uploadCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
|
|
49
|
-
expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.
|
|
50
|
+
expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command. Set the `CAPAWESOME_TOKEN` environment variable or use the `--token` option.');
|
|
50
51
|
});
|
|
51
52
|
it('should handle path validation errors', async () => {
|
|
52
53
|
const appId = 'app-123';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import authorizationService from '../../services/authorization-service.js';
|
|
2
1
|
import organizationsService from '../../services/organizations.js';
|
|
2
|
+
import { withAuth } from '../../utils/auth.js';
|
|
3
3
|
import { isInteractive } from '../../utils/environment.js';
|
|
4
4
|
import { prompt } from '../../utils/prompt.js';
|
|
5
5
|
import { defineCommand, defineOptions } from '@robingenz/zli';
|
|
@@ -10,12 +10,8 @@ export default defineCommand({
|
|
|
10
10
|
options: defineOptions(z.object({
|
|
11
11
|
name: z.string().optional().describe('Name of the organization.'),
|
|
12
12
|
})),
|
|
13
|
-
action: async (options, args) => {
|
|
13
|
+
action: withAuth(async (options, args) => {
|
|
14
14
|
let { name } = options;
|
|
15
|
-
if (!authorizationService.hasAuthorizationToken()) {
|
|
16
|
-
consola.error('You must be logged in to run this command. Please run the `login` command first.');
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
15
|
if (!name) {
|
|
20
16
|
if (!isInteractive()) {
|
|
21
17
|
consola.error('You must provide the organization name when running in non-interactive environment.');
|
|
@@ -26,5 +22,5 @@ export default defineCommand({
|
|
|
26
22
|
const response = await organizationsService.create({ name });
|
|
27
23
|
consola.info(`Organization ID: ${response.id}`);
|
|
28
24
|
consola.success('Organization created successfully.');
|
|
29
|
-
},
|
|
25
|
+
}),
|
|
30
26
|
});
|
|
@@ -66,8 +66,10 @@ describe('organizations-create', () => {
|
|
|
66
66
|
const organizationName = 'Test Organization';
|
|
67
67
|
const options = { name: organizationName };
|
|
68
68
|
mockAuthorizationService.hasAuthorizationToken.mockReturnValue(false);
|
|
69
|
+
mockPrompt.mockResolvedValueOnce(false);
|
|
69
70
|
await expect(createOrganizationCommand.action(options, undefined)).rejects.toThrow('Process exited with code 1');
|
|
70
|
-
expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.
|
|
71
|
+
expect(mockConsola.error).toHaveBeenCalledWith('You must be logged in to run this command.');
|
|
72
|
+
expect(mockConsola.error).toHaveBeenCalledWith('Please run the `login` command first.');
|
|
71
73
|
});
|
|
72
74
|
it('should handle API error during creation', async () => {
|
|
73
75
|
const organizationName = 'Test Organization';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import authorizationService from '../services/authorization-service.js';
|
|
2
|
+
import { isInteractive } from '../utils/environment.js';
|
|
3
|
+
import { prompt } from '../utils/prompt.js';
|
|
4
|
+
import consola from 'consola';
|
|
5
|
+
export function withAuth(action) {
|
|
6
|
+
return async (options, args) => {
|
|
7
|
+
if (!authorizationService.hasAuthorizationToken()) {
|
|
8
|
+
if (!isInteractive()) {
|
|
9
|
+
consola.error('You must be logged in to run this command. Set the `CAPAWESOME_TOKEN` environment variable or use the `--token` option.');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
consola.error('You must be logged in to run this command.');
|
|
13
|
+
const shouldLogin = await prompt('Do you want to login now?', {
|
|
14
|
+
type: 'confirm',
|
|
15
|
+
initial: true,
|
|
16
|
+
});
|
|
17
|
+
if (shouldLogin) {
|
|
18
|
+
await (await import('../commands/login.js').then((mod) => mod.default)).action({}, undefined);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
consola.error('Please run the `login` command first.');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return action(options, args);
|
|
26
|
+
};
|
|
27
|
+
}
|