contensis-cli 1.0.0-beta.71 → 1.0.0-beta.75

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.
@@ -5,7 +5,14 @@ import inquirer from 'inquirer';
5
5
  import to from 'await-to-js';
6
6
  import chalk from 'chalk';
7
7
  import { Component, ContentType, Project } from 'contensis-core-api';
8
- import { isPassword, isSharedSecret, isUuid, tryStringify, url } from '~/util';
8
+ import {
9
+ isPassword,
10
+ isSharedSecret,
11
+ isUuid,
12
+ tryParse,
13
+ tryStringify,
14
+ url,
15
+ } from '~/util';
9
16
  import SessionCacheProvider from '../providers/SessionCacheProvider';
10
17
  import ContensisAuthService from './ContensisAuthService';
11
18
  import CredentialProvider from '~/providers/CredentialProvider';
@@ -27,6 +34,8 @@ import { Entry, Role } from 'contensis-management-api/lib/models';
27
34
  import { csvFormatter } from '~/util/csv.formatter';
28
35
  import { xmlFormatter } from '~/util/xml.formatter';
29
36
  import { jsonFormatter } from '~/util/json.formatter';
37
+ import { diffLogStrings } from '~/util/diff';
38
+ import { promiseDelay } from '~/util/timers';
30
39
  import {
31
40
  printBlockVersion,
32
41
  printMigrateResult,
@@ -2009,7 +2018,8 @@ class ContensisCli {
2009
2018
  blockId: string,
2010
2019
  branch: string,
2011
2020
  version: string,
2012
- dataCenter: 'hq' | 'manchester' | 'london'
2021
+ dataCenter: 'hq' | 'manchester' | 'london',
2022
+ follow = false
2013
2023
  ) => {
2014
2024
  const { currentEnv, env, log, messages } = this;
2015
2025
  const contensis = await this.ConnectContensis();
@@ -2026,8 +2036,17 @@ class ContensisCli {
2026
2036
  dataCenter,
2027
2037
  });
2028
2038
 
2029
- if (blockLogs) {
2030
- this.HandleFormattingAndOutput(blockLogs, () => {
2039
+ if (err) {
2040
+ log.error(
2041
+ messages.blocks.failedGetLogs(blockId, currentEnv, env.currentProject)
2042
+ );
2043
+ log.error(jsonFormatter(err));
2044
+ } else if (blockLogs) {
2045
+ const removeTrailingNewline = (logs: string) =>
2046
+ logs.endsWith('\n') ? logs.slice(0, logs.length - 1) : logs;
2047
+ const renderLogs = removeTrailingNewline(blockLogs);
2048
+
2049
+ this.HandleFormattingAndOutput(renderLogs, () => {
2031
2050
  // print the logs to console
2032
2051
  console.log(
2033
2052
  ` - ${blockId} ${branch} ${
@@ -2035,20 +2054,176 @@ class ContensisCli {
2035
2054
  } [${dataCenter}]`
2036
2055
  );
2037
2056
  log.line();
2038
- console.log(log.infoText(blockLogs));
2039
- log.line();
2057
+ console.log(log.infoText(renderLogs));
2058
+ });
2059
+
2060
+ // Code for the `--follow` options
2061
+ let following = follow;
2062
+ let alreadyShown = blockLogs;
2063
+ let needsNewLine = false;
2064
+ let counter = 0;
2065
+
2066
+ // remove existing listeners and add them back afterwards
2067
+ const listeners = process.listeners('SIGINT');
2068
+
2069
+ process.removeAllListeners('SIGINT');
2070
+ // add listener to update following to false and break out
2071
+ process.on('SIGINT', () => {
2072
+ Logger.warning(
2073
+ `\n${messages.blocks.stopFollow(
2074
+ blockId,
2075
+ currentEnv,
2076
+ env.currentProject
2077
+ )}`
2078
+ );
2079
+ stopFollowing();
2080
+ });
2081
+
2082
+ let delay = promiseDelay(5 * 1000, null);
2083
+ const stopFollowing = () => {
2084
+ following = false;
2085
+ delay.cancel();
2086
+
2087
+ // Add back the listeners we removed previously
2088
+ process.removeAllListeners('SIGINT');
2089
+ for (const listener of listeners)
2090
+ process.addListener('SIGINT', listener);
2091
+ };
2092
+
2093
+ while (following) {
2094
+ if (counter++ > 300) {
2095
+ Logger.warning(
2096
+ `\n${messages.blocks.timeoutFollow(
2097
+ blockId,
2098
+ currentEnv,
2099
+ env.currentProject
2100
+ )}`
2101
+ );
2102
+ stopFollowing();
2103
+ }
2104
+
2105
+ // wait n. seconds then poll for logs again
2106
+ await delay.wait();
2107
+
2108
+ const [lastErr, lastLogs] = following
2109
+ ? await contensis.blocks.GetBlockLogs({
2110
+ blockId,
2111
+ branchId: branch,
2112
+ version,
2113
+ dataCenter,
2114
+ })
2115
+ : [null, null];
2116
+
2117
+ if (lastLogs) {
2118
+ // Find the difference and output it next
2119
+ const difference = diffLogStrings(lastLogs, alreadyShown);
2120
+ if (difference) {
2121
+ if (needsNewLine) {
2122
+ console.log('');
2123
+ }
2124
+ // Take the trailing newline off of the logged output to
2125
+ // avoid blank lines inbetween logs fetched sequentially
2126
+ const render = removeTrailingNewline(difference);
2127
+ console.log(log.infoText(render));
2128
+
2129
+ // Add what we've just rendered to already shown "cache"
2130
+ alreadyShown += render;
2131
+ needsNewLine = false;
2132
+ } else {
2133
+ // If no difference output a dot
2134
+ process.stdout.write('.');
2135
+ needsNewLine = true;
2136
+ }
2137
+ } else if (lastErr) {
2138
+ // If error output an x
2139
+ process.stdout.write('x');
2140
+ }
2141
+ }
2142
+ }
2143
+ }
2144
+ };
2145
+
2146
+ PrintProxies = async (proxyId?: string) => {
2147
+ const { currentEnv, env, log, messages } = this;
2148
+ const contensis = await this.ConnectContensis();
2149
+ if (contensis) {
2150
+ // Retrieve proxies list for env
2151
+ const [err, proxies] = await contensis.proxies.GetProxies(proxyId);
2152
+
2153
+ if (Array.isArray(proxies)) {
2154
+ this.HandleFormattingAndOutput(proxies, () => {
2155
+ // print the proxies to console
2156
+ log.success(messages.proxies.list(currentEnv, env.currentProject));
2157
+ for (const { id, name, description, endpoints, version } of proxies) {
2158
+ console.log(
2159
+ ` - ${name} [${
2160
+ version.versionNo
2161
+ }] ${id} ${log.infoText`${description}`}`
2162
+ );
2163
+ for (const [language, endpoint] of Object.entries(endpoints))
2164
+ console.log(
2165
+ ` - ${log.infoText`language: ${language}
2166
+ server: ${endpoint.server}
2167
+ headers.host: ${endpoint.headers.host}
2168
+ ssl: ${endpoint.ssl}`}`
2169
+ );
2170
+ }
2040
2171
  });
2041
2172
  }
2042
2173
 
2043
2174
  if (err) {
2044
- log.error(
2045
- messages.blocks.failedGetLogs(blockId, currentEnv, env.currentProject)
2046
- );
2175
+ log.error(messages.proxies.noList(currentEnv, env.currentProject));
2047
2176
  log.error(jsonFormatter(err));
2048
2177
  }
2049
2178
  }
2050
2179
  };
2051
2180
 
2181
+ PrintRenderers = async (rendererId?: string) => {
2182
+ const { currentEnv, env, log, messages } = this;
2183
+ const contensis = await this.ConnectContensis();
2184
+ if (contensis) {
2185
+ // Retrieve renderers list for env
2186
+ const [err, renderers] = await contensis.renderers.GetRenderers(
2187
+ rendererId
2188
+ );
2189
+
2190
+ if (Array.isArray(renderers)) {
2191
+ this.HandleFormattingAndOutput(renderers, () => {
2192
+ // print the renderers to console
2193
+ log.success(messages.renderers.list(currentEnv, env.currentProject));
2194
+ for (const {
2195
+ id,
2196
+ description,
2197
+ assignedContentTypes,
2198
+ rules,
2199
+ version,
2200
+ } of renderers) {
2201
+ console.log(
2202
+ ` - ${id} [${version.versionNo}] ${log.infoText`${description}`}`
2203
+ );
2204
+ if (assignedContentTypes?.length)
2205
+ console.log(
2206
+ log.infoText` assignedContentTypes: ${assignedContentTypes.join(
2207
+ ', '
2208
+ )}`
2209
+ );
2210
+ for (const rule of rules)
2211
+ if (rule.return)
2212
+ console.log(
2213
+ log.infoText` ${
2214
+ rule.return.endpointId ? 'endpointId' : 'blockId'
2215
+ }: ${rule.return.endpointId || rule.return.blockId}`
2216
+ );
2217
+ }
2218
+ });
2219
+ }
2220
+
2221
+ if (err) {
2222
+ log.error(messages.renderers.noList(currentEnv, env.currentProject));
2223
+ log.error(jsonFormatter(err));
2224
+ }
2225
+ }
2226
+ };
2052
2227
  HandleFormattingAndOutput = <T>(obj: T, logFn: (obj: T) => void) => {
2053
2228
  const { format, log, messages, output } = this;
2054
2229
  if (!format) {
@@ -2068,15 +2243,16 @@ class ContensisCli {
2068
2243
 
2069
2244
  if (output) {
2070
2245
  let writeString = '';
2246
+ const isText = !tryParse(obj) && typeof obj === 'string';
2071
2247
  if (format === 'csv') {
2072
2248
  writeString = csvFormatter(obj as any);
2073
2249
  } else if (format === 'xml') {
2074
2250
  writeString = xmlFormatter(obj as any);
2075
- } else writeString = jsonFormatter(obj);
2251
+ } else writeString = isText ? (obj as string) : jsonFormatter(obj);
2076
2252
  // write output to file
2077
2253
  if (writeString) {
2078
2254
  fs.writeFileSync(output, writeString);
2079
- log.success(messages.app.fileOutput(format, output));
2255
+ log.success(messages.app.fileOutput(isText ? 'text' : format, output));
2080
2256
  } else {
2081
2257
  log.info(messages.app.noFileOutput());
2082
2258
  }
package/src/shell.ts CHANGED
@@ -162,6 +162,8 @@ class ContensisShell {
162
162
  'list components',
163
163
  'list keys',
164
164
  'list models',
165
+ 'list proxies',
166
+ 'list renderers',
165
167
  'list roles',
166
168
  'list webhooks',
167
169
  'push block',
@@ -0,0 +1,21 @@
1
+ export const diffLogStrings = (updates: string, previous: string) => {
2
+ const lastFewLines = previous.split('\n').slice(-10);
3
+ const incomingLines = updates.split('\n');
4
+
5
+ // Find the line indices in the incoming lines
6
+ // of the last few lines previously rendered
7
+ const incomingLineIndices = [];
8
+ for (const lastRenderedLine of lastFewLines) {
9
+ if (lastRenderedLine.length > 20)
10
+ incomingLineIndices.push(
11
+ incomingLines.findIndex(
12
+ incomingLine => incomingLine === lastRenderedLine
13
+ )
14
+ );
15
+ }
16
+
17
+ // Get the new lines from the next position on from the last of the already shown lines
18
+ const differentFromPos = Math.max(...incomingLineIndices) + 1 || 0;
19
+ // Return just the incoming lines from the position we matched
20
+ return incomingLines.slice(differentFromPos).join('\n');
21
+ };
package/src/util/index.ts CHANGED
@@ -8,7 +8,7 @@ export const isSharedSecret = (str = '') =>
8
8
  export const isPassword = (str = '') =>
9
9
  !isSharedSecret(str) ? str : undefined;
10
10
 
11
- export const tryParse = (str: string) => {
11
+ export const tryParse = (str: any) => {
12
12
  try {
13
13
  return typeof str === 'object' ? str : JSON.parse(str);
14
14
  } catch (e) {
@@ -0,0 +1,24 @@
1
+ export const promiseDelay = (delay: number, value: any) => {
2
+ let timeout: NodeJS.Timeout | null;
3
+ let _reject: PromiseRejectionEvent['reason'];
4
+
5
+ const wait = () =>
6
+ new Promise((resolve, reject) => {
7
+ _reject = reject;
8
+ timeout = setTimeout(resolve, delay, value);
9
+ });
10
+
11
+ const promise = wait();
12
+ return {
13
+ promise,
14
+ cancel() {
15
+ if (timeout) {
16
+ clearTimeout(timeout);
17
+ timeout = null;
18
+ _reject();
19
+ _reject = null;
20
+ }
21
+ },
22
+ wait,
23
+ };
24
+ };
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const LIB_VERSION = "1.0.0-beta.71";
1
+ export const LIB_VERSION = "1.0.0-beta.75";