hotcodepush 0.0.1 → 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/README.md +3 -3
- package/dist/commands/app/create.js +49 -0
- package/dist/commands/app/delete.js +34 -0
- package/dist/commands/app/get.js +33 -0
- package/dist/commands/app/list.js +38 -0
- package/dist/commands/app/transfer.js +58 -0
- package/dist/commands/app/update.js +34 -0
- package/dist/commands/audience/get.js +69 -0
- package/dist/commands/audit-log/list.js +82 -0
- package/dist/commands/binary/create.js +191 -0
- package/dist/commands/binary/get.js +56 -0
- package/dist/commands/binary/list.js +58 -0
- package/dist/commands/bundle/delete.js +35 -0
- package/dist/commands/bundle/get.js +63 -0
- package/dist/commands/bundle/list.js +66 -0
- package/dist/commands/bundle/upload.js +177 -0
- package/dist/commands/channel/create.js +59 -0
- package/dist/commands/channel/delete.js +68 -0
- package/dist/commands/channel/get.js +45 -0
- package/dist/commands/channel/list.js +39 -0
- package/dist/commands/channel/pause.js +32 -0
- package/dist/commands/channel/resume.js +32 -0
- package/dist/commands/channel/update.js +40 -0
- package/dist/commands/checkout/create.js +25 -0
- package/dist/commands/completion.js +37 -0
- package/dist/commands/customer-portal-session/create.js +25 -0
- package/dist/commands/device/delete.js +29 -0
- package/dist/commands/device/get.js +60 -0
- package/dist/commands/device/list.js +97 -0
- package/dist/commands/device/probe.js +253 -0
- package/dist/commands/doctor.js +364 -0
- package/dist/commands/fingerprint/diff.js +134 -0
- package/dist/commands/fingerprint.js +42 -0
- package/dist/commands/init.js +493 -0
- package/dist/commands/invitation/accept.js +53 -0
- package/dist/commands/invitation/create.js +52 -0
- package/dist/commands/invitation/delete.js +60 -0
- package/dist/commands/invitation/list.js +40 -0
- package/dist/commands/limit/list.js +34 -0
- package/dist/commands/login.js +36 -0
- package/dist/commands/logout.js +81 -0
- package/dist/commands/member/delete.js +35 -0
- package/dist/commands/member/get.js +37 -0
- package/dist/commands/member/list.js +41 -0
- package/dist/commands/member/update.js +53 -0
- package/dist/commands/open.js +37 -0
- package/dist/commands/organization/create.js +30 -0
- package/dist/commands/organization/delete.js +39 -0
- package/dist/commands/organization/get.js +38 -0
- package/dist/commands/organization/list.js +41 -0
- package/dist/commands/organization/update.js +64 -0
- package/dist/commands/release/create.js +237 -0
- package/dist/commands/release/get.js +81 -0
- package/dist/commands/release/list.js +69 -0
- package/dist/commands/release/pause.js +36 -0
- package/dist/commands/release/resume.js +36 -0
- package/dist/commands/release/revoke.js +254 -0
- package/dist/commands/release/rollback.js +73 -0
- package/dist/commands/release/rollout.js +63 -0
- package/dist/commands/release/update.js +82 -0
- package/dist/commands/resource-file/write.js +78 -0
- package/dist/commands/signing-key/add.js +45 -0
- package/dist/commands/signing-key/create.js +84 -0
- package/dist/commands/signing-key/delete.js +67 -0
- package/dist/commands/signing-key/list.js +38 -0
- package/dist/commands/sso-provider/delete.js +32 -0
- package/dist/commands/sso-provider/get.js +63 -0
- package/dist/commands/sso-provider/set.js +161 -0
- package/dist/commands/sso-provider/verify.js +31 -0
- package/dist/commands/statistics/get.js +189 -0
- package/dist/commands/usage/get.js +31 -0
- package/dist/commands/usage/list.js +41 -0
- package/dist/commands/webhook/create.js +72 -0
- package/dist/commands/webhook/delete.js +32 -0
- package/dist/commands/webhook/get.js +34 -0
- package/dist/commands/webhook/list.js +40 -0
- package/dist/commands/webhook/test.js +32 -0
- package/dist/commands/webhook/update.js +56 -0
- package/dist/commands/webhook-delivery/list.js +63 -0
- package/dist/commands/webhook-delivery/redeliver.js +48 -0
- package/dist/commands/whoami.js +24 -0
- package/dist/completion/hotcodepush.bash +536 -0
- package/dist/completion/hotcodepush.fish +979 -0
- package/dist/completion/hotcodepush.zsh +1372 -0
- package/dist/config/consts.js +32 -0
- package/dist/index.js +5 -0
- package/dist/registry.js +83 -0
- package/dist/utils/api-client.js +17 -0
- package/dist/utils/audience.js +9 -0
- package/dist/utils/auth-client.js +35 -0
- package/dist/utils/authentication.js +60 -0
- package/dist/utils/boolean-flag.js +3 -0
- package/dist/utils/browser.js +6 -0
- package/dist/utils/build-step.js +104 -0
- package/dist/utils/bundle-files.js +80 -0
- package/dist/utils/bundle-resolution.js +46 -0
- package/dist/utils/channel-fields.js +130 -0
- package/dist/utils/cli.js +80 -0
- package/dist/utils/command-registry.js +79 -0
- package/dist/utils/command.js +4 -0
- package/dist/utils/completion/bash.js +48 -0
- package/dist/utils/completion/command-tree.js +72 -0
- package/dist/utils/completion/fish.js +44 -0
- package/dist/utils/completion/posix-case-arms.js +9 -0
- package/dist/utils/completion/posix-quote.js +4 -0
- package/dist/utils/completion/script-files.js +26 -0
- package/dist/utils/completion/zsh.js +72 -0
- package/dist/utils/compressed-files.js +31 -0
- package/dist/utils/credential.js +15 -0
- package/dist/utils/device-resolution.js +17 -0
- package/dist/utils/diagnostics.js +20 -0
- package/dist/utils/duration.js +16 -0
- package/dist/utils/environment.js +22 -0
- package/dist/utils/error-mapping.js +75 -0
- package/dist/utils/errors.js +266 -0
- package/dist/utils/fingerprint.js +76 -0
- package/dist/utils/flag-name.js +4 -0
- package/dist/utils/fleet.js +9 -0
- package/dist/utils/framework.js +74 -0
- package/dist/utils/frameworks/binary-create-step.js +70 -0
- package/dist/utils/frameworks/capacitor.js +150 -0
- package/dist/utils/frameworks/cordova.js +110 -0
- package/dist/utils/frameworks/expo.js +152 -0
- package/dist/utils/frameworks/index.js +13 -0
- package/dist/utils/frameworks/native-glue.js +10 -0
- package/dist/utils/frameworks/native-projects.js +27 -0
- package/dist/utils/frameworks/react-native-build.js +182 -0
- package/dist/utils/frameworks/react-native.js +127 -0
- package/dist/utils/frameworks/sdk-package.js +63 -0
- package/dist/utils/git-provenance.js +71 -0
- package/dist/utils/global-options.js +34 -0
- package/dist/utils/hosts.js +53 -0
- package/dist/utils/init-steps.js +51 -0
- package/dist/utils/json-file.js +28 -0
- package/dist/utils/login.js +153 -0
- package/dist/utils/member-resolution.js +49 -0
- package/dist/utils/native-project-edit.js +41 -0
- package/dist/utils/nullable-field.js +10 -0
- package/dist/utils/outcome.js +24 -0
- package/dist/utils/output.js +38 -0
- package/dist/utils/pack.js +20 -0
- package/dist/utils/package-json.js +5 -0
- package/dist/utils/package-manager.js +50 -0
- package/dist/utils/pagination.js +29 -0
- package/dist/utils/progress.js +23 -0
- package/dist/utils/progression.js +119 -0
- package/dist/utils/project-config.js +61 -0
- package/dist/utils/prompts.js +53 -0
- package/dist/utils/react-native-project.js +119 -0
- package/dist/utils/release-conditions.js +79 -0
- package/dist/utils/release-output.js +13 -0
- package/dist/utils/release-resolution.js +83 -0
- package/dist/utils/resource-file.js +81 -0
- package/dist/utils/resource-resolution.js +107 -0
- package/dist/utils/signing-private-key.js +105 -0
- package/dist/utils/spending-cap.js +16 -0
- package/dist/utils/telemetry.js +172 -0
- package/dist/utils/token-store.js +63 -0
- package/dist/utils/update-notice.js +68 -0
- package/dist/utils/upload.js +148 -0
- package/dist/utils/usage-month.js +14 -0
- package/dist/utils/user-config.js +54 -0
- package/dist/utils/webhook-resolution.js +47 -0
- package/dist/utils/xcode-project.js +181 -0
- package/package.json +11 -9
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
|
+
import { printDetails, printJson } from '../../utils/output.js';
|
|
5
|
+
import { resolveByteText } from '../../utils/progress.js';
|
|
6
|
+
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
7
|
+
import { monthOptionShape, resolveMonthText } from '../../utils/usage-month.js';
|
|
8
|
+
export default defineCommand({
|
|
9
|
+
description: "Print an organization's monthly active devices and data transfer in a month, the totals the invoice counts.",
|
|
10
|
+
examples: [
|
|
11
|
+
'hotcodepush usage get',
|
|
12
|
+
'hotcodepush usage get --organization Acme --month 2026-09 --json',
|
|
13
|
+
],
|
|
14
|
+
options: defineCommandOptions(monthOptionShape),
|
|
15
|
+
action: async (options) => {
|
|
16
|
+
const hotCodePush = createApiClient();
|
|
17
|
+
const fetchedUsage = await hotCodePush.organizations.usage.get({
|
|
18
|
+
month: options.month,
|
|
19
|
+
organizationId: await fetchOrganizationId(hotCodePush, options),
|
|
20
|
+
});
|
|
21
|
+
if (options.json) {
|
|
22
|
+
printJson(fetchedUsage);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
printDetails([
|
|
26
|
+
['Month', resolveMonthText(fetchedUsage.month)],
|
|
27
|
+
['MAU', String(fetchedUsage.monthlyActiveDeviceCount)],
|
|
28
|
+
['Data transfer', resolveByteText(fetchedUsage.dataTransferBytes)],
|
|
29
|
+
]);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
|
+
import { printJson, printTable } from '../../utils/output.js';
|
|
5
|
+
import { paginationShape, resolveNextOffset } from '../../utils/pagination.js';
|
|
6
|
+
import { resolveByteText } from '../../utils/progress.js';
|
|
7
|
+
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
8
|
+
import { monthOptionShape } from '../../utils/usage-month.js';
|
|
9
|
+
export default defineCommand({
|
|
10
|
+
description: "List an organization's apps with their monthly active devices and data transfer in a month, the most devices first.",
|
|
11
|
+
examples: [
|
|
12
|
+
'hotcodepush usage list --month 2026-09',
|
|
13
|
+
'hotcodepush usage list --organization Acme --limit 10 --offset 10 --json',
|
|
14
|
+
],
|
|
15
|
+
options: defineCommandOptions({ ...monthOptionShape, ...paginationShape }),
|
|
16
|
+
action: async (options) => {
|
|
17
|
+
const hotCodePush = createApiClient();
|
|
18
|
+
const listedApps = await hotCodePush.organizations.usage.apps.list({
|
|
19
|
+
limit: options.limit,
|
|
20
|
+
month: options.month,
|
|
21
|
+
offset: options.offset,
|
|
22
|
+
organizationId: await fetchOrganizationId(hotCodePush, options),
|
|
23
|
+
relations: ['app'],
|
|
24
|
+
});
|
|
25
|
+
const nextOffset = resolveNextOffset(listedApps.length, options);
|
|
26
|
+
if (options.json) {
|
|
27
|
+
printJson({ apps: listedApps, nextOffset });
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
printTable({
|
|
31
|
+
emptyText: 'No app had monthly active devices in the month.',
|
|
32
|
+
headers: ['APP', 'MAU', 'DATA TRANSFER'],
|
|
33
|
+
nextOffset,
|
|
34
|
+
rows: listedApps.map(({ app, appId, dataTransferBytes, monthlyActiveDeviceCount }) => [
|
|
35
|
+
app?.name ?? appId,
|
|
36
|
+
String(monthlyActiveDeviceCount),
|
|
37
|
+
resolveByteText(dataTransferBytes),
|
|
38
|
+
]),
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
|
+
import { printJson } from '../../utils/output.js';
|
|
6
|
+
import { promptSelect, promptText } from '../../utils/prompts.js';
|
|
7
|
+
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
8
|
+
import { fetchWebhookAppId, resolveWebhookEventTypes, webhookAppOptionShape, webhookEventOptionShape, } from '../../utils/webhook-resolution.js';
|
|
9
|
+
const WEBHOOK_FORMATS = ['raw', 'slack', 'discord', 'teams'];
|
|
10
|
+
export default defineCommand({
|
|
11
|
+
description: "Create a webhook that posts the organization's events to a URL, as signed JSON or as a Slack, Discord or Teams message. A raw webhook's secret is printed this once.",
|
|
12
|
+
examples: [
|
|
13
|
+
'hotcodepush webhook create --name releases --url https://example.com/hooks/hotcodepush --format raw --event release.created --event release.paused',
|
|
14
|
+
'hotcodepush webhook create --name team-chat --url https://chat.example.com/incoming/team --format slack --event release.failure_rate_exceeded --app "My App" --json',
|
|
15
|
+
],
|
|
16
|
+
options: defineCommandOptions({
|
|
17
|
+
...webhookAppOptionShape,
|
|
18
|
+
...webhookEventOptionShape,
|
|
19
|
+
format: z
|
|
20
|
+
.enum(WEBHOOK_FORMATS)
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("raw for HotCodePush's signed JSON, slack, discord or teams for a message to that service's incoming-webhook URL."),
|
|
23
|
+
name: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('The name, unique in the organization.'),
|
|
27
|
+
url: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('The https URL the events are posted to.'),
|
|
31
|
+
}),
|
|
32
|
+
action: async (options) => {
|
|
33
|
+
const hotCodePush = createApiClient();
|
|
34
|
+
const organizationId = await fetchOrganizationId(hotCodePush, options);
|
|
35
|
+
const name = options.name ??
|
|
36
|
+
(await promptText('--name', 'What is the webhook called?', options));
|
|
37
|
+
const url = options.url ??
|
|
38
|
+
(await promptText('--url', 'Which URL receives the events?', options));
|
|
39
|
+
const format = options.format ?? (await promptFormat(options));
|
|
40
|
+
const events = options.event?.length
|
|
41
|
+
? options.event
|
|
42
|
+
: [
|
|
43
|
+
await promptText('--event', 'Which event type, such as release.created?', options),
|
|
44
|
+
];
|
|
45
|
+
const createdWebhook = await hotCodePush.organizations.webhooks.create({
|
|
46
|
+
appId: options.app === undefined
|
|
47
|
+
? undefined
|
|
48
|
+
: await fetchWebhookAppId(hotCodePush, organizationId, options.app),
|
|
49
|
+
events: resolveWebhookEventTypes(events),
|
|
50
|
+
format,
|
|
51
|
+
name,
|
|
52
|
+
organizationId,
|
|
53
|
+
url,
|
|
54
|
+
});
|
|
55
|
+
if (options.json) {
|
|
56
|
+
printJson(createdWebhook);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
printCreatedWebhook(createdWebhook);
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
function printCreatedWebhook(webhook) {
|
|
63
|
+
console.log(`Created webhook ${webhook.name} (${webhook.id}).`);
|
|
64
|
+
if (webhook.secret === null) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.log(`Secret: ${webhook.secret}`);
|
|
68
|
+
console.log('Store the secret now to verify the signature of every delivery. It is never shown again.');
|
|
69
|
+
}
|
|
70
|
+
function promptFormat(options) {
|
|
71
|
+
return promptSelect('--format', 'Which format?', WEBHOOK_FORMATS.map(format => ({ label: format, value: format })), options);
|
|
72
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
|
+
import { printJson } from '../../utils/output.js';
|
|
5
|
+
import { confirmConsequence } from '../../utils/prompts.js';
|
|
6
|
+
import { fetchWebhook, webhookOptionShape, } from '../../utils/webhook-resolution.js';
|
|
7
|
+
export default defineCommand({
|
|
8
|
+
description: 'Delete a webhook and its delivery log.',
|
|
9
|
+
examples: [
|
|
10
|
+
'hotcodepush webhook delete --webhook releases',
|
|
11
|
+
'hotcodepush webhook delete --webhook team-chat --yes --json',
|
|
12
|
+
],
|
|
13
|
+
options: defineCommandOptions(webhookOptionShape),
|
|
14
|
+
action: async (options) => {
|
|
15
|
+
const hotCodePush = createApiClient();
|
|
16
|
+
const fetchedWebhook = await fetchWebhook(hotCodePush, options);
|
|
17
|
+
const isConfirmed = await confirmConsequence(`deletes webhook ${fetchedWebhook.name} and its delivery log: ${fetchedWebhook.url} receives no more events`, options);
|
|
18
|
+
if (!isConfirmed) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
await hotCodePush.organizations.webhooks.delete({
|
|
22
|
+
organizationId: fetchedWebhook.organizationId,
|
|
23
|
+
webhookId: fetchedWebhook.id,
|
|
24
|
+
});
|
|
25
|
+
if (options.json) {
|
|
26
|
+
printJson({ id: fetchedWebhook.id, name: fetchedWebhook.name });
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.log(`Deleted webhook ${fetchedWebhook.name} (${fetchedWebhook.id}).`);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
|
+
import { printDetails, printJson } from '../../utils/output.js';
|
|
5
|
+
import { fetchWebhook, webhookOptionShape, } from '../../utils/webhook-resolution.js';
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
description: 'Print a webhook: its URL, format, events, app filter and whether it is enabled. The secret is never printed.',
|
|
8
|
+
examples: [
|
|
9
|
+
'hotcodepush webhook get --webhook releases',
|
|
10
|
+
'hotcodepush webhook get --webhook 3c9e7a52-8d14-4b6f-a0e2-5f71c3d8b946 --json',
|
|
11
|
+
],
|
|
12
|
+
options: defineCommandOptions(webhookOptionShape),
|
|
13
|
+
action: async (options) => {
|
|
14
|
+
const fetchedWebhook = await fetchWebhook(createApiClient(), options);
|
|
15
|
+
if (options.json) {
|
|
16
|
+
printJson(fetchedWebhook);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
printWebhookDetails(fetchedWebhook);
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
function printWebhookDetails(webhook) {
|
|
23
|
+
printDetails([
|
|
24
|
+
['ID', webhook.id],
|
|
25
|
+
['Name', webhook.name],
|
|
26
|
+
['URL', webhook.url],
|
|
27
|
+
['Format', webhook.format],
|
|
28
|
+
['Events', webhook.events.join(', ')],
|
|
29
|
+
['App', webhook.appId ?? 'every app'],
|
|
30
|
+
['Enabled', webhook.isEnabled ? 'yes' : 'no'],
|
|
31
|
+
['Consecutive failures', String(webhook.consecutiveFailureCount)],
|
|
32
|
+
['Created', webhook.createdAt],
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
|
+
import { printJson, printTable, resolveDate } from '../../utils/output.js';
|
|
5
|
+
import { paginationShape, resolveNextOffset } from '../../utils/pagination.js';
|
|
6
|
+
import { fetchOrganizationId } from '../../utils/resource-resolution.js';
|
|
7
|
+
export default defineCommand({
|
|
8
|
+
description: "List an organization's webhooks, newest first.",
|
|
9
|
+
examples: [
|
|
10
|
+
'hotcodepush webhook list',
|
|
11
|
+
'hotcodepush webhook list --organization Acme --json',
|
|
12
|
+
],
|
|
13
|
+
options: defineCommandOptions(paginationShape),
|
|
14
|
+
action: async (options) => {
|
|
15
|
+
const hotCodePush = createApiClient();
|
|
16
|
+
const listedWebhooks = await hotCodePush.organizations.webhooks.list({
|
|
17
|
+
limit: options.limit,
|
|
18
|
+
offset: options.offset,
|
|
19
|
+
organizationId: await fetchOrganizationId(hotCodePush, options),
|
|
20
|
+
});
|
|
21
|
+
const nextOffset = resolveNextOffset(listedWebhooks.length, options);
|
|
22
|
+
if (options.json) {
|
|
23
|
+
printJson({ nextOffset, webhooks: listedWebhooks });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
printTable({
|
|
27
|
+
emptyText: 'No webhooks.',
|
|
28
|
+
headers: ['ID', 'NAME', 'FORMAT', 'URL', 'ENABLED', 'CREATED'],
|
|
29
|
+
nextOffset,
|
|
30
|
+
rows: listedWebhooks.map(({ createdAt, format, id, isEnabled, name, url }) => [
|
|
31
|
+
id,
|
|
32
|
+
name,
|
|
33
|
+
format,
|
|
34
|
+
url,
|
|
35
|
+
isEnabled ? 'yes' : 'no',
|
|
36
|
+
resolveDate(createdAt),
|
|
37
|
+
]),
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
2
|
+
import { defineCommand } from '../../utils/command.js';
|
|
3
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
4
|
+
import { printJson } from '../../utils/output.js';
|
|
5
|
+
import { confirmConsequence } from '../../utils/prompts.js';
|
|
6
|
+
import { fetchWebhook, webhookOptionShape, } from '../../utils/webhook-resolution.js';
|
|
7
|
+
import { printSettledDelivery } from '../webhook-delivery/redeliver.js';
|
|
8
|
+
export default defineCommand({
|
|
9
|
+
description: "Send one sample event, webhook.test, to a webhook's URL and print the receiver's answer.",
|
|
10
|
+
examples: [
|
|
11
|
+
'hotcodepush webhook test --webhook releases',
|
|
12
|
+
'hotcodepush webhook test --webhook team-chat --yes --json',
|
|
13
|
+
],
|
|
14
|
+
options: defineCommandOptions(webhookOptionShape),
|
|
15
|
+
action: async (options) => {
|
|
16
|
+
const hotCodePush = createApiClient();
|
|
17
|
+
const fetchedWebhook = await fetchWebhook(hotCodePush, options);
|
|
18
|
+
const isConfirmed = await confirmConsequence(`sends a sample event to ${fetchedWebhook.url}`, options);
|
|
19
|
+
if (!isConfirmed) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const settledDelivery = await hotCodePush.organizations.webhooks.test({
|
|
23
|
+
organizationId: fetchedWebhook.organizationId,
|
|
24
|
+
webhookId: fetchedWebhook.id,
|
|
25
|
+
});
|
|
26
|
+
if (options.json) {
|
|
27
|
+
printJson(settledDelivery);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
printSettledDelivery(settledDelivery, fetchedWebhook.name);
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { booleanFlagSchema } from '../../utils/boolean-flag.js';
|
|
4
|
+
import { defineCommand } from '../../utils/command.js';
|
|
5
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
6
|
+
import { resolveNullableField } from '../../utils/nullable-field.js';
|
|
7
|
+
import { printJson } from '../../utils/output.js';
|
|
8
|
+
import { fetchWebhook, fetchWebhookAppId, resolveWebhookEventTypes, webhookAppOptionShape, webhookEventOptionShape, webhookOptionShape, } from '../../utils/webhook-resolution.js';
|
|
9
|
+
export default defineCommand({
|
|
10
|
+
description: 'Rename a webhook or change its URL, events, app filter or whether it is enabled. The format and the secret never change.',
|
|
11
|
+
examples: [
|
|
12
|
+
'hotcodepush webhook update --webhook releases --event release.created --event release.revoked',
|
|
13
|
+
'hotcodepush webhook update --webhook team-chat --enabled --clear-app --json',
|
|
14
|
+
],
|
|
15
|
+
options: defineCommandOptions({
|
|
16
|
+
...webhookAppOptionShape,
|
|
17
|
+
...webhookEventOptionShape,
|
|
18
|
+
...webhookOptionShape,
|
|
19
|
+
clearApp: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Sets the app filter back to null: the webhook receives every app's events and the organization's."),
|
|
23
|
+
enabled: booleanFlagSchema
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Whether the webhook delivers. Turning it on again restarts the count of failures that disables it. Pass false to turn it off.'),
|
|
26
|
+
name: z.string().optional().describe("The webhook's new name."),
|
|
27
|
+
url: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('The https URL the events are posted to.'),
|
|
31
|
+
}),
|
|
32
|
+
action: async (options) => {
|
|
33
|
+
const app = resolveNullableField(options.app, options.clearApp, 'app');
|
|
34
|
+
const hotCodePush = createApiClient();
|
|
35
|
+
const fetchedWebhook = await fetchWebhook(hotCodePush, options);
|
|
36
|
+
const updatedWebhook = await hotCodePush.organizations.webhooks.update({
|
|
37
|
+
appId: typeof app === 'string'
|
|
38
|
+
? await fetchWebhookAppId(hotCodePush, fetchedWebhook.organizationId, app)
|
|
39
|
+
: app,
|
|
40
|
+
events: options.event === undefined
|
|
41
|
+
? undefined
|
|
42
|
+
: resolveWebhookEventTypes(options.event),
|
|
43
|
+
isEnabled: options.enabled,
|
|
44
|
+
name: options.name,
|
|
45
|
+
organizationId: fetchedWebhook.organizationId,
|
|
46
|
+
url: options.url,
|
|
47
|
+
webhookId: fetchedWebhook.id,
|
|
48
|
+
});
|
|
49
|
+
if (options.json) {
|
|
50
|
+
printJson(updatedWebhook);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
console.log(`Updated webhook ${updatedWebhook.name} (${updatedWebhook.id}).`);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
|
+
import { resolveTimeBound } from '../../utils/duration.js';
|
|
5
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
6
|
+
import { printJson, printTable } from '../../utils/output.js';
|
|
7
|
+
import { paginationShape, resolveNextOffset } from '../../utils/pagination.js';
|
|
8
|
+
import { fetchWebhook, webhookOptionShape, } from '../../utils/webhook-resolution.js';
|
|
9
|
+
import { resolveResponseText } from './redeliver.js';
|
|
10
|
+
export default defineCommand({
|
|
11
|
+
description: "List a webhook's deliveries, newest first, filtered by status and time, to find the ones worth redelivering. Each is kept for 30 days.",
|
|
12
|
+
examples: [
|
|
13
|
+
'hotcodepush webhook-delivery list --webhook releases --status failed --created-since 2h',
|
|
14
|
+
'hotcodepush webhook-delivery list --webhook releases --json',
|
|
15
|
+
],
|
|
16
|
+
options: defineCommandOptions({
|
|
17
|
+
...paginationShape,
|
|
18
|
+
...webhookOptionShape,
|
|
19
|
+
createdSince: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('The earliest delivery, inclusive: an ISO 8601 timestamp or a duration ago such as 2h or 7d.'),
|
|
23
|
+
createdUntil: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('The latest delivery, inclusive: an ISO 8601 timestamp or a duration ago such as 2h or 7d.'),
|
|
27
|
+
status: z
|
|
28
|
+
.enum(['failed', 'pending', 'succeeded'])
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('failed, pending while it is retried, or succeeded.'),
|
|
31
|
+
}),
|
|
32
|
+
action: async (options) => {
|
|
33
|
+
const hotCodePush = createApiClient();
|
|
34
|
+
const fetchedWebhook = await fetchWebhook(hotCodePush, options);
|
|
35
|
+
const listedDeliveries = await hotCodePush.organizations.webhooks.deliveries.list({
|
|
36
|
+
createdSince: resolveTimeBound(options.createdSince),
|
|
37
|
+
createdUntil: resolveTimeBound(options.createdUntil),
|
|
38
|
+
limit: options.limit,
|
|
39
|
+
offset: options.offset,
|
|
40
|
+
organizationId: fetchedWebhook.organizationId,
|
|
41
|
+
status: options.status,
|
|
42
|
+
webhookId: fetchedWebhook.id,
|
|
43
|
+
});
|
|
44
|
+
const nextOffset = resolveNextOffset(listedDeliveries.length, options);
|
|
45
|
+
if (options.json) {
|
|
46
|
+
printJson({ nextOffset, webhookDeliveries: listedDeliveries });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
printTable({
|
|
50
|
+
emptyText: 'No deliveries match.',
|
|
51
|
+
headers: ['ID', 'TIME', 'TYPE', 'STATUS', 'RESPONSE', 'ATTEMPTS'],
|
|
52
|
+
nextOffset,
|
|
53
|
+
rows: listedDeliveries.map(delivery => [
|
|
54
|
+
delivery.id,
|
|
55
|
+
delivery.createdAt,
|
|
56
|
+
delivery.type,
|
|
57
|
+
delivery.status,
|
|
58
|
+
resolveResponseText(delivery),
|
|
59
|
+
String(delivery.attemptCount),
|
|
60
|
+
]),
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createApiClient } from '../../utils/api-client.js';
|
|
3
|
+
import { defineCommand } from '../../utils/command.js';
|
|
4
|
+
import { defineCommandOptions } from '../../utils/global-options.js';
|
|
5
|
+
import { printJson } from '../../utils/output.js';
|
|
6
|
+
import { confirmConsequence, promptText } from '../../utils/prompts.js';
|
|
7
|
+
import { fetchWebhook, webhookOptionShape, } from '../../utils/webhook-resolution.js';
|
|
8
|
+
export default defineCommand({
|
|
9
|
+
description: "Deliver a webhook's event again, once, and print the receiver's answer. A pending delivery is taken from the retries.",
|
|
10
|
+
examples: [
|
|
11
|
+
'hotcodepush webhook-delivery redeliver --webhook releases --delivery 9a4f2e71-3b8c-4d65-b1e7-0c2d5f8a6e93',
|
|
12
|
+
'hotcodepush webhook-delivery redeliver --webhook releases --delivery 9a4f2e71-3b8c-4d65-b1e7-0c2d5f8a6e93 --yes --json',
|
|
13
|
+
],
|
|
14
|
+
options: defineCommandOptions({
|
|
15
|
+
...webhookOptionShape,
|
|
16
|
+
delivery: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('The delivery, by id, as "hotcodepush webhook-delivery list" prints it.'),
|
|
20
|
+
}),
|
|
21
|
+
action: async (options) => {
|
|
22
|
+
const hotCodePush = createApiClient();
|
|
23
|
+
const fetchedWebhook = await fetchWebhook(hotCodePush, options);
|
|
24
|
+
// A delivery has no name to pick from, so a missing one is asked for as text.
|
|
25
|
+
const deliveryId = options.delivery ??
|
|
26
|
+
(await promptText('--delivery', 'Which delivery id?', options));
|
|
27
|
+
const isConfirmed = await confirmConsequence(`sends the event of delivery ${deliveryId} to ${fetchedWebhook.url} again`, options);
|
|
28
|
+
if (!isConfirmed) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const settledDelivery = await hotCodePush.organizations.webhooks.deliveries.redeliver({
|
|
32
|
+
deliveryId,
|
|
33
|
+
organizationId: fetchedWebhook.organizationId,
|
|
34
|
+
webhookId: fetchedWebhook.id,
|
|
35
|
+
});
|
|
36
|
+
if (options.json) {
|
|
37
|
+
printJson(settledDelivery);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
printSettledDelivery(settledDelivery, fetchedWebhook.name);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
export function printSettledDelivery(delivery, webhookName) {
|
|
44
|
+
console.log(`Sent ${delivery.type} to webhook ${webhookName}: ${delivery.status}, ${resolveResponseText(delivery)}.`);
|
|
45
|
+
}
|
|
46
|
+
export function resolveResponseText({ responseCode }) {
|
|
47
|
+
return responseCode === null ? 'no response' : `HTTP ${responseCode}`;
|
|
48
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DEFAULT_API_URL } from '../config/consts.js';
|
|
2
|
+
import { defineCommand } from '../utils/command.js';
|
|
3
|
+
import { fetchCurrentUser, resolveCredentialText, } from '../utils/credential.js';
|
|
4
|
+
import { defineCommandOptions } from '../utils/global-options.js';
|
|
5
|
+
import { printJson } from '../utils/output.js';
|
|
6
|
+
import { isEnvironmentToken } from '../utils/token-store.js';
|
|
7
|
+
import { readApiUrl } from '../utils/user-config.js';
|
|
8
|
+
export default defineCommand({
|
|
9
|
+
description: 'Print the user you are logged in as, or the one HOTCODEPUSH_TOKEN stands for.',
|
|
10
|
+
examples: ['hotcodepush whoami', 'hotcodepush whoami --json'],
|
|
11
|
+
options: defineCommandOptions({}),
|
|
12
|
+
action: async (options) => {
|
|
13
|
+
const user = await fetchCurrentUser();
|
|
14
|
+
const apiUrl = readApiUrl();
|
|
15
|
+
if (options.json) {
|
|
16
|
+
printJson({ apiUrl, user });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log(resolveCredentialText(user, isEnvironmentToken()));
|
|
20
|
+
if (apiUrl !== DEFAULT_API_URL) {
|
|
21
|
+
console.log(`API: ${apiUrl}`);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
});
|