clever-tools 4.4.1 → 4.5.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/bin/clever.js +208 -2125
- package/package.json +33 -25
- package/src/commands/README.md +65 -0
- package/src/commands/accesslogs/accesslogs.command.js +158 -0
- package/src/commands/accesslogs/accesslogs.docs.md +20 -0
- package/src/commands/{activity.js → activity/activity.command.js} +74 -44
- package/src/commands/activity/activity.docs.md +19 -0
- package/src/commands/addon/addon.args.js +14 -0
- package/src/commands/addon/addon.command.js +7 -0
- package/src/commands/addon/addon.create.command.js +236 -0
- package/src/commands/addon/addon.delete.command.js +32 -0
- package/src/commands/addon/addon.docs.md +156 -0
- package/src/commands/addon/addon.env.command.js +50 -0
- package/src/commands/addon/addon.list.command.js +55 -0
- package/src/commands/addon/addon.providers.command.js +45 -0
- package/src/commands/addon/addon.providers.show.command.js +99 -0
- package/src/commands/addon/addon.rename.command.js +24 -0
- package/src/commands/applications/applications.command.js +59 -0
- package/src/commands/applications/applications.docs.md +31 -0
- package/src/commands/applications/applications.list.command.js +100 -0
- package/src/commands/cancel-deploy/cancel-deploy.command.js +30 -0
- package/src/commands/cancel-deploy/cancel-deploy.docs.md +16 -0
- package/src/commands/config/config.args.js +10 -0
- package/src/commands/config/config.command.js +20 -0
- package/src/commands/config/config.docs.md +86 -0
- package/src/commands/config/config.get.command.js +21 -0
- package/src/commands/config/config.set.command.js +38 -0
- package/src/commands/config/config.update.command.js +88 -0
- package/src/commands/console/console.command.js +31 -0
- package/src/commands/console/console.docs.md +16 -0
- package/src/commands/create/create.command.js +173 -0
- package/src/commands/create/create.docs.md +27 -0
- package/src/commands/{curl.js → curl/curl.command.js} +10 -3
- package/src/commands/curl/curl.docs.md +9 -0
- package/src/commands/database/database.args.js +8 -0
- package/src/commands/database/database.backups.command.js +60 -0
- package/src/commands/database/database.backups.download.command.js +55 -0
- package/src/commands/database/database.command.js +10 -0
- package/src/commands/database/database.docs.md +52 -0
- package/src/commands/delete/delete.command.js +43 -0
- package/src/commands/delete/delete.docs.md +17 -0
- package/src/commands/deploy/deploy.command.js +166 -0
- package/src/commands/deploy/deploy.docs.md +22 -0
- package/src/commands/diag/diag.command.js +136 -0
- package/src/commands/diag/diag.docs.md +15 -0
- package/src/commands/domain/domain.add.command.js +25 -0
- package/src/commands/domain/domain.args.js +8 -0
- package/src/commands/domain/domain.command.js +38 -0
- package/src/commands/domain/domain.diag.command.js +204 -0
- package/src/commands/domain/domain.docs.md +143 -0
- package/src/commands/domain/domain.favourite.command.js +35 -0
- package/src/commands/domain/domain.favourite.set.command.js +24 -0
- package/src/commands/domain/domain.favourite.unset.command.js +23 -0
- package/src/commands/domain/domain.overview.command.js +157 -0
- package/src/commands/domain/domain.rm.command.js +25 -0
- package/src/commands/drain/drain.args.js +8 -0
- package/src/commands/drain/drain.command.js +56 -0
- package/src/commands/drain/drain.create.command.js +128 -0
- package/src/commands/drain/drain.disable.command.js +27 -0
- package/src/commands/drain/drain.docs.md +129 -0
- package/src/commands/drain/drain.enable.command.js +27 -0
- package/src/commands/drain/drain.get.command.js +38 -0
- package/src/commands/drain/drain.remove.command.js +26 -0
- package/src/commands/emails/emails.add.command.js +32 -0
- package/src/commands/emails/emails.args.js +8 -0
- package/src/commands/emails/emails.command.js +35 -0
- package/src/commands/emails/emails.docs.md +79 -0
- package/src/commands/emails/emails.open.command.js +15 -0
- package/src/commands/emails/emails.primary.command.js +29 -0
- package/src/commands/emails/emails.remove-all.command.js +54 -0
- package/src/commands/emails/emails.remove.command.js +25 -0
- package/src/commands/env/env.command.js +77 -0
- package/src/commands/env/env.docs.md +99 -0
- package/src/commands/env/env.import-vars.command.js +45 -0
- package/src/commands/env/env.import.command.js +29 -0
- package/src/commands/env/env.rm.command.js +25 -0
- package/src/commands/env/env.set.command.js +32 -0
- package/src/commands/features/features.args.js +9 -0
- package/src/commands/features/features.command.js +7 -0
- package/src/commands/features/features.disable.command.js +25 -0
- package/src/commands/features/features.docs.md +71 -0
- package/src/commands/features/features.enable.command.js +32 -0
- package/src/commands/features/features.info.command.js +27 -0
- package/src/commands/features/features.list.command.js +49 -0
- package/src/commands/global.args.js +45 -0
- package/src/commands/global.commands.js +461 -0
- package/src/commands/global.options.js +186 -0
- package/src/commands/help/help.command.js +9 -0
- package/src/commands/help/help.docs.md +9 -0
- package/src/commands/k8s/k8s.add-persistent-storage.command.js +39 -0
- package/src/commands/k8s/k8s.args.js +9 -0
- package/src/commands/k8s/k8s.command.js +12 -0
- package/src/commands/k8s/k8s.create.command.js +86 -0
- package/src/commands/k8s/k8s.delete.command.js +40 -0
- package/src/commands/k8s/k8s.docs.md +131 -0
- package/src/commands/k8s/k8s.get-kubeconfig.command.js +32 -0
- package/src/commands/k8s/k8s.get.command.js +43 -0
- package/src/commands/k8s/k8s.list.command.js +38 -0
- package/src/commands/keycloak/keycloak.command.js +17 -0
- package/src/commands/keycloak/keycloak.disable-ng.command.js +13 -0
- package/src/commands/keycloak/keycloak.docs.md +197 -0
- package/src/commands/keycloak/keycloak.enable-ng.command.js +13 -0
- package/src/commands/keycloak/keycloak.get.command.js +17 -0
- package/src/commands/keycloak/keycloak.open.command.js +13 -0
- package/src/commands/keycloak/keycloak.open.logs.command.js +13 -0
- package/src/commands/keycloak/keycloak.open.webui.command.js +13 -0
- package/src/commands/keycloak/keycloak.rebuild.command.js +13 -0
- package/src/commands/keycloak/keycloak.restart.command.js +13 -0
- package/src/commands/keycloak/keycloak.version.check.command.js +17 -0
- package/src/commands/keycloak/keycloak.version.command.js +17 -0
- package/src/commands/keycloak/keycloak.version.update.command.js +17 -0
- package/src/commands/kv/kv.command.js +99 -0
- package/src/commands/kv/kv.docs.md +27 -0
- package/src/commands/link/link.command.js +31 -0
- package/src/commands/link/link.docs.md +22 -0
- package/src/commands/{login.js → login/login.command.js} +44 -22
- package/src/commands/login/login.docs.md +16 -0
- package/src/commands/logout/logout.command.js +15 -0
- package/src/commands/logout/logout.docs.md +9 -0
- package/src/commands/logs/logs.command.js +81 -0
- package/src/commands/logs/logs.docs.md +22 -0
- package/src/commands/make-default/make-default.command.js +17 -0
- package/src/commands/make-default/make-default.docs.md +15 -0
- package/src/commands/matomo/matomo.command.js +17 -0
- package/src/commands/matomo/matomo.docs.md +109 -0
- package/src/commands/matomo/matomo.get.command.js +17 -0
- package/src/commands/matomo/matomo.open.command.js +13 -0
- package/src/commands/matomo/matomo.open.logs.command.js +13 -0
- package/src/commands/matomo/matomo.open.webui.command.js +13 -0
- package/src/commands/matomo/matomo.rebuild.command.js +13 -0
- package/src/commands/matomo/matomo.restart.command.js +13 -0
- package/src/commands/metabase/metabase.command.js +17 -0
- package/src/commands/metabase/metabase.docs.md +169 -0
- package/src/commands/metabase/metabase.get.command.js +17 -0
- package/src/commands/metabase/metabase.open.command.js +13 -0
- package/src/commands/metabase/metabase.open.logs.command.js +13 -0
- package/src/commands/metabase/metabase.open.webui.command.js +13 -0
- package/src/commands/metabase/metabase.rebuild.command.js +13 -0
- package/src/commands/metabase/metabase.restart.command.js +13 -0
- package/src/commands/metabase/metabase.version.check.command.js +17 -0
- package/src/commands/metabase/metabase.version.command.js +17 -0
- package/src/commands/metabase/metabase.version.update.command.js +17 -0
- package/src/commands/ng/ng.args.js +27 -0
- package/src/commands/ng/ng.command.js +45 -0
- package/src/commands/ng/ng.create.command.js +60 -0
- package/src/commands/ng/ng.create.external.command.js +44 -0
- package/src/commands/ng/ng.delete.command.js +22 -0
- package/src/commands/ng/ng.delete.external.command.js +25 -0
- package/src/commands/ng/ng.docs.md +214 -0
- package/src/commands/ng/ng.get-config.command.js +32 -0
- package/src/commands/ng/ng.get.command.js +22 -0
- package/src/commands/ng/ng.link.command.js +25 -0
- package/src/commands/ng/ng.options.js +9 -0
- package/src/commands/ng/ng.search.command.js +22 -0
- package/src/commands/ng/ng.unlink.command.js +25 -0
- package/src/commands/notify-email/notify-email.add.command.js +65 -0
- package/src/commands/notify-email/notify-email.command.js +61 -0
- package/src/commands/notify-email/notify-email.docs.md +60 -0
- package/src/commands/notify-email/notify-email.remove.command.js +24 -0
- package/src/commands/open/open.command.js +24 -0
- package/src/commands/open/open.docs.md +16 -0
- package/src/commands/otoroshi/otoroshi.command.js +17 -0
- package/src/commands/otoroshi/otoroshi.disable-ng.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.docs.md +211 -0
- package/src/commands/otoroshi/otoroshi.enable-ng.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.get-config.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.get.command.js +17 -0
- package/src/commands/otoroshi/otoroshi.open.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.open.logs.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.open.webui.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.rebuild.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.restart.command.js +13 -0
- package/src/commands/otoroshi/otoroshi.version.check.command.js +17 -0
- package/src/commands/otoroshi/otoroshi.version.command.js +17 -0
- package/src/commands/otoroshi/otoroshi.version.update.command.js +17 -0
- package/src/commands/profile/profile.command.js +60 -0
- package/src/commands/profile/profile.docs.md +23 -0
- package/src/commands/profile/profile.open.command.js +12 -0
- package/src/commands/published-config/published-config.command.js +40 -0
- package/src/commands/published-config/published-config.docs.md +77 -0
- package/src/commands/published-config/published-config.import.command.js +29 -0
- package/src/commands/published-config/published-config.rm.command.js +27 -0
- package/src/commands/published-config/published-config.set.command.js +34 -0
- package/src/commands/restart/restart.command.js +77 -0
- package/src/commands/restart/restart.docs.md +21 -0
- package/src/commands/scale/scale.command.js +121 -0
- package/src/commands/scale/scale.docs.md +23 -0
- package/src/commands/service/service.command.js +91 -0
- package/src/commands/service/service.docs.md +104 -0
- package/src/commands/service/service.link-addon.command.js +24 -0
- package/src/commands/service/service.link-app.command.js +23 -0
- package/src/commands/service/service.unlink-addon.command.js +24 -0
- package/src/commands/service/service.unlink-app.command.js +23 -0
- package/src/commands/ssh/ssh.command.js +40 -0
- package/src/commands/ssh/ssh.docs.md +17 -0
- package/src/commands/ssh-keys/ssh-keys.add.command.js +41 -0
- package/src/commands/ssh-keys/ssh-keys.args.js +8 -0
- package/src/commands/ssh-keys/ssh-keys.command.js +50 -0
- package/src/commands/ssh-keys/ssh-keys.docs.md +66 -0
- package/src/commands/ssh-keys/ssh-keys.open.command.js +12 -0
- package/src/commands/ssh-keys/ssh-keys.remove-all.command.js +54 -0
- package/src/commands/ssh-keys/ssh-keys.remove.command.js +26 -0
- package/src/commands/status/status.command.js +122 -0
- package/src/commands/status/status.docs.md +17 -0
- package/src/commands/stop/stop.command.js +23 -0
- package/src/commands/stop/stop.docs.md +16 -0
- package/src/commands/tcp-redirs/tcp-redirs.add.command.js +24 -0
- package/src/commands/tcp-redirs/tcp-redirs.command.js +41 -0
- package/src/commands/tcp-redirs/tcp-redirs.docs.md +71 -0
- package/src/commands/tcp-redirs/tcp-redirs.list-namespaces.command.js +48 -0
- package/src/commands/tcp-redirs/tcp-redirs.options.js +11 -0
- package/src/commands/tcp-redirs/tcp-redirs.remove.command.js +34 -0
- package/src/commands/tokens/tokens.command.js +43 -0
- package/src/commands/tokens/tokens.create.command.js +108 -0
- package/src/commands/tokens/tokens.docs.md +50 -0
- package/src/commands/tokens/tokens.revoke.command.js +25 -0
- package/src/commands/unlink/unlink.command.js +21 -0
- package/src/commands/unlink/unlink.docs.md +15 -0
- package/src/commands/version/version.command.js +13 -0
- package/src/commands/version/version.docs.md +9 -0
- package/src/commands/webhooks/webhooks.add.command.js +51 -0
- package/src/commands/webhooks/webhooks.command.js +57 -0
- package/src/commands/webhooks/webhooks.docs.md +61 -0
- package/src/commands/webhooks/webhooks.remove.command.js +24 -0
- package/src/lib/cliparse-patched.js +192 -0
- package/src/lib/define-argument.js +7 -0
- package/src/lib/define-argument.types.d.ts +23 -0
- package/src/lib/define-command.js +7 -0
- package/src/lib/define-command.types.d.ts +85 -0
- package/src/lib/define-common.types.d.ts +18 -0
- package/src/lib/define-option.js +7 -0
- package/src/lib/define-option.types.d.ts +29 -0
- package/src/lib/get-command-info.js +86 -0
- package/src/lib/get-command-info.types.d.ts +42 -0
- package/src/lib/zod-utils.js +66 -0
- package/src/models/addon.js +2 -3
- package/src/models/application.js +4 -5
- package/src/models/application_configuration.js +5 -23
- package/src/models/domain.js +34 -2
- package/src/models/exit-strategy-option.js +0 -9
- package/src/models/git.js +1 -4
- package/src/models/log-v4.js +5 -0
- package/src/models/log.js +5 -0
- package/src/models/namespaces.js +1 -2
- package/src/models/notification.js +1 -7
- package/src/parsers.js +33 -92
- package/src/command-options.js +0 -55
- package/src/command-promise-handler.js +0 -16
- package/src/commands/accesslogs.js +0 -138
- package/src/commands/addon.js +0 -391
- package/src/commands/applications.js +0 -123
- package/src/commands/cancel-deploy.js +0 -19
- package/src/commands/config.js +0 -47
- package/src/commands/console.js +0 -20
- package/src/commands/create.js +0 -129
- package/src/commands/database.js +0 -73
- package/src/commands/delete.js +0 -24
- package/src/commands/deploy.js +0 -133
- package/src/commands/diag.js +0 -126
- package/src/commands/domain.js +0 -445
- package/src/commands/drain.js +0 -164
- package/src/commands/emails.js +0 -156
- package/src/commands/env.js +0 -124
- package/src/commands/features.js +0 -87
- package/src/commands/k8s.js +0 -193
- package/src/commands/keycloak.js +0 -138
- package/src/commands/kv.js +0 -93
- package/src/commands/link.js +0 -20
- package/src/commands/logout.js +0 -8
- package/src/commands/logs.js +0 -45
- package/src/commands/makeDefault.js +0 -11
- package/src/commands/matomo.js +0 -85
- package/src/commands/metabase.js +0 -112
- package/src/commands/ng.js +0 -202
- package/src/commands/notify-email.js +0 -99
- package/src/commands/open.js +0 -13
- package/src/commands/otoroshi.js +0 -149
- package/src/commands/profile.js +0 -55
- package/src/commands/published-config.js +0 -70
- package/src/commands/restart.js +0 -52
- package/src/commands/scale.js +0 -66
- package/src/commands/service.js +0 -105
- package/src/commands/ssh-keys.js +0 -144
- package/src/commands/ssh.js +0 -20
- package/src/commands/status.js +0 -115
- package/src/commands/stop.js +0 -12
- package/src/commands/tcp-redirs.js +0 -80
- package/src/commands/tokens.js +0 -144
- package/src/commands/unlink.js +0 -14
- package/src/commands/version.js +0 -6
- package/src/commands/webhooks.js +0 -74
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
} from '@clevercloud/client/esm/api/v2/application.js';
|
|
12
12
|
import { getAvailableInstances } from '@clevercloud/client/esm/api/v2/product.js';
|
|
13
13
|
import { getSummary } from '@clevercloud/client/esm/api/v2/user.js';
|
|
14
|
-
import cliparse from 'cliparse';
|
|
15
14
|
import _ from 'lodash';
|
|
16
15
|
import { confirmAnswer } from '../lib/prompts.js';
|
|
17
16
|
import { styleText } from '../lib/style-text.js';
|
|
@@ -23,7 +22,7 @@ import { sendToApi } from './send-to-api.js';
|
|
|
23
22
|
import * as User from './user.js';
|
|
24
23
|
|
|
25
24
|
export function listAvailableTypes() {
|
|
26
|
-
return
|
|
25
|
+
return [
|
|
27
26
|
'docker',
|
|
28
27
|
'elixir',
|
|
29
28
|
'frankenphp',
|
|
@@ -46,17 +45,17 @@ export function listAvailableTypes() {
|
|
|
46
45
|
'static-apache',
|
|
47
46
|
'v',
|
|
48
47
|
'war',
|
|
49
|
-
]
|
|
48
|
+
];
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
export const AVAILABLE_ZONES = ['par', 'parhds', 'grahds', 'rbx', 'rbxhds', 'scw', 'ldn', 'mtl', 'sgp', 'syd', 'wsw'];
|
|
53
52
|
|
|
54
53
|
export function listAvailableZones() {
|
|
55
|
-
return
|
|
54
|
+
return AVAILABLE_ZONES;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
export function listAvailableAliases() {
|
|
59
|
-
return AppConfiguration.loadApplicationConf().then(({ apps }) =>
|
|
58
|
+
return AppConfiguration.loadApplicationConf().then(({ apps }) => _.map(apps, 'alias'));
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export function listAvailableFlavors() {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import cliparse from 'cliparse';
|
|
2
1
|
import dedent from 'dedent';
|
|
3
2
|
import { Logger } from '../logger.js';
|
|
4
3
|
|
|
@@ -80,29 +79,12 @@ export function parse(config, value) {
|
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
export function getUpdateOptions() {
|
|
84
|
-
return CONFIG_KEYS.map((config) => getConfigOptions(config)).reduce((a, b) => [...a, ...b], []);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function getConfigOptions(config) {
|
|
88
|
-
switch (config.kind) {
|
|
89
|
-
case 'bool':
|
|
90
|
-
case 'inverted-bool':
|
|
91
|
-
case 'force-https':
|
|
92
|
-
case 'task': {
|
|
93
|
-
return [
|
|
94
|
-
cliparse.flag(`enable-${config.id}`, { description: `Enable ${config.id}` }),
|
|
95
|
-
cliparse.flag(`disable-${config.id}`, { description: `Disable ${config.id}` }),
|
|
96
|
-
];
|
|
97
|
-
}
|
|
98
|
-
default: {
|
|
99
|
-
return [cliparse.option(`${config.id}`, { description: `Set ${config.id}` })];
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
82
|
export function parseOptions(options) {
|
|
105
|
-
const newOptions = CONFIG_KEYS.map((config) =>
|
|
83
|
+
const newOptions = CONFIG_KEYS.map((config) => {
|
|
84
|
+
return parseConfigOption(config, options);
|
|
85
|
+
}).filter((a) => {
|
|
86
|
+
return a != null && a[1] != null;
|
|
87
|
+
});
|
|
106
88
|
return Object.fromEntries(newOptions);
|
|
107
89
|
}
|
|
108
90
|
|
package/src/models/domain.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
getAllDomains,
|
|
3
|
+
getFavouriteDomain as getFavouriteDomainWithError,
|
|
4
|
+
} from '@clevercloud/client/esm/api/v2/application.js';
|
|
2
5
|
import _ from 'lodash';
|
|
6
|
+
import { parse as parseDomain } from 'tldts';
|
|
3
7
|
import { Logger } from '../logger.js';
|
|
4
8
|
import { sendToApi } from './send-to-api.js';
|
|
5
9
|
|
|
6
10
|
export async function getBest(appId, orgaId) {
|
|
7
11
|
Logger.debug('Trying to get the favourite vhost for ' + appId);
|
|
8
|
-
return
|
|
12
|
+
return getFavouriteDomainWithError({ id: orgaId, appId })
|
|
9
13
|
.then(sendToApi)
|
|
10
14
|
.catch(async (e) => {
|
|
11
15
|
if (e.response.status !== 404) {
|
|
@@ -35,3 +39,31 @@ export function selectBest(vhosts) {
|
|
|
35
39
|
});
|
|
36
40
|
return customVhost || withoutDefaultDomain || vhosts[0];
|
|
37
41
|
}
|
|
42
|
+
|
|
43
|
+
export function getFavouriteDomain({ ownerId, appId }) {
|
|
44
|
+
return getFavouriteDomainWithError({ id: ownerId, appId })
|
|
45
|
+
.then(sendToApi)
|
|
46
|
+
.then(({ fqdn }) => fqdn)
|
|
47
|
+
.catch((error) => {
|
|
48
|
+
if (error.id === 4021) {
|
|
49
|
+
// No favourite vhost
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getDomainObject(domainWithPathPrefix, favouriteDomain) {
|
|
57
|
+
const parsed = parseDomain(domainWithPathPrefix, { validateHostname: false });
|
|
58
|
+
return {
|
|
59
|
+
domainWithPathPrefix,
|
|
60
|
+
domain: parsed.domain,
|
|
61
|
+
domainWithoutSuffix: parsed.domainWithoutSuffix,
|
|
62
|
+
hostname: parsed.hostname,
|
|
63
|
+
publicSuffix: parsed.publicSuffix,
|
|
64
|
+
subdomain: parsed.subdomain,
|
|
65
|
+
isApex: parsed.subdomain === '',
|
|
66
|
+
pathPrefix: new URL('https://' + domainWithPathPrefix).pathname,
|
|
67
|
+
isFavourite: domainWithPathPrefix === favouriteDomain,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
import { styleText } from '../lib/style-text.js';
|
|
2
|
-
import { Logger } from '../logger.js';
|
|
3
|
-
|
|
4
1
|
export function get(follow, exitOnDeploy) {
|
|
5
2
|
if (follow) {
|
|
6
3
|
if (exitOnDeploy === 'deploy-start') {
|
|
7
4
|
throw new Error('The `follow` and `exit-on` set to "deploy-start" options are not compatible');
|
|
8
5
|
}
|
|
9
|
-
Logger.println(
|
|
10
|
-
styleText(
|
|
11
|
-
'yellow',
|
|
12
|
-
'The `follow` option is deprecated and will be removed in an upcoming major, use --exit-on set to "never" instead',
|
|
13
|
-
),
|
|
14
|
-
);
|
|
15
6
|
return 'never';
|
|
16
7
|
}
|
|
17
8
|
return exitOnDeploy;
|
package/src/models/git.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import cliparse from 'cliparse';
|
|
2
1
|
import * as git from 'isomorphic-git';
|
|
3
2
|
import _ from 'lodash';
|
|
4
3
|
import fs from 'node:fs';
|
|
@@ -111,9 +110,7 @@ export async function push(remoteUrl, branchRefspec, force) {
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
export function completeBranches() {
|
|
114
|
-
return getRepo()
|
|
115
|
-
.then((repo) => git.listBranches(repo))
|
|
116
|
-
.then(cliparse.autocomplete.words);
|
|
113
|
+
return getRepo().then((repo) => git.listBranches(repo));
|
|
117
114
|
}
|
|
118
115
|
|
|
119
116
|
export async function isShallow() {
|
package/src/models/log-v4.js
CHANGED
|
@@ -133,6 +133,11 @@ export async function watchDeploymentAndDisplayLogs(options) {
|
|
|
133
133
|
logsStream.close(quiet ? 'quiet' : 'follow');
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
// deploymentEnded can be undefined if deferred resolved (e.g., stream closed via SIGINT)
|
|
137
|
+
if (deploymentEnded == null) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
136
141
|
if (deploymentEnded.state === 'OK') {
|
|
137
142
|
Logger.println('');
|
|
138
143
|
|
package/src/models/log.js
CHANGED
|
@@ -133,6 +133,11 @@ export async function watchDeploymentAndDisplayLogs({
|
|
|
133
133
|
logsStream.close();
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
// deploymentEnded can be undefined if deferred resolved (e.g., stream closed via SIGINT)
|
|
137
|
+
if (deploymentEnded == null) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
136
141
|
if (deploymentEnded.state === 'OK') {
|
|
137
142
|
Logger.println(styleText(['bold', 'green'], 'Deployment successful'));
|
|
138
143
|
} else if (deploymentEnded.state === 'CANCELLED') {
|
package/src/models/namespaces.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getNamespaces as getTcpRedirNamespaces } from '@clevercloud/client/esm/api/v2/organisation.js';
|
|
2
|
-
import cliparse from 'cliparse';
|
|
3
2
|
import * as Application from './application.js';
|
|
4
3
|
import { sendToApi } from './send-to-api.js';
|
|
5
4
|
|
|
@@ -11,5 +10,5 @@ export async function completeNamespaces() {
|
|
|
11
10
|
// Sadly we do not have access to current params in complete as of now
|
|
12
11
|
const { ownerId } = await Application.resolveId(null, null);
|
|
13
12
|
|
|
14
|
-
return getNamespaces(ownerId)
|
|
13
|
+
return getNamespaces(ownerId);
|
|
15
14
|
}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import cliparse from 'cliparse';
|
|
2
1
|
import * as AppConfig from './app_configuration.js';
|
|
3
2
|
import * as Organisation from './organisation.js';
|
|
4
3
|
import * as User from './user.js';
|
|
5
4
|
|
|
6
5
|
export function listMetaEvents() {
|
|
7
|
-
return
|
|
8
|
-
'META_SERVICE_LIFECYCLE',
|
|
9
|
-
'META_DEPLOYMENT_RESULT',
|
|
10
|
-
'META_SERVICE_MANAGEMENT',
|
|
11
|
-
'META_CREDITS',
|
|
12
|
-
]);
|
|
6
|
+
return ['META_SERVICE_LIFECYCLE', 'META_DEPLOYMENT_RESULT', 'META_SERVICE_MANAGEMENT', 'META_CREDITS'];
|
|
13
7
|
}
|
|
14
8
|
|
|
15
9
|
export function getOrgaIdOrUserId(orgIdOrName) {
|
package/src/parsers.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import cliparse from 'cliparse';
|
|
2
1
|
import ISO8601 from 'iso8601-duration';
|
|
3
2
|
import * as Application from './models/application.js';
|
|
4
3
|
import { NG_MEMBER_PREFIXES } from './models/ng.js';
|
|
@@ -9,92 +8,63 @@ export function addonOptions(options) {
|
|
|
9
8
|
const optionsArray = typeof options === 'string' ? [options] : options;
|
|
10
9
|
for (const option of optionsArray) {
|
|
11
10
|
if (!option.match(addonOptionsRegex)) {
|
|
12
|
-
|
|
11
|
+
throw new Error('Invalid option: ' + option);
|
|
13
12
|
}
|
|
14
13
|
}
|
|
15
|
-
return
|
|
14
|
+
return optionsArray.join(',');
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
export function flavor(flavor) {
|
|
19
18
|
const flavors = Application.listAvailableFlavors();
|
|
20
19
|
if (flavors.includes(flavor)) {
|
|
21
|
-
return
|
|
20
|
+
return flavor;
|
|
22
21
|
}
|
|
23
|
-
|
|
22
|
+
throw new Error('Invalid value: ' + flavor);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
export function buildFlavor(flavorOrDisabled) {
|
|
27
26
|
if (flavorOrDisabled === 'disabled') {
|
|
28
|
-
return
|
|
27
|
+
return flavorOrDisabled;
|
|
29
28
|
}
|
|
30
29
|
return flavor(flavorOrDisabled);
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
export function instances(instances) {
|
|
34
|
-
const parsedInstances = parseInt(instances, 10);
|
|
35
|
-
if (isNaN(parsedInstances)) {
|
|
36
|
-
return cliparse.parsers.error('Invalid number: ' + instances);
|
|
37
|
-
}
|
|
38
|
-
if (parsedInstances < 1 || parsedInstances > 20) {
|
|
39
|
-
return cliparse.parsers.error('The number of instances must be between 1 and 20');
|
|
40
|
-
}
|
|
41
|
-
return cliparse.parsers.success(parsedInstances);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
32
|
export function date(dateString) {
|
|
45
33
|
const date = new Date(dateString);
|
|
46
34
|
if (isNaN(dateString) && !isNaN(date.getTime())) {
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const duration = durationInSeconds(dateString);
|
|
51
|
-
if (duration.success) {
|
|
52
|
-
return cliparse.parsers.success(new Date(Date.now() - duration.success * 1000));
|
|
35
|
+
return date;
|
|
53
36
|
}
|
|
54
37
|
|
|
55
|
-
|
|
38
|
+
const seconds = durationInSeconds(dateString);
|
|
39
|
+
return new Date(Date.now() - seconds * 1000);
|
|
56
40
|
}
|
|
57
41
|
|
|
58
42
|
export function futureDateOrDuration(dateString) {
|
|
59
43
|
const date = new Date(dateString);
|
|
60
44
|
if (isNaN(dateString) && !isNaN(date.getTime())) {
|
|
61
|
-
return
|
|
45
|
+
return date;
|
|
62
46
|
}
|
|
63
47
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return cliparse.parsers.success(new Date(Date.now() + duration.success * 1000));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return duration;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// This simple regex is enough for our use cases
|
|
73
|
-
const emailRegex = /^\S+@\S+\.\S+$/g;
|
|
74
|
-
|
|
75
|
-
export function email(string) {
|
|
76
|
-
if (string.match(emailRegex)) {
|
|
77
|
-
return cliparse.parsers.success(string);
|
|
78
|
-
}
|
|
79
|
-
return cliparse.parsers.error('Invalid email');
|
|
48
|
+
const seconds = durationInSeconds(dateString);
|
|
49
|
+
return new Date(Date.now() + seconds * 1000);
|
|
80
50
|
}
|
|
81
51
|
|
|
82
52
|
const appIdRegex = /^app_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
83
53
|
|
|
84
54
|
export function appIdOrName(string) {
|
|
85
55
|
if (string.match(appIdRegex)) {
|
|
86
|
-
return
|
|
56
|
+
return { app_id: string };
|
|
87
57
|
}
|
|
88
|
-
return
|
|
58
|
+
return { app_name: string };
|
|
89
59
|
}
|
|
90
60
|
|
|
91
61
|
const orgaIdRegex = /^(user_|orga_)[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
92
62
|
|
|
93
63
|
export function orgaIdOrName(string) {
|
|
94
64
|
if (string.match(orgaIdRegex)) {
|
|
95
|
-
return
|
|
65
|
+
return { orga_id: string };
|
|
96
66
|
}
|
|
97
|
-
return
|
|
67
|
+
return { orga_name: string };
|
|
98
68
|
}
|
|
99
69
|
|
|
100
70
|
const addonIdRegex = /^addon_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -104,31 +74,16 @@ const ulidRegex = /^(kubernetes)_[0-9A-HJ-NP-TV-Z]{26}$/i;
|
|
|
104
74
|
|
|
105
75
|
export function addonIdOrName(string) {
|
|
106
76
|
if (string.match(addonIdRegex)) {
|
|
107
|
-
return
|
|
77
|
+
return { addon_id: string };
|
|
108
78
|
}
|
|
109
79
|
if (string.match(operatorIdRegex) || string.match(ulidRegex)) {
|
|
110
|
-
return
|
|
80
|
+
return { operator_id: string };
|
|
111
81
|
}
|
|
112
|
-
return
|
|
82
|
+
return { addon_name: string };
|
|
113
83
|
}
|
|
114
84
|
|
|
115
85
|
export function commaSeparated(string) {
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function integer(string) {
|
|
120
|
-
const integer = parseInt(string);
|
|
121
|
-
if (isNaN(integer)) {
|
|
122
|
-
return cliparse.parsers.error('Invalid number: ' + string);
|
|
123
|
-
}
|
|
124
|
-
return cliparse.parsers.success(integer);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function nonEmptyString(string) {
|
|
128
|
-
if (typeof string !== 'string' || string === '') {
|
|
129
|
-
return cliparse.parsers.error('Invalid string, it should not be empty');
|
|
130
|
-
}
|
|
131
|
-
return cliparse.parsers.success(string);
|
|
86
|
+
return string.split(',');
|
|
132
87
|
}
|
|
133
88
|
|
|
134
89
|
// /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/i;
|
|
@@ -136,22 +91,20 @@ const tagRegex = /^[^,\s]+$/;
|
|
|
136
91
|
|
|
137
92
|
export function tag(string) {
|
|
138
93
|
if (string.match(tagRegex)) {
|
|
139
|
-
return
|
|
94
|
+
return string;
|
|
140
95
|
}
|
|
141
|
-
|
|
96
|
+
throw new Error(`Invalid tag '${string}'. Should match ${tagRegex}`);
|
|
142
97
|
}
|
|
143
98
|
|
|
144
99
|
export function tags(string) {
|
|
145
100
|
if (String(string).length === 0) {
|
|
146
|
-
return
|
|
101
|
+
return [];
|
|
147
102
|
}
|
|
148
103
|
const tags = String(string).split(',');
|
|
149
104
|
for (const current of tags) {
|
|
150
|
-
|
|
151
|
-
return cliparse.parsers.error(`Invalid tag '${current}'. Should match \`${tagRegex}\``);
|
|
152
|
-
}
|
|
105
|
+
tag(current); // will throw if invalid
|
|
153
106
|
}
|
|
154
|
-
return
|
|
107
|
+
return tags;
|
|
155
108
|
}
|
|
156
109
|
|
|
157
110
|
/**
|
|
@@ -161,29 +114,25 @@ export function tags(string) {
|
|
|
161
114
|
* @returns {number} number of seconds
|
|
162
115
|
*/
|
|
163
116
|
export function durationInSeconds(durationStr = '') {
|
|
164
|
-
const
|
|
165
|
-
`Invalid duration: "${durationStr}", expect (IS0 8601 duration / a "1h, 1m, 30s" like duration / a positive number in seconds)`,
|
|
166
|
-
);
|
|
117
|
+
const errorMessage = `Invalid duration: "${durationStr}", expect (IS0 8601 duration / a "1h, 1m, 30s" like duration / a positive number in seconds)`;
|
|
167
118
|
|
|
168
119
|
if (durationStr.startsWith('P')) {
|
|
169
120
|
try {
|
|
170
121
|
const d = ISO8601.parse(durationStr);
|
|
171
|
-
return
|
|
122
|
+
return ISO8601.toSeconds(d);
|
|
172
123
|
} catch {
|
|
173
|
-
|
|
124
|
+
throw new Error(errorMessage);
|
|
174
125
|
}
|
|
175
126
|
}
|
|
176
127
|
|
|
177
128
|
try {
|
|
178
|
-
|
|
179
|
-
return cliparse.parsers.success(durationInSeconds);
|
|
129
|
+
return parseSimpleDuration(durationStr);
|
|
180
130
|
} catch {
|
|
181
131
|
const n = Number.parseInt(durationStr);
|
|
182
132
|
if (isNaN(n) || n < 0) {
|
|
183
|
-
|
|
133
|
+
throw new Error(errorMessage);
|
|
184
134
|
}
|
|
185
|
-
|
|
186
|
-
return cliparse.parsers.success(n);
|
|
135
|
+
return n;
|
|
187
136
|
}
|
|
188
137
|
}
|
|
189
138
|
|
|
@@ -211,18 +160,10 @@ function parseSimpleDuration(durationStr) {
|
|
|
211
160
|
// Network Groups parsers
|
|
212
161
|
export function ngResourceType(string) {
|
|
213
162
|
if (string.startsWith('ng_')) {
|
|
214
|
-
return
|
|
163
|
+
return { ngId: string };
|
|
215
164
|
}
|
|
216
165
|
if (Object.keys(NG_MEMBER_PREFIXES).some((prefix) => string.startsWith(prefix))) {
|
|
217
|
-
return
|
|
218
|
-
}
|
|
219
|
-
return cliparse.parsers.success({ ngResourceLabel: string });
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export function ngValidType(string) {
|
|
223
|
-
if (string === 'NetworkGroup' || string === 'Member' || string === 'CleverPeer' || string === 'ExternalPeer') {
|
|
224
|
-
return cliparse.parsers.success(string);
|
|
225
|
-
} else {
|
|
226
|
-
return cliparse.parsers.error(`Invalid Network Group resource type: ${string}`);
|
|
166
|
+
return { memberId: string };
|
|
227
167
|
}
|
|
168
|
+
return { ngResourceLabel: string };
|
|
228
169
|
}
|
package/src/command-options.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import cliparse from 'cliparse';
|
|
2
|
-
|
|
3
|
-
export function getOutputFormatOption(formats = []) {
|
|
4
|
-
const availableFormats = ['human', 'json', ...formats];
|
|
5
|
-
return cliparse.option('format', {
|
|
6
|
-
aliases: ['F'],
|
|
7
|
-
metavar: 'format',
|
|
8
|
-
parser: (format) => {
|
|
9
|
-
return availableFormats.includes(format)
|
|
10
|
-
? cliparse.parsers.success(format)
|
|
11
|
-
: cliparse.parsers.error('The output format must be one of ' + availableFormats.join(', '));
|
|
12
|
-
},
|
|
13
|
-
default: 'human',
|
|
14
|
-
description: `Output format (${availableFormats.join(', ')})`,
|
|
15
|
-
complete() {
|
|
16
|
-
return cliparse.autocomplete.words(availableFormats);
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function getSameCommitPolicyOption() {
|
|
22
|
-
const availablePolicies = ['error', 'ignore', 'restart', 'rebuild'];
|
|
23
|
-
return cliparse.option('same-commit-policy', {
|
|
24
|
-
aliases: ['p'],
|
|
25
|
-
metavar: 'policy',
|
|
26
|
-
parser: (policy) => {
|
|
27
|
-
return availablePolicies.includes(policy)
|
|
28
|
-
? cliparse.parsers.success(policy)
|
|
29
|
-
: cliparse.parsers.error(`the policy must be one of ${availablePolicies.join(', ')}`);
|
|
30
|
-
},
|
|
31
|
-
default: 'error',
|
|
32
|
-
description: `What to do when local and remote commit are identical (${availablePolicies.join(', ')})`,
|
|
33
|
-
complete() {
|
|
34
|
-
return cliparse.autocomplete.words(availablePolicies);
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function getExitOnOption() {
|
|
40
|
-
const availableExitOn = ['deploy-start', 'deploy-end', 'never'];
|
|
41
|
-
return cliparse.option('exit-on', {
|
|
42
|
-
aliases: ['e'],
|
|
43
|
-
metavar: 'step',
|
|
44
|
-
parser: (exitOnStrategy) => {
|
|
45
|
-
return availableExitOn.includes(exitOnStrategy)
|
|
46
|
-
? cliparse.parsers.success(exitOnStrategy)
|
|
47
|
-
: cliparse.parsers.error(`The exit-on strategy must be one of ${availableExitOn.join(', ')}`);
|
|
48
|
-
},
|
|
49
|
-
default: 'deploy-end',
|
|
50
|
-
description: `Step at which the logs streaming is ended, steps are: ${availableExitOn.join(', ')}`,
|
|
51
|
-
complete() {
|
|
52
|
-
return cliparse.autocomplete.words(availableExitOn);
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import semver from 'semver';
|
|
2
|
-
import pkg from '../package.json' with { type: 'json' };
|
|
3
|
-
import { Logger } from './logger.js';
|
|
4
|
-
|
|
5
|
-
export function handleCommandPromise(promise) {
|
|
6
|
-
promise.catch((error) => {
|
|
7
|
-
Logger.error(error);
|
|
8
|
-
const semverIsOk = semver.satisfies(process.version, pkg.engines.node);
|
|
9
|
-
if (!semverIsOk) {
|
|
10
|
-
Logger.warn(
|
|
11
|
-
`You are using node ${process.version}, some of our commands require node ${pkg.engines.node}. The error may be caused by this.`,
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
process.exit(1);
|
|
15
|
-
});
|
|
16
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { ApplicationAccessLogStream } from '@clevercloud/client/esm/streams/access-logs.js';
|
|
2
|
-
import { formatTable } from '../format-table.js';
|
|
3
|
-
import { styleText } from '../lib/style-text.js';
|
|
4
|
-
import { Logger } from '../logger.js';
|
|
5
|
-
import * as Application from '../models/application.js';
|
|
6
|
-
import { JsonArray } from '../models/json-array.js';
|
|
7
|
-
import { getHostAndTokens } from '../models/send-to-api.js';
|
|
8
|
-
import { truncateWithEllipsis } from '../models/utils.js';
|
|
9
|
-
|
|
10
|
-
// 2000 logs per 100ms maximum
|
|
11
|
-
const THROTTLE_ELEMENTS = 2000;
|
|
12
|
-
const THROTTLE_PER_IN_MILLISECONDS = 100;
|
|
13
|
-
const CITY_MAX_LENGTH = 20;
|
|
14
|
-
|
|
15
|
-
export async function accessLogs(params) {
|
|
16
|
-
// TODO: drop when add-ons are supported in API
|
|
17
|
-
if (params.options.addon) {
|
|
18
|
-
throw new Error('Access Logs are not available for add-ons yet');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { apiHost, tokens } = await getHostAndTokens();
|
|
22
|
-
const { alias, app: appIdOrName, format, before: until, after: since } = params.options;
|
|
23
|
-
const { ownerId, appId } = await Application.resolveId(appIdOrName, alias);
|
|
24
|
-
|
|
25
|
-
const stream = new ApplicationAccessLogStream({
|
|
26
|
-
apiHost,
|
|
27
|
-
tokens,
|
|
28
|
-
ownerId,
|
|
29
|
-
appId,
|
|
30
|
-
since,
|
|
31
|
-
until,
|
|
32
|
-
throttleElements: THROTTLE_ELEMENTS,
|
|
33
|
-
throttlePerInMilliseconds: THROTTLE_PER_IN_MILLISECONDS,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
if (format === 'human') {
|
|
37
|
-
Logger.println(styleText('yellow', '/!\\ This feature is in Beta testing phase'));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (format === 'json' && !until) {
|
|
41
|
-
throw new Error('JSON format only works with a limiting parameter such as `before`');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// used for 'json' format
|
|
45
|
-
const jsonArray = new JsonArray();
|
|
46
|
-
|
|
47
|
-
stream
|
|
48
|
-
.on('open', () => {
|
|
49
|
-
Logger.debug(styleText('blue', `Logs stream (open) ${JSON.stringify({ appId })}`));
|
|
50
|
-
if (format === 'json') {
|
|
51
|
-
jsonArray.open();
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
.on('error', (event) => {
|
|
55
|
-
Logger.debug(styleText('red', `Logs stream (error) ${event.error.message}`));
|
|
56
|
-
})
|
|
57
|
-
.onLog((log) => {
|
|
58
|
-
switch (format) {
|
|
59
|
-
case 'json':
|
|
60
|
-
jsonArray.push(log);
|
|
61
|
-
break;
|
|
62
|
-
case 'json-stream':
|
|
63
|
-
Logger.printJson(log);
|
|
64
|
-
break;
|
|
65
|
-
case 'human':
|
|
66
|
-
default:
|
|
67
|
-
// when the connection is cut too early, or for TCP redirections, we don't have HTTP section
|
|
68
|
-
if (log.http == null) {
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
Logger.println(formatHuman(log));
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Properly close the stream
|
|
78
|
-
process.once('SIGINT', (signal) => stream.close(signal));
|
|
79
|
-
|
|
80
|
-
const closeReason = await stream.start();
|
|
81
|
-
|
|
82
|
-
if (format === 'json') {
|
|
83
|
-
jsonArray.close();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
Logger.debug(`stream closed: ${closeReason?.type}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function formatHuman(log) {
|
|
90
|
-
const { date, http, source } = log;
|
|
91
|
-
const country = source.countryCode ?? '(unknown)';
|
|
92
|
-
const hasSourceCity = source.city ?? '';
|
|
93
|
-
|
|
94
|
-
return formatTable(
|
|
95
|
-
[
|
|
96
|
-
[
|
|
97
|
-
styleText('grey', date.toISOString(date)),
|
|
98
|
-
source.ip,
|
|
99
|
-
`${country}${hasSourceCity ? '/' + truncateWithEllipsis(CITY_MAX_LENGTH, source.city) : ''}`,
|
|
100
|
-
colorStatusCode(http.response.statusCode),
|
|
101
|
-
http.request.method.toString().padEnd(4, ' ') + ' ' + http.request.path,
|
|
102
|
-
],
|
|
103
|
-
],
|
|
104
|
-
ACCESSLOG_COLUMN_WIDTHS,
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const ACCESSLOG_COLUMN_WIDTHS = [
|
|
109
|
-
'2024-06-24T08:05:43.880Z',
|
|
110
|
-
'255.255.255.255',
|
|
111
|
-
// country / city
|
|
112
|
-
2 + 1 + CITY_MAX_LENGTH,
|
|
113
|
-
'XXX',
|
|
114
|
-
// longest method name
|
|
115
|
-
'OPTIONS',
|
|
116
|
-
// path
|
|
117
|
-
];
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* @param {number} code
|
|
121
|
-
* @returns {string}
|
|
122
|
-
*/
|
|
123
|
-
function colorStatusCode(code) {
|
|
124
|
-
const codeString = code.toString();
|
|
125
|
-
if (code >= 500) {
|
|
126
|
-
return styleText('red', codeString);
|
|
127
|
-
}
|
|
128
|
-
if (code >= 400) {
|
|
129
|
-
return styleText('yellow', codeString);
|
|
130
|
-
}
|
|
131
|
-
if (code >= 300) {
|
|
132
|
-
return styleText('blue', codeString);
|
|
133
|
-
}
|
|
134
|
-
if (code >= 200) {
|
|
135
|
-
return styleText('green', codeString);
|
|
136
|
-
}
|
|
137
|
-
return codeString;
|
|
138
|
-
}
|