hotcodepush 0.1.0 → 0.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/dist/commands/app/create.js +1 -1
- package/dist/commands/app/delete.js +2 -2
- package/dist/commands/app/get.js +1 -1
- package/dist/commands/app/list.js +1 -1
- package/dist/commands/app/transfer.js +1 -1
- package/dist/commands/app/update.js +1 -1
- package/dist/commands/audience/get.js +2 -2
- package/dist/commands/audit-log/list.js +2 -2
- package/dist/commands/binary/create.js +11 -9
- package/dist/commands/binary/get.js +1 -1
- package/dist/commands/binary/list.js +2 -2
- package/dist/commands/bundle/delete.js +2 -2
- package/dist/commands/bundle/get.js +1 -1
- package/dist/commands/bundle/list.js +2 -2
- package/dist/commands/bundle/upload.js +7 -6
- package/dist/commands/channel/create.js +1 -1
- package/dist/commands/channel/delete.js +3 -3
- package/dist/commands/channel/get.js +1 -1
- package/dist/commands/channel/list.js +1 -1
- package/dist/commands/channel/pause.js +1 -1
- package/dist/commands/channel/resume.js +1 -1
- package/dist/commands/channel/update.js +1 -1
- package/dist/commands/checkout/create.js +1 -1
- package/dist/commands/completion.js +2 -1
- package/dist/commands/customer-portal-session/create.js +1 -1
- package/dist/commands/device/delete.js +2 -2
- package/dist/commands/device/get.js +1 -1
- package/dist/commands/device/list.js +3 -3
- package/dist/commands/device/probe.js +3 -3
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/fingerprint/diff.js +3 -2
- package/dist/commands/fingerprint.js +3 -2
- package/dist/commands/init.js +4 -3
- package/dist/commands/invitation/accept.js +1 -1
- package/dist/commands/invitation/create.js +2 -2
- package/dist/commands/invitation/delete.js +2 -2
- package/dist/commands/invitation/list.js +1 -1
- package/dist/commands/limit/list.js +1 -1
- package/dist/commands/login.js +4 -153
- package/dist/commands/logout.js +7 -5
- package/dist/commands/member/delete.js +2 -2
- package/dist/commands/member/get.js +1 -1
- package/dist/commands/member/list.js +1 -1
- package/dist/commands/member/update.js +2 -2
- package/dist/commands/open.js +1 -1
- package/dist/commands/organization/create.js +1 -1
- package/dist/commands/organization/delete.js +2 -2
- package/dist/commands/organization/get.js +1 -1
- package/dist/commands/organization/list.js +1 -1
- package/dist/commands/organization/update.js +1 -1
- package/dist/commands/release/create.js +5 -5
- package/dist/commands/release/get.js +1 -1
- package/dist/commands/release/list.js +1 -1
- package/dist/commands/release/pause.js +1 -1
- package/dist/commands/release/resume.js +1 -1
- package/dist/commands/release/revoke.js +5 -4
- package/dist/commands/release/rollback.js +3 -3
- package/dist/commands/release/rollout.js +4 -4
- package/dist/commands/release/update.js +2 -2
- package/dist/commands/resource-file/write.js +8 -6
- package/dist/commands/signing-key/add.js +2 -2
- package/dist/commands/signing-key/create.js +2 -2
- package/dist/commands/signing-key/delete.js +1 -1
- package/dist/commands/signing-key/list.js +2 -2
- package/dist/commands/sso-provider/delete.js +1 -1
- package/dist/commands/sso-provider/get.js +1 -1
- package/dist/commands/sso-provider/set.js +2 -2
- package/dist/commands/sso-provider/verify.js +2 -2
- package/dist/commands/statistics/get.js +5 -5
- package/dist/commands/usage/get.js +1 -1
- package/dist/commands/usage/list.js +1 -1
- package/dist/commands/webhook/create.js +3 -3
- package/dist/commands/webhook/delete.js +1 -1
- package/dist/commands/webhook/get.js +2 -2
- package/dist/commands/webhook/list.js +1 -1
- package/dist/commands/webhook/test.js +1 -1
- package/dist/commands/webhook/update.js +3 -3
- package/dist/commands/webhook-delivery/list.js +2 -2
- package/dist/commands/webhook-delivery/redeliver.js +2 -2
- package/dist/commands/whoami.js +1 -1
- package/dist/completion/hotcodepush.fish +75 -75
- package/dist/completion/hotcodepush.zsh +75 -75
- package/dist/utils/audience.js +1 -1
- package/dist/utils/authentication.js +60 -0
- package/dist/utils/build-step.js +1 -1
- package/dist/utils/channel-fields.js +3 -3
- package/dist/utils/cli.js +5 -0
- package/dist/utils/command.js +4 -0
- package/dist/utils/diagnostics.js +20 -0
- package/dist/utils/error-mapping.js +10 -14
- package/dist/utils/login.js +153 -0
- package/dist/utils/output.js +2 -1
- package/dist/utils/release-conditions.js +3 -4
- package/dist/utils/release-output.js +1 -1
- package/dist/utils/resource-resolution.js +1 -1
- package/dist/utils/telemetry.js +3 -2
- package/dist/utils/update-notice.js +2 -1
- package/dist/utils/usage-month.js +1 -1
- package/dist/utils/user-config.js +8 -0
- package/dist/utils/webhook-resolution.js +1 -1
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
4
|
import { InvalidParameterError } from '../../utils/errors.js';
|
|
5
5
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
6
6
|
import { printJson } from '../../utils/output.js';
|
|
@@ -8,7 +8,7 @@ import { fetchAllPages } from '../../utils/pagination.js';
|
|
|
8
8
|
import { confirmConsequence, promptSelect } from '../../utils/prompts.js';
|
|
9
9
|
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
10
10
|
export default defineCommand({
|
|
11
|
-
description: 'Withdraw a pending invitation
|
|
11
|
+
description: 'Withdraw a pending invitation. The link in its mail stops working at once.',
|
|
12
12
|
examples: [
|
|
13
13
|
'hotcodepush invitation delete --invitation anna@example.com',
|
|
14
14
|
'hotcodepush invitation delete --invitation 4c8e2a6f-1d3b-4e97-a5c0-8f2d6b4a1e93 --yes --json',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { printJson, printTable, resolveDate } from '../../utils/output.js';
|
|
5
5
|
import { paginationShape, resolveNextOffset } from '../../utils/pagination.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { printJson, printTable } from '../../utils/output.js';
|
|
5
5
|
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
package/dist/commands/login.js
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
|
-
import { setTimeout } from 'node:timers/promises';
|
|
2
1
|
import { z } from 'zod';
|
|
3
|
-
import { defineCommand } from '
|
|
4
|
-
import { CLI_CLIENT_ID } from '../config/consts.js';
|
|
5
|
-
import { createApiAuthClient, fetchSession, resolveResponseData, } from '../utils/auth-client.js';
|
|
6
|
-
import { openBrowser } from '../utils/browser.js';
|
|
7
|
-
import { isInteractive } from '../utils/environment.js';
|
|
8
|
-
import { resolveApiError } from '../utils/error-mapping.js';
|
|
9
|
-
import { LoginDeniedError, LoginExpiredError, NotLoggedInError, } from '../utils/errors.js';
|
|
2
|
+
import { defineCommand } from '../utils/command.js';
|
|
10
3
|
import { defineCommandOptions } from '../utils/global-options.js';
|
|
4
|
+
import { logIn } from '../utils/login.js';
|
|
11
5
|
import { printJson } from '../utils/output.js';
|
|
12
|
-
import { writeToken } from '../utils/token-store.js';
|
|
13
6
|
import { readUserConfig, writeUserConfig } from '../utils/user-config.js';
|
|
14
|
-
// RFC 8628, section 3.2: without an interval from the server, a client polls every five seconds.
|
|
15
|
-
const DEFAULT_INTERVAL_SECONDS = 5;
|
|
16
|
-
const DEVICE_CODE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
|
|
17
|
-
// RFC 8628, section 3.5: each slow_down adds five seconds to this and every later interval.
|
|
18
|
-
const SLOW_DOWN_INCREMENT_SECONDS = 5;
|
|
19
7
|
export default defineCommand({
|
|
20
8
|
description: 'Log in by approving a one-time code in the browser.',
|
|
9
|
+
authentication: 'optional',
|
|
21
10
|
examples: [
|
|
22
11
|
'hotcodepush login',
|
|
23
12
|
'hotcodepush login --api-url https://api.example.com --json',
|
|
@@ -30,7 +19,7 @@ export default defineCommand({
|
|
|
30
19
|
})
|
|
31
20
|
.transform(apiUrl => apiUrl.replace(/\/+$/, ''))
|
|
32
21
|
.optional()
|
|
33
|
-
.describe('The API to log in to, kept in config.json for every later command
|
|
22
|
+
.describe('The API to log in to, kept in config.json for every later command. Defaults to the one kept there.'),
|
|
34
23
|
}),
|
|
35
24
|
action: async (options) => {
|
|
36
25
|
if (options.apiUrl !== undefined) {
|
|
@@ -45,141 +34,3 @@ export default defineCommand({
|
|
|
45
34
|
}
|
|
46
35
|
},
|
|
47
36
|
});
|
|
48
|
-
// The page and the code go to stderr, so the stdout of the calling command stays its own.
|
|
49
|
-
export async function logIn(options) {
|
|
50
|
-
const authClient = createApiAuthClient();
|
|
51
|
-
const sessionToken = await fetchSessionToken(authClient, isInteractive(options));
|
|
52
|
-
const { session, user } = await fetchSession(createApiAuthClient(sessionToken));
|
|
53
|
-
writeToken(sessionToken);
|
|
54
|
-
deletePendingDeviceAuthorization();
|
|
55
|
-
writeUserConfig({ ...readUserConfig(), sessionId: session.id });
|
|
56
|
-
return { email: user.email, id: user.id, name: user.name };
|
|
57
|
-
}
|
|
58
|
-
// A request without an answer or with a transient status is polled again, since the person may be approving meanwhile.
|
|
59
|
-
async function fetchApprovedSessionToken(authClient, deviceAuthorization) {
|
|
60
|
-
let currentIntervalSeconds = deviceAuthorization.intervalSeconds;
|
|
61
|
-
for (;;) {
|
|
62
|
-
await setTimeout(currentIntervalSeconds * 1000);
|
|
63
|
-
if (isDeviceAuthorizationExpired(deviceAuthorization)) {
|
|
64
|
-
throw new LoginExpiredError();
|
|
65
|
-
}
|
|
66
|
-
const response = await fetchDeviceToken(authClient, deviceAuthorization.deviceCode).catch(() => undefined);
|
|
67
|
-
if (response === undefined) {
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
const { data, error } = response;
|
|
71
|
-
if (error === null) {
|
|
72
|
-
return data.access_token;
|
|
73
|
-
}
|
|
74
|
-
switch (error.error) {
|
|
75
|
-
case 'access_denied':
|
|
76
|
-
throw new LoginDeniedError();
|
|
77
|
-
case 'authorization_pending':
|
|
78
|
-
break;
|
|
79
|
-
case 'expired_token':
|
|
80
|
-
throw new LoginExpiredError();
|
|
81
|
-
case 'slow_down':
|
|
82
|
-
currentIntervalSeconds += SLOW_DOWN_INCREMENT_SECONDS;
|
|
83
|
-
break;
|
|
84
|
-
default:
|
|
85
|
-
if (!isTransientStatus(error.status)) {
|
|
86
|
-
throw resolveApiError(error);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
async function fetchDeviceAuthorization(authClient) {
|
|
92
|
-
const { device_code, expires_in, interval, user_code, verification_uri_complete, } = resolveResponseData(await authClient.device.code({ client_id: CLI_CLIENT_ID }));
|
|
93
|
-
return {
|
|
94
|
-
deviceCode: device_code,
|
|
95
|
-
expiresAt: new Date(Date.now() + expires_in * 1000).toISOString(),
|
|
96
|
-
intervalSeconds: interval,
|
|
97
|
-
userCode: user_code,
|
|
98
|
-
verificationUrl: verification_uri_complete,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
function fetchDeviceToken(authClient, deviceCode) {
|
|
102
|
-
return authClient.device.token({
|
|
103
|
-
client_id: CLI_CLIENT_ID,
|
|
104
|
-
device_code: deviceCode,
|
|
105
|
-
grant_type: DEVICE_CODE_GRANT_TYPE,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
// A code that a non-interactive login kept is redeemed first, with one token request.
|
|
109
|
-
// While pending it is shown again. Denied, expired or unknown, it gives way to a new one.
|
|
110
|
-
async function fetchSessionToken(authClient, isLoginInteractive) {
|
|
111
|
-
const pendingDeviceAuthorization = readPendingDeviceAuthorization();
|
|
112
|
-
if (pendingDeviceAuthorization !== undefined &&
|
|
113
|
-
!isDeviceAuthorizationExpired(pendingDeviceAuthorization)) {
|
|
114
|
-
const { data, error } = await fetchDeviceToken(authClient, pendingDeviceAuthorization.deviceCode);
|
|
115
|
-
if (error === null) {
|
|
116
|
-
return data.access_token;
|
|
117
|
-
}
|
|
118
|
-
switch (error.error) {
|
|
119
|
-
case 'access_denied':
|
|
120
|
-
case 'expired_token':
|
|
121
|
-
case 'invalid_grant':
|
|
122
|
-
break;
|
|
123
|
-
case 'authorization_pending':
|
|
124
|
-
case 'slow_down':
|
|
125
|
-
return fetchSessionTokenOnApproval(authClient, pendingDeviceAuthorization, isLoginInteractive);
|
|
126
|
-
default:
|
|
127
|
-
throw resolveApiError(error);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
deletePendingDeviceAuthorization();
|
|
131
|
-
return fetchSessionTokenOnApproval(authClient, await fetchDeviceAuthorization(authClient), isLoginInteractive);
|
|
132
|
-
}
|
|
133
|
-
// The code is kept, so the next login redeems one that ended before the approval.
|
|
134
|
-
async function fetchSessionTokenOnApproval(authClient, deviceAuthorization, isLoginInteractive) {
|
|
135
|
-
writePendingDeviceAuthorization(deviceAuthorization);
|
|
136
|
-
if (!isLoginInteractive) {
|
|
137
|
-
throw new NotLoggedInError(deviceAuthorization);
|
|
138
|
-
}
|
|
139
|
-
process.stderr.write(`Open ${deviceAuthorization.verificationUrl} and approve the code ${deviceAuthorization.userCode}.\nWaiting for the approval…\n`);
|
|
140
|
-
await openBrowser(deviceAuthorization.verificationUrl);
|
|
141
|
-
return fetchApprovedSessionToken(authClient, deviceAuthorization);
|
|
142
|
-
}
|
|
143
|
-
function deletePendingDeviceAuthorization() {
|
|
144
|
-
const userConfig = readUserConfig();
|
|
145
|
-
if (userConfig.pendingDeviceCode === undefined) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
delete userConfig.pendingDeviceCode;
|
|
149
|
-
delete userConfig.pendingDeviceCodeExpiresAt;
|
|
150
|
-
delete userConfig.pendingUserCode;
|
|
151
|
-
delete userConfig.pendingVerificationUrl;
|
|
152
|
-
writeUserConfig(userConfig);
|
|
153
|
-
}
|
|
154
|
-
function isDeviceAuthorizationExpired({ expiresAt, }) {
|
|
155
|
-
return new Date(expiresAt) <= new Date();
|
|
156
|
-
}
|
|
157
|
-
// The statuses the Node client also retries: a timeout, the rate limit or a server error.
|
|
158
|
-
function isTransientStatus(status) {
|
|
159
|
-
return status === 408 || status === 429 || status >= 500;
|
|
160
|
-
}
|
|
161
|
-
function readPendingDeviceAuthorization() {
|
|
162
|
-
const { pendingDeviceCode, pendingDeviceCodeExpiresAt, pendingUserCode, pendingVerificationUrl, } = readUserConfig();
|
|
163
|
-
if (pendingDeviceCode === undefined ||
|
|
164
|
-
pendingDeviceCodeExpiresAt === undefined ||
|
|
165
|
-
pendingUserCode === undefined ||
|
|
166
|
-
pendingVerificationUrl === undefined) {
|
|
167
|
-
return undefined;
|
|
168
|
-
}
|
|
169
|
-
return {
|
|
170
|
-
deviceCode: pendingDeviceCode,
|
|
171
|
-
expiresAt: pendingDeviceCodeExpiresAt,
|
|
172
|
-
intervalSeconds: DEFAULT_INTERVAL_SECONDS,
|
|
173
|
-
userCode: pendingUserCode,
|
|
174
|
-
verificationUrl: pendingVerificationUrl,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function writePendingDeviceAuthorization({ deviceCode, expiresAt, userCode, verificationUrl, }) {
|
|
178
|
-
writeUserConfig({
|
|
179
|
-
...readUserConfig(),
|
|
180
|
-
pendingDeviceCode: deviceCode,
|
|
181
|
-
pendingDeviceCodeExpiresAt: expiresAt,
|
|
182
|
-
pendingUserCode: userCode,
|
|
183
|
-
pendingVerificationUrl: verificationUrl,
|
|
184
|
-
});
|
|
185
|
-
}
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiAuthClient } from '../utils/auth-client.js';
|
|
2
|
+
import { defineCommand } from '../utils/command.js';
|
|
3
3
|
import { resolveApiError } from '../utils/error-mapping.js';
|
|
4
4
|
import { NotLoggedInError } from '../utils/errors.js';
|
|
5
5
|
import { defineCommandOptions } from '../utils/global-options.js';
|
|
@@ -8,7 +8,8 @@ import { deleteToken, readStoredToken } from '../utils/token-store.js';
|
|
|
8
8
|
import { readUserConfig, writeUserConfig } from '../utils/user-config.js';
|
|
9
9
|
const UNAUTHORIZED_STATUS = 401;
|
|
10
10
|
export default defineCommand({
|
|
11
|
-
description: 'End the stored session and remove its token
|
|
11
|
+
description: 'End the stored session and remove its token. HOTCODEPUSH_TOKEN, when set, stays what it is.',
|
|
12
|
+
authentication: 'optional',
|
|
12
13
|
examples: ['hotcodepush logout', 'hotcodepush logout --json'],
|
|
13
14
|
options: defineCommandOptions({}),
|
|
14
15
|
action: async (options) => {
|
|
@@ -30,19 +31,20 @@ export default defineCommand({
|
|
|
30
31
|
throw resolveApiError(error);
|
|
31
32
|
}
|
|
32
33
|
deleteToken();
|
|
33
|
-
const storedSessionId =
|
|
34
|
+
const storedSessionId = deleteStoredSession();
|
|
34
35
|
printEnded({
|
|
35
36
|
id: knownSession?.session.id ?? storedSessionId ?? null,
|
|
36
37
|
name: knownSession?.user.name ?? null,
|
|
37
38
|
}, options.json);
|
|
38
39
|
},
|
|
39
40
|
});
|
|
40
|
-
function
|
|
41
|
+
function deleteStoredSession() {
|
|
41
42
|
const userConfig = readUserConfig();
|
|
42
43
|
const { sessionId } = userConfig;
|
|
43
|
-
if (sessionId === undefined) {
|
|
44
|
+
if (sessionId === undefined && userConfig.sessionExpiresAt === undefined) {
|
|
44
45
|
return undefined;
|
|
45
46
|
}
|
|
47
|
+
delete userConfig.sessionExpiresAt;
|
|
46
48
|
delete userConfig.sessionId;
|
|
47
49
|
writeUserConfig(userConfig);
|
|
48
50
|
return sessionId;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { fetchMember, memberOptionShape, resolveMemberEmail, } from '../../utils/member-resolution.js';
|
|
5
5
|
import { printJson } from '../../utils/output.js';
|
|
6
6
|
import { confirmConsequence } from '../../utils/prompts.js';
|
|
7
7
|
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
8
8
|
export default defineCommand({
|
|
9
|
-
description: 'Remove a member from the organization, or yourself to leave it
|
|
9
|
+
description: 'Remove a member from the organization, or yourself to leave it. The Owner leaves only after transferring the ownership.',
|
|
10
10
|
examples: [
|
|
11
11
|
'hotcodepush member delete --member bob@example.com',
|
|
12
12
|
'hotcodepush member delete --member 5e8a2c71-0b4d-4f39-9a6e-3c1d7b2f8e40 --yes --json',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { fetchMember, memberOptionShape, resolveMemberEmail, } from '../../utils/member-resolution.js';
|
|
5
5
|
import { printDetails, printJson } from '../../utils/output.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { resolveMemberEmail } from '../../utils/member-resolution.js';
|
|
5
5
|
import { printJson, printTable, resolveDate } from '../../utils/output.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
4
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
5
|
import { fetchMember, memberOptionShape, resolveMemberEmail, } from '../../utils/member-resolution.js';
|
|
6
6
|
import { printJson } from '../../utils/output.js';
|
|
@@ -33,7 +33,7 @@ export default defineCommand({
|
|
|
33
33
|
(await promptSelect('--role', 'Which role does the member get?', MEMBER_ROLES.map(role => ({ label: role, value: role })), options));
|
|
34
34
|
const email = resolveMemberEmail(fetchedMember);
|
|
35
35
|
if (role === 'owner') {
|
|
36
|
-
const isConfirmed = await confirmConsequence(`transfers the ownership of the organization to ${email} and makes you an admin
|
|
36
|
+
const isConfirmed = await confirmConsequence(`transfers the ownership of the organization to ${email} and makes you an admin, and only the new owner can transfer it back`, options);
|
|
37
37
|
if (!isConfirmed) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
package/dist/commands/open.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../utils/api-client.js';
|
|
3
2
|
import { openBrowser } from '../utils/browser.js';
|
|
3
|
+
import { defineCommand } from '../utils/command.js';
|
|
4
4
|
import { defineCommandOptions } from '../utils/global-options.js';
|
|
5
5
|
import { resolveConsoleBaseUrl } from '../utils/hosts.js';
|
|
6
6
|
import { printJson } from '../utils/output.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
4
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
5
|
import { printJson } from '../../utils/output.js';
|
|
6
6
|
import { promptText } from '../../utils/prompts.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { printJson, resolveQuantityText } from '../../utils/output.js';
|
|
5
5
|
import { confirmConsequence } from '../../utils/prompts.js';
|
|
6
6
|
import { fetchApps, fetchOrganizationId, } from '../../utils/resource-resolution.js';
|
|
7
7
|
export default defineCommand({
|
|
8
|
-
description: 'Delete an organization with everything in it
|
|
8
|
+
description: 'Delete an organization with everything in it. Support can restore it for seven days.',
|
|
9
9
|
examples: [
|
|
10
10
|
'hotcodepush organization delete --organization Acme',
|
|
11
11
|
'hotcodepush organization delete --organization Acme --yes --json',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { printDetails, printJson } from '../../utils/output.js';
|
|
5
5
|
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { resolveMemberRole } from '../../utils/member-resolution.js';
|
|
5
5
|
import { printJson, printTable, resolveDate } from '../../utils/output.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
4
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
5
|
import { printJson } from '../../utils/output.js';
|
|
6
6
|
import { confirmConsequence, promptText } from '../../utils/prompts.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
4
3
|
import { resolveAudienceText } from '../../utils/audience.js';
|
|
5
4
|
import { booleanFlagSchema } from '../../utils/boolean-flag.js';
|
|
6
5
|
import { fetchBundle, resolveBundleLabel, } from '../../utils/bundle-resolution.js';
|
|
7
6
|
import { failurePolicyShape, resolveFailurePolicy, } from '../../utils/channel-fields.js';
|
|
7
|
+
import { defineCommand } from '../../utils/command.js';
|
|
8
8
|
import { withTemporaryDirectory } from '../../utils/compressed-files.js';
|
|
9
9
|
import { InvalidParameterError } from '../../utils/errors.js';
|
|
10
10
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
@@ -32,15 +32,15 @@ export default defineCommand({
|
|
|
32
32
|
bundle: z
|
|
33
33
|
.string()
|
|
34
34
|
.optional()
|
|
35
|
-
.describe('A bundle already uploaded, by number or id
|
|
35
|
+
.describe('A bundle already uploaded, by number or id. Without it the build is uploaded first.'),
|
|
36
36
|
channel: z
|
|
37
37
|
.array(z.string())
|
|
38
38
|
.optional()
|
|
39
|
-
.describe("The channel, by id or name, repeatable
|
|
39
|
+
.describe("The channel, by id or name, repeatable. Defaults to hotcodepush.json's channel."),
|
|
40
40
|
dryRun: z
|
|
41
41
|
.boolean()
|
|
42
42
|
.optional()
|
|
43
|
-
.describe('Validate and print the audience the release would reach
|
|
43
|
+
.describe('Validate and print the audience the release would reach. Nothing is signed, uploaded or published, so no private key is needed.'),
|
|
44
44
|
fromChannel: z
|
|
45
45
|
.string()
|
|
46
46
|
.optional()
|
|
@@ -51,7 +51,7 @@ export default defineCommand({
|
|
|
51
51
|
notes: z
|
|
52
52
|
.string()
|
|
53
53
|
.optional()
|
|
54
|
-
.describe('The release notes
|
|
54
|
+
.describe('The release notes. They ride the public index.'),
|
|
55
55
|
rolloutPercent: z.coerce
|
|
56
56
|
.number()
|
|
57
57
|
.int()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
2
|
import { resolveEffectiveFailurePolicy, resolveFailurePolicyDetails, } from '../../utils/channel-fields.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
4
|
import { resolveReleaseDeviceCount } from '../../utils/fleet.js';
|
|
5
5
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
6
6
|
import { printDetails, printJson } from '../../utils/output.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { resolveReleaseDeviceCount } from '../../utils/fleet.js';
|
|
4
4
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
5
|
import { printJson, printTable, resolveDate } from '../../utils/output.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { printJson } from '../../utils/output.js';
|
|
5
5
|
import { confirmConsequence } from '../../utils/prompts.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
3
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
4
|
import { printJson } from '../../utils/output.js';
|
|
5
5
|
import { confirmConsequence } from '../../utils/prompts.js';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
4
3
|
import { fetchBundle } from '../../utils/bundle-resolution.js';
|
|
4
|
+
import { defineCommand } from '../../utils/command.js';
|
|
5
|
+
import { printWarning } from '../../utils/diagnostics.js';
|
|
5
6
|
import { InvalidParameterError } from '../../utils/errors.js';
|
|
6
7
|
import { resolveReleaseDeviceCount } from '../../utils/fleet.js';
|
|
7
8
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
@@ -25,11 +26,11 @@ export default defineCommand({
|
|
|
25
26
|
all: z
|
|
26
27
|
.boolean()
|
|
27
28
|
.optional()
|
|
28
|
-
.describe('Every release of the channel
|
|
29
|
+
.describe('Every release of the channel. Its devices return to the embedded bundle.'),
|
|
29
30
|
bundle: z
|
|
30
31
|
.string()
|
|
31
32
|
.optional()
|
|
32
|
-
.describe("Every release of this bundle, by number or id, across the app's channels
|
|
33
|
+
.describe("Every release of this bundle, by number or id, across the app's channels. Takes no --channel."),
|
|
33
34
|
releaseFrom: z.coerce
|
|
34
35
|
.number()
|
|
35
36
|
.int()
|
|
@@ -50,7 +51,7 @@ export default defineCommand({
|
|
|
50
51
|
appId: firstRevocation.channel.appId,
|
|
51
52
|
});
|
|
52
53
|
for (const pausedText of resolvePausedLandingTexts(revocations, fleet)) {
|
|
53
|
-
|
|
54
|
+
printWarning(pausedText);
|
|
54
55
|
}
|
|
55
56
|
const isConfirmed = await confirmConsequence(resolveRevocationConsequence(revocations, fleet), options);
|
|
56
57
|
if (!isConfirmed) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
4
3
|
import { booleanFlagSchema } from '../../utils/boolean-flag.js';
|
|
4
|
+
import { defineCommand } from '../../utils/command.js';
|
|
5
5
|
import { InvalidParameterError } from '../../utils/errors.js';
|
|
6
6
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
7
7
|
import { printJson } from '../../utils/output.js';
|
|
@@ -19,11 +19,11 @@ export default defineCommand({
|
|
|
19
19
|
...channelOptionShape,
|
|
20
20
|
mandatory: booleanFlagSchema
|
|
21
21
|
.optional()
|
|
22
|
-
.describe('Devices apply the rollback at once and restart, the default for an incident fix
|
|
22
|
+
.describe('Devices apply the rollback at once and restart, the default for an incident fix. Pass false to let them wait.'),
|
|
23
23
|
toRelease: z
|
|
24
24
|
.string()
|
|
25
25
|
.optional()
|
|
26
|
-
.describe("The release whose bundle comes back, by number or id
|
|
26
|
+
.describe("The release whose bundle comes back, by number or id. Defaults to the channel's previous one."),
|
|
27
27
|
}),
|
|
28
28
|
action: async (options) => {
|
|
29
29
|
const hotCodePush = createApiClient();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
4
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
5
|
import { printJson } from '../../utils/output.js';
|
|
6
6
|
import { progressionShape, resolveProgression, resolveProgressionText, } from '../../utils/progression.js';
|
|
@@ -10,7 +10,7 @@ import { fetchReleaseInChannel, releaseOptionShape, } from '../../utils/release-
|
|
|
10
10
|
import { channelOptionShape } from '../../utils/resource-resolution.js';
|
|
11
11
|
const rolloutPercentSchema = z.coerce.number().int().min(0).max(100);
|
|
12
12
|
export default defineCommand({
|
|
13
|
-
description: "Set a release's rollout percentage in either direction, or widen it step by step with --progression
|
|
13
|
+
description: "Set a release's rollout percentage in either direction, or widen it step by step with --progression. A device that has the release keeps it.",
|
|
14
14
|
examples: [
|
|
15
15
|
'hotcodepush release rollout --release 43 --rollout-percent 50',
|
|
16
16
|
'hotcodepush release rollout --channel staging --release 43 --rollout-percent 10 --progression --yes',
|
|
@@ -21,7 +21,7 @@ export default defineCommand({
|
|
|
21
21
|
...releaseOptionShape,
|
|
22
22
|
rolloutPercent: rolloutPercentSchema
|
|
23
23
|
.optional()
|
|
24
|
-
.describe("The share of devices the release reaches from now on, 0 to 100
|
|
24
|
+
.describe("The share of devices the release reaches from now on, 0 to 100. With --progression it is where the schedule starts. Defaults to the release's own percentage."),
|
|
25
25
|
}),
|
|
26
26
|
action: async (options) => {
|
|
27
27
|
const hotCodePush = createApiClient();
|
|
@@ -58,6 +58,6 @@ function resolveRolloutConsequence(release, channelName, rolloutPercent, progres
|
|
|
58
58
|
if (progression !== null) {
|
|
59
59
|
return `progresses ${releaseText} from ${rolloutPercent} percent through ${resolveProgressionText(progression)}: devices already on it keep it`;
|
|
60
60
|
}
|
|
61
|
-
const progressionEndText = release.progression === null ? '' : '
|
|
61
|
+
const progressionEndText = release.progression === null ? '' : ', and its progression ends';
|
|
62
62
|
return `sets ${releaseText} to ${rolloutPercent} percent: devices already on it keep it, and no new device above ${rolloutPercent} percent gets it${progressionEndText}`;
|
|
63
63
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineCommand } from 'zodline';
|
|
3
2
|
import { createApiClient } from '../../utils/api-client.js';
|
|
4
3
|
import { booleanFlagSchema } from '../../utils/boolean-flag.js';
|
|
5
4
|
import { failurePolicyShape, releaseFailurePolicyClearShape, resolveFailurePolicy, } from '../../utils/channel-fields.js';
|
|
5
|
+
import { defineCommand } from '../../utils/command.js';
|
|
6
6
|
import { MissingParameterError } from '../../utils/errors.js';
|
|
7
7
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
8
8
|
import { resolveNullableField } from '../../utils/nullable-field.js';
|
|
@@ -25,7 +25,7 @@ export default defineCommand({
|
|
|
25
25
|
clearNotes: z.boolean().optional().describe('Sets the notes back to null.'),
|
|
26
26
|
mandatory: booleanFlagSchema
|
|
27
27
|
.optional()
|
|
28
|
-
.describe('Whether devices apply the release at once and restart
|
|
28
|
+
.describe('Whether devices apply the release at once and restart. Pass false to turn it off.'),
|
|
29
29
|
notes: z.string().optional().describe('The new release notes.'),
|
|
30
30
|
}),
|
|
31
31
|
action: async (options) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { defineCommand } from 'zodline';
|
|
2
1
|
import { createApiClient } from '../../utils/api-client.js';
|
|
3
2
|
import { buildStepShape, fetchChannelId, readBuildStep, resolveChannelIdByShape, resolveFailureText, resolveOfflineCause, writeBuildResourceFile, } from '../../utils/build-step.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
|
+
import { printNotice, printWarning } from '../../utils/diagnostics.js';
|
|
4
5
|
import { CliError } from '../../utils/errors.js';
|
|
5
6
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
6
7
|
import { printJson } from '../../utils/output.js';
|
|
@@ -8,6 +9,7 @@ import { printJson } from '../../utils/output.js';
|
|
|
8
9
|
const UNVERSIONED_BUNDLE_VERSION = '';
|
|
9
10
|
export default defineCommand({
|
|
10
11
|
description: 'The build step of every build that is no store build: writes the resource file the SDK reads, listing the embedded bundle, and creates no binary. Without a token, offline or with an API that cannot be reached, the channel name stays unresolved and one warning says so, in CI too.',
|
|
12
|
+
authentication: 'optional',
|
|
11
13
|
examples: [
|
|
12
14
|
'hotcodepush resource-file write --platform ios --embedded-bundle-path build/App.app/public --resource-file-path build/App.app/hotcodepush.json',
|
|
13
15
|
'hotcodepush resource-file write --platform android --embedded-bundle-path build/assets/public --resource-file-path build/assets/hotcodepush.json --json',
|
|
@@ -18,7 +20,7 @@ export default defineCommand({
|
|
|
18
20
|
const { embeddedFiles, platform, resourceFilePath } = buildStep;
|
|
19
21
|
if (embeddedFiles === undefined) {
|
|
20
22
|
writeBuildResourceFile(buildStep, resolveChannelIdByShape(buildStep.channelReference), null);
|
|
21
|
-
|
|
23
|
+
printNotice(`The ${platform} build bundled no JavaScript, as a debug build served by the development server does. Wrote ${resourceFilePath} without an embedded bundle: over-the-air (OTA) updates are off in this build.`);
|
|
22
24
|
if (options.json) {
|
|
23
25
|
printJson({ resourceFilePath });
|
|
24
26
|
}
|
|
@@ -31,7 +33,7 @@ export default defineCommand({
|
|
|
31
33
|
id: null,
|
|
32
34
|
});
|
|
33
35
|
if (skippedReason !== null) {
|
|
34
|
-
|
|
36
|
+
printWarning(skippedReason);
|
|
35
37
|
}
|
|
36
38
|
if (options.json) {
|
|
37
39
|
printJson({ resourceFilePath });
|
|
@@ -65,12 +67,12 @@ async function resolveChannel(buildStep) {
|
|
|
65
67
|
}
|
|
66
68
|
return {
|
|
67
69
|
channelId: null,
|
|
68
|
-
skippedReason: `
|
|
70
|
+
skippedReason: `The channel could not be resolved, so the build names none and takes no OTA updates: ${resolveFailureText(error)}`,
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
function resolveOfflineText(offlineCause) {
|
|
73
75
|
return offlineCause === 'offline-switch'
|
|
74
|
-
? 'HOTCODEPUSH_OFFLINE is set, so the channel name was not resolved
|
|
75
|
-
: '
|
|
76
|
+
? 'HOTCODEPUSH_OFFLINE is set, so the channel name was not resolved. The build names no channel and takes no OTA updates.'
|
|
77
|
+
: 'Not logged in, so the channel name was not resolved. The build names no channel and takes no OTA updates. Run "hotcodepush login" or set HOTCODEPUSH_TOKEN.';
|
|
76
78
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { defineCommand } from 'zodline';
|
|
4
3
|
import { createApiClient } from '../../utils/api-client.js';
|
|
4
|
+
import { defineCommand } from '../../utils/command.js';
|
|
5
5
|
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
6
6
|
import { printJson } from '../../utils/output.js';
|
|
7
7
|
import { locateProjectConfig } from '../../utils/project-config.js';
|
|
@@ -19,7 +19,7 @@ export default defineCommand({
|
|
|
19
19
|
privateKeyPath: z
|
|
20
20
|
.string()
|
|
21
21
|
.optional()
|
|
22
|
-
.describe('The private key file of the pair, a PEM of PKCS #8 or PKCS #1, read on this machine
|
|
22
|
+
.describe('The private key file of the pair, a PEM of PKCS #8 or PKCS #1, read on this machine. Its public key is derived from it.'),
|
|
23
23
|
}),
|
|
24
24
|
action: async (options) => {
|
|
25
25
|
const privateKeyPath = resolve(options.privateKeyPath ??
|