@dynamicweb/cli 1.1.2 → 2.0.0-beta.2
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 +413 -171
- package/bin/commands/command.js +102 -41
- package/bin/commands/config.js +14 -2
- package/bin/commands/env.js +181 -38
- package/bin/commands/files.js +393 -110
- package/bin/commands/install.js +55 -47
- package/bin/commands/login.js +384 -45
- package/bin/commands/query.js +130 -38
- package/bin/index.js +41 -8
- package/package.json +3 -2
- package/bin/commands/files.test.js +0 -76
- package/bin/commands/install.test.js +0 -48
package/bin/commands/command.js
CHANGED
|
@@ -1,74 +1,82 @@
|
|
|
1
1
|
import fetch from 'node-fetch';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
-
import { setupEnv, getAgent } from './env.js';
|
|
4
|
+
import { setupEnv, getAgent, createCommandError } from './env.js';
|
|
5
5
|
import { setupUser } from './login.js';
|
|
6
6
|
|
|
7
|
-
const exclude = ['_', '$0', 'command', 'list', 'json', 'verbose', 'v', 'host', 'protocol', 'apiKey', 'env']
|
|
7
|
+
const exclude = ['_', '$0', 'command', 'list', 'json', 'verbose', 'v', 'host', 'protocol', 'apiKey', 'env', 'output', 'auth', 'clientId', 'clientSecret', 'clientIdEnv', 'clientSecretEnv', 'oauth']
|
|
8
8
|
|
|
9
9
|
export function commandCommand() {
|
|
10
10
|
return {
|
|
11
|
-
command: 'command [command]',
|
|
12
|
-
describe: 'Runs the given command',
|
|
11
|
+
command: 'command [command]',
|
|
12
|
+
describe: 'Runs the given command',
|
|
13
13
|
builder: (yargs) => {
|
|
14
14
|
return yargs
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
.positional('command', {
|
|
16
|
+
describe: 'The command to execute'
|
|
17
|
+
})
|
|
18
|
+
.option('json', {
|
|
19
|
+
describe: 'Literal json or location of json file to send'
|
|
20
|
+
})
|
|
21
|
+
.option('list', {
|
|
22
|
+
alias: 'l',
|
|
23
|
+
describe: 'Lists all the properties for the command, currently not working'
|
|
24
|
+
})
|
|
25
|
+
.option('output', {
|
|
26
|
+
choices: ['json'],
|
|
27
|
+
describe: 'Outputs a single JSON response for automation-friendly parsing'
|
|
28
|
+
})
|
|
25
29
|
},
|
|
26
30
|
handler: async (argv) => {
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
const output = createCommandOutput(argv);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
output.verboseLog(`Running command ${argv.command}`);
|
|
35
|
+
await handleCommand(argv, output);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
output.fail(err);
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
} finally {
|
|
40
|
+
output.finish();
|
|
41
|
+
}
|
|
29
42
|
}
|
|
30
43
|
}
|
|
31
44
|
}
|
|
32
45
|
|
|
33
|
-
async function handleCommand(argv) {
|
|
34
|
-
let env = await setupEnv(argv);
|
|
46
|
+
async function handleCommand(argv, output) {
|
|
47
|
+
let env = await setupEnv(argv, output);
|
|
35
48
|
let user = await setupUser(argv, env);
|
|
36
49
|
if (argv.list) {
|
|
37
|
-
|
|
50
|
+
const properties = await getProperties(env, user, argv.command);
|
|
51
|
+
output.addData(properties);
|
|
52
|
+
output.log(properties);
|
|
38
53
|
} else {
|
|
39
|
-
let response = await runCommand(env, user, argv.command, getQueryParams(argv), parseJsonOrPath(argv.json))
|
|
40
|
-
|
|
54
|
+
let response = await runCommand(env, user, argv.command, getQueryParams(argv), parseJsonOrPath(argv.json));
|
|
55
|
+
output.addData(response);
|
|
56
|
+
output.log(response);
|
|
41
57
|
}
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
async function getProperties(env, user, command) {
|
|
45
|
-
|
|
46
|
-
let res = await fetch(`${env.protocol}://${env.host}/Admin/Api/CommandByName?name=${command}`, {
|
|
47
|
-
method: 'GET',
|
|
48
|
-
headers: {
|
|
49
|
-
'Authorization': `Bearer ${user.apiKey}`
|
|
50
|
-
},
|
|
51
|
-
agent: getAgent(env.protocol)
|
|
52
|
-
})
|
|
53
|
-
if (res.ok) {
|
|
54
|
-
let body = await res.json()
|
|
55
|
-
return body.model.propertyNames
|
|
56
|
-
}
|
|
61
|
+
throw createCommandError('The --list option is not currently implemented for commands.');
|
|
57
62
|
}
|
|
58
63
|
|
|
59
|
-
function getQueryParams(argv) {
|
|
64
|
+
export function getQueryParams(argv) {
|
|
60
65
|
let params = {}
|
|
61
66
|
Object.keys(argv).filter(k => !exclude.includes(k)).forEach(k => params['Command.' + k] = argv[k])
|
|
62
67
|
return params
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
function parseJsonOrPath(json) {
|
|
70
|
+
export function parseJsonOrPath(json) {
|
|
66
71
|
if (!json) return
|
|
72
|
+
const trimmed = json.trim();
|
|
73
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
74
|
+
return JSON.parse(trimmed);
|
|
75
|
+
}
|
|
67
76
|
if (fs.existsSync(json)) {
|
|
68
|
-
return JSON.parse(fs.readFileSync(path.resolve(json)))
|
|
69
|
-
} else {
|
|
70
|
-
return JSON.parse(json)
|
|
77
|
+
return JSON.parse(fs.readFileSync(path.resolve(json)));
|
|
71
78
|
}
|
|
79
|
+
return JSON.parse(json);
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
async function runCommand(env, user, command, queryParams, data) {
|
|
@@ -82,8 +90,61 @@ async function runCommand(env, user, command, queryParams, data) {
|
|
|
82
90
|
agent: getAgent(env.protocol)
|
|
83
91
|
})
|
|
84
92
|
if (!res.ok) {
|
|
85
|
-
|
|
86
|
-
process.exit(1);
|
|
93
|
+
throw createCommandError(`Error when doing request ${res.url}`, res.status, await parseJsonSafe(res));
|
|
87
94
|
}
|
|
88
95
|
return await res.json()
|
|
89
|
-
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function createCommandOutput(argv) {
|
|
99
|
+
const response = {
|
|
100
|
+
ok: true,
|
|
101
|
+
command: 'command',
|
|
102
|
+
operation: argv.list ? 'list' : 'run',
|
|
103
|
+
status: 200,
|
|
104
|
+
data: [],
|
|
105
|
+
errors: [],
|
|
106
|
+
meta: {
|
|
107
|
+
commandName: argv.command
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
json: argv.output === 'json',
|
|
113
|
+
response,
|
|
114
|
+
log(value) {
|
|
115
|
+
if (!this.json) {
|
|
116
|
+
console.log(value);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
verboseLog(...args) {
|
|
120
|
+
if (argv.verbose && !this.json) {
|
|
121
|
+
console.info(...args);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
addData(entry) {
|
|
125
|
+
response.data.push(entry);
|
|
126
|
+
},
|
|
127
|
+
fail(err) {
|
|
128
|
+
response.ok = false;
|
|
129
|
+
response.status = err?.status || 1;
|
|
130
|
+
response.errors.push({
|
|
131
|
+
message: err?.message || 'Unknown command error.',
|
|
132
|
+
details: err?.details ?? null
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
finish() {
|
|
136
|
+
if (this.json) {
|
|
137
|
+
console.log(JSON.stringify(response, null, 2));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
async function parseJsonSafe(res) {
|
|
145
|
+
try {
|
|
146
|
+
return await res.json();
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
package/bin/commands/config.js
CHANGED
|
@@ -27,10 +27,22 @@ export function setupConfig() {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function getConfig() {
|
|
30
|
-
return localConfig;
|
|
30
|
+
return localConfig || {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Overrides the in-memory config for testing.
|
|
35
|
+
* @param {Object} config - Must be a plain, non-null object; handleConfig writes keys directly onto it.
|
|
36
|
+
*/
|
|
37
|
+
export function setConfigForTests(config) {
|
|
38
|
+
if (config === null || typeof config !== 'object') {
|
|
39
|
+
throw new Error('setConfigForTests: config must be a plain object');
|
|
40
|
+
}
|
|
41
|
+
localConfig = config;
|
|
31
42
|
}
|
|
32
43
|
|
|
33
44
|
export function handleConfig(argv) {
|
|
45
|
+
localConfig = localConfig || {};
|
|
34
46
|
Object.keys(argv).forEach(a => {
|
|
35
47
|
if (a != '_' && a != '$0') {
|
|
36
48
|
localConfig[a] = resolveConfig(a, argv[a], localConfig[a] || {});
|
|
@@ -52,4 +64,4 @@ function resolveConfig(key, obj, conf) {
|
|
|
52
64
|
conf[a] = resolveConfig(key, obj[a], conf[a]);
|
|
53
65
|
})
|
|
54
66
|
return conf;
|
|
55
|
-
}
|
|
67
|
+
}
|
package/bin/commands/env.js
CHANGED
|
@@ -22,6 +22,30 @@ export function getAgent(protocol) {
|
|
|
22
22
|
return protocol === 'http' ? httpAgent : httpsAgent;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export function parseHostInput(hostValue) {
|
|
26
|
+
if (!hostValue || typeof hostValue !== 'string' || !hostValue.trim()) {
|
|
27
|
+
throw createCommandError(`Invalid host value: ${hostValue}`);
|
|
28
|
+
}
|
|
29
|
+
hostValue = hostValue.trim();
|
|
30
|
+
const hostSplit = hostValue.split('://');
|
|
31
|
+
|
|
32
|
+
if (hostSplit.length === 1) {
|
|
33
|
+
return {
|
|
34
|
+
protocol: 'https',
|
|
35
|
+
host: hostSplit[0]
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (hostSplit.length === 2) {
|
|
40
|
+
return {
|
|
41
|
+
protocol: hostSplit[0],
|
|
42
|
+
host: hostSplit[1]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
throw createCommandError(`Issues resolving host ${hostValue}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
25
49
|
export function envCommand() {
|
|
26
50
|
return {
|
|
27
51
|
command: 'env [env]',
|
|
@@ -41,12 +65,29 @@ export function envCommand() {
|
|
|
41
65
|
type: 'boolean',
|
|
42
66
|
description: 'List all users in environment, uses positional [env] if used, otherwise current env'
|
|
43
67
|
})
|
|
68
|
+
.option('output', {
|
|
69
|
+
choices: ['json'],
|
|
70
|
+
describe: 'Outputs a single JSON response for automation-friendly parsing'
|
|
71
|
+
})
|
|
44
72
|
},
|
|
45
|
-
handler: (argv) =>
|
|
73
|
+
handler: async (argv) => {
|
|
74
|
+
const output = createEnvOutput(argv);
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await handleEnv(argv, output);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
output.fail(err);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
} finally {
|
|
82
|
+
output.finish();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
46
85
|
}
|
|
47
86
|
}
|
|
48
87
|
|
|
49
|
-
export async function setupEnv(argv) {
|
|
88
|
+
export async function setupEnv(argv, output = null, deps = {}) {
|
|
89
|
+
const interactiveEnvFn = deps.interactiveEnvFn || interactiveEnv;
|
|
90
|
+
const cfg = getConfig();
|
|
50
91
|
let env = {};
|
|
51
92
|
let askEnv = true;
|
|
52
93
|
|
|
@@ -60,36 +101,58 @@ export async function setupEnv(argv) {
|
|
|
60
101
|
}
|
|
61
102
|
}
|
|
62
103
|
|
|
63
|
-
if (askEnv &&
|
|
64
|
-
env =
|
|
65
|
-
if (!env.protocol) {
|
|
66
|
-
|
|
104
|
+
if (askEnv && cfg.env) {
|
|
105
|
+
env = cfg.env[argv.env] || cfg.env[cfg?.current?.env];
|
|
106
|
+
if (env && !env.protocol) {
|
|
107
|
+
logMessage(argv, 'Protocol for environment not set, defaulting to https');
|
|
67
108
|
env.protocol = 'https';
|
|
68
109
|
}
|
|
69
110
|
}
|
|
70
111
|
else if (askEnv) {
|
|
71
|
-
|
|
72
|
-
|
|
112
|
+
if (isJsonOutput(argv)) {
|
|
113
|
+
throw createCommandError('Current environment not set, please set it');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
logMessage(argv, 'Current environment not set, please set it');
|
|
117
|
+
await interactiveEnvFn(argv, {
|
|
73
118
|
environment: {
|
|
74
119
|
type: 'input'
|
|
75
120
|
},
|
|
76
121
|
interactive: {
|
|
77
122
|
default: true
|
|
78
123
|
}
|
|
79
|
-
})
|
|
80
|
-
|
|
124
|
+
}, output)
|
|
125
|
+
const updatedConfig = getConfig();
|
|
126
|
+
env = updatedConfig.env?.[updatedConfig?.current?.env];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!env || Object.keys(env).length === 0) {
|
|
130
|
+
throw createCommandError('Unable to resolve the current environment.');
|
|
81
131
|
}
|
|
132
|
+
|
|
82
133
|
return env;
|
|
83
134
|
}
|
|
84
135
|
|
|
85
|
-
async function handleEnv(argv) {
|
|
136
|
+
async function handleEnv(argv, output) {
|
|
86
137
|
if (argv.users) {
|
|
87
|
-
|
|
88
|
-
|
|
138
|
+
const cfg = getConfig();
|
|
139
|
+
let env = argv.env || cfg.current?.env;
|
|
140
|
+
const envConfig = cfg.env?.[env];
|
|
141
|
+
if (!envConfig) {
|
|
142
|
+
throw createCommandError(`Environment '${env}' does not exist`, 404);
|
|
143
|
+
}
|
|
144
|
+
const users = Object.keys(envConfig.users || {});
|
|
145
|
+
output.addData({ environment: env, users });
|
|
146
|
+
output.log(`Users in environment ${env}: ${users}`);
|
|
89
147
|
} else if (argv.env) {
|
|
90
|
-
changeEnv(argv)
|
|
148
|
+
const result = await changeEnv(argv, output);
|
|
149
|
+
if (result !== null) {
|
|
150
|
+
output.addData(result);
|
|
151
|
+
}
|
|
91
152
|
} else if (argv.list) {
|
|
92
|
-
|
|
153
|
+
const environments = Object.keys(getConfig().env || {});
|
|
154
|
+
output.addData({ environments });
|
|
155
|
+
output.log(`Existing environments: ${environments}`);
|
|
93
156
|
} else {
|
|
94
157
|
await interactiveEnv(argv, {
|
|
95
158
|
environment: {
|
|
@@ -102,12 +165,12 @@ async function handleEnv(argv) {
|
|
|
102
165
|
interactive: {
|
|
103
166
|
default: true
|
|
104
167
|
}
|
|
105
|
-
})
|
|
168
|
+
}, output)
|
|
106
169
|
}
|
|
107
170
|
}
|
|
108
171
|
|
|
109
|
-
export async function interactiveEnv(argv, options) {
|
|
110
|
-
|
|
172
|
+
export async function interactiveEnv(argv, options, output) {
|
|
173
|
+
verboseLog(argv, 'Setting up new environment');
|
|
111
174
|
const result = {};
|
|
112
175
|
for (const [key, config] of Object.entries(options)) {
|
|
113
176
|
if (key === 'interactive') continue;
|
|
@@ -122,35 +185,46 @@ export async function interactiveEnv(argv, options) {
|
|
|
122
185
|
}
|
|
123
186
|
getConfig().env = getConfig().env || {};
|
|
124
187
|
if (!result.environment || !result.environment.trim()) {
|
|
125
|
-
|
|
126
|
-
return;
|
|
188
|
+
throw createCommandError('Environment name cannot be empty');
|
|
127
189
|
}
|
|
128
190
|
getConfig().env[result.environment] = getConfig().env[result.environment] || {};
|
|
129
191
|
if (result.host) {
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
getConfig().env[result.environment].host = hostSplit[0];
|
|
134
|
-
} else if (hostSplit.length == 2) {
|
|
135
|
-
getConfig().env[result.environment].protocol = hostSplit[0];
|
|
136
|
-
getConfig().env[result.environment].host = hostSplit[1];
|
|
137
|
-
} else {
|
|
138
|
-
console.log(`Issues resolving host ${result.host}`);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
192
|
+
const resolvedHost = parseHostInput(result.host);
|
|
193
|
+
getConfig().env[result.environment].protocol = resolvedHost.protocol;
|
|
194
|
+
getConfig().env[result.environment].host = resolvedHost.host;
|
|
141
195
|
}
|
|
142
196
|
if (result.environment) {
|
|
143
197
|
getConfig().current = getConfig().current || {};
|
|
144
198
|
getConfig().current.env = result.environment;
|
|
145
199
|
}
|
|
146
200
|
updateConfig();
|
|
147
|
-
|
|
148
|
-
|
|
201
|
+
logMessage(argv, `Your current environment is now ${getConfig().current.env}`);
|
|
202
|
+
logMessage(argv, `To change the host of your environment, use the command 'dw env'`);
|
|
203
|
+
|
|
204
|
+
const currentEnv = getConfig().env[result.environment];
|
|
205
|
+
const data = {
|
|
206
|
+
environment: result.environment,
|
|
207
|
+
protocol: currentEnv.protocol || null,
|
|
208
|
+
host: currentEnv.host || null,
|
|
209
|
+
current: getConfig().current.env
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
if (output) {
|
|
213
|
+
output.addData(data);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return data;
|
|
149
217
|
}
|
|
150
218
|
|
|
151
|
-
async function changeEnv(argv) {
|
|
152
|
-
|
|
153
|
-
|
|
219
|
+
async function changeEnv(argv, output) {
|
|
220
|
+
const environments = getConfig().env || {};
|
|
221
|
+
|
|
222
|
+
if (!Object.hasOwn(environments, argv.env)) {
|
|
223
|
+
if (isJsonOutput(argv)) {
|
|
224
|
+
throw createCommandError(`The specified environment ${argv.env} doesn't exist, please create it`, 404);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
logMessage(argv, `The specified environment ${argv.env} doesn't exist, please create it`);
|
|
154
228
|
await interactiveEnv(argv, {
|
|
155
229
|
environment: {
|
|
156
230
|
type: 'input',
|
|
@@ -165,10 +239,79 @@ async function changeEnv(argv) {
|
|
|
165
239
|
interactive: {
|
|
166
240
|
default: true
|
|
167
241
|
}
|
|
168
|
-
})
|
|
242
|
+
}, output)
|
|
243
|
+
return null;
|
|
169
244
|
} else {
|
|
170
245
|
getConfig().current.env = argv.env;
|
|
171
246
|
updateConfig();
|
|
172
|
-
|
|
247
|
+
const data = {
|
|
248
|
+
environment: argv.env,
|
|
249
|
+
current: getConfig().current.env
|
|
250
|
+
};
|
|
251
|
+
logMessage(argv, `Your current environment is now ${getConfig().current.env}`);
|
|
252
|
+
if (output) {
|
|
253
|
+
output.addData(data);
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
173
256
|
}
|
|
174
257
|
}
|
|
258
|
+
|
|
259
|
+
export function isJsonOutput(argv) {
|
|
260
|
+
return argv?.output === 'json';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function createCommandError(message, status = 1, details = null) {
|
|
264
|
+
const error = new Error(message);
|
|
265
|
+
error.status = status;
|
|
266
|
+
error.details = details;
|
|
267
|
+
return error;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function logMessage(argv, ...args) {
|
|
271
|
+
if (!isJsonOutput(argv)) {
|
|
272
|
+
console.log(...args);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function verboseLog(argv, ...args) {
|
|
277
|
+
if (argv?.verbose && !isJsonOutput(argv)) {
|
|
278
|
+
console.info(...args);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function createEnvOutput(argv) {
|
|
283
|
+
const response = {
|
|
284
|
+
ok: true,
|
|
285
|
+
command: 'env',
|
|
286
|
+
operation: argv.users ? 'users' : argv.list ? 'list' : argv.env ? 'select' : 'setup',
|
|
287
|
+
status: 200,
|
|
288
|
+
data: [],
|
|
289
|
+
errors: [],
|
|
290
|
+
meta: {}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
json: isJsonOutput(argv),
|
|
295
|
+
addData(entry) {
|
|
296
|
+
response.data.push(entry);
|
|
297
|
+
},
|
|
298
|
+
log(...args) {
|
|
299
|
+
if (!this.json) {
|
|
300
|
+
console.log(...args);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
fail(err) {
|
|
304
|
+
response.ok = false;
|
|
305
|
+
response.status = err?.status || 1;
|
|
306
|
+
response.errors.push({
|
|
307
|
+
message: err?.message || 'Unknown env command error.',
|
|
308
|
+
details: err?.details ?? null
|
|
309
|
+
});
|
|
310
|
+
},
|
|
311
|
+
finish() {
|
|
312
|
+
if (this.json) {
|
|
313
|
+
console.log(JSON.stringify(response, null, 2));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|