@dynamicweb/cli 1.0.16 → 1.1.1
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 +256 -222
- package/bin/commands/command.js +164 -89
- package/bin/commands/config.js +54 -54
- package/bin/commands/database.js +65 -71
- package/bin/commands/env.js +174 -155
- package/bin/commands/files.js +502 -377
- package/bin/commands/install.js +64 -63
- package/bin/commands/login.js +228 -218
- package/bin/commands/query.js +172 -102
- package/bin/commands/swift.js +78 -78
- package/bin/downloader.js +70 -67
- package/bin/extractor.js +28 -28
- package/bin/index.js +73 -73
- package/bin/utils.js +112 -125
- package/package.json +51 -42
package/bin/commands/command.js
CHANGED
|
@@ -1,89 +1,164 @@
|
|
|
1
|
-
import fetch from 'node-fetch';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import { setupEnv, getAgent } from './env.js';
|
|
5
|
-
import { setupUser } from './login.js';
|
|
6
|
-
|
|
7
|
-
const exclude = ['_', '$0', 'command', 'list', 'json']
|
|
8
|
-
|
|
9
|
-
export function commandCommand() {
|
|
10
|
-
return {
|
|
11
|
-
command: 'command [command]',
|
|
12
|
-
describe: 'Runs the given command',
|
|
13
|
-
builder: (yargs) => {
|
|
14
|
-
return yargs
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
let
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { setupEnv, getAgent } from './env.js';
|
|
5
|
+
import { setupUser } from './login.js';
|
|
6
|
+
|
|
7
|
+
const exclude = ['_', '$0', 'command', 'list', 'json', 'verbose', 'v', 'host', 'protocol', 'apiKey', 'env', 'output']
|
|
8
|
+
|
|
9
|
+
export function commandCommand() {
|
|
10
|
+
return {
|
|
11
|
+
command: 'command [command]',
|
|
12
|
+
describe: 'Runs the given command',
|
|
13
|
+
builder: (yargs) => {
|
|
14
|
+
return yargs
|
|
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
|
+
})
|
|
29
|
+
},
|
|
30
|
+
handler: async (argv) => {
|
|
31
|
+
const output = createCommandOutput(argv);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
output.verboseLog(`Running command ${argv.command}`);
|
|
35
|
+
await handleCommand(argv, output);
|
|
36
|
+
output.finish();
|
|
37
|
+
} catch (err) {
|
|
38
|
+
output.fail(err);
|
|
39
|
+
output.finish();
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function handleCommand(argv, output) {
|
|
47
|
+
let env = await setupEnv(argv);
|
|
48
|
+
let user = await setupUser(argv, env);
|
|
49
|
+
if (argv.list) {
|
|
50
|
+
const properties = await getProperties(env, user, argv.command);
|
|
51
|
+
output.addData(properties);
|
|
52
|
+
output.log(properties);
|
|
53
|
+
} else {
|
|
54
|
+
let response = await runCommand(env, user, argv.command, getQueryParams(argv), parseJsonOrPath(argv.json));
|
|
55
|
+
output.addData(response);
|
|
56
|
+
output.log(response);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function getProperties(env, user, command) {
|
|
61
|
+
return `This option currently doesn't work`
|
|
62
|
+
let res = await fetch(`${env.protocol}://${env.host}/Admin/Api/CommandByName?name=${command}`, {
|
|
63
|
+
method: 'GET',
|
|
64
|
+
headers: {
|
|
65
|
+
'Authorization': `Bearer ${user.apiKey}`
|
|
66
|
+
},
|
|
67
|
+
agent: getAgent(env.protocol)
|
|
68
|
+
})
|
|
69
|
+
if (res.ok) {
|
|
70
|
+
let body = await res.json()
|
|
71
|
+
return body.model.propertyNames
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getQueryParams(argv) {
|
|
76
|
+
let params = {}
|
|
77
|
+
Object.keys(argv).filter(k => !exclude.includes(k)).forEach(k => params['Command.' + k] = argv[k])
|
|
78
|
+
return params
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function parseJsonOrPath(json) {
|
|
82
|
+
if (!json) return
|
|
83
|
+
if (fs.existsSync(json)) {
|
|
84
|
+
return JSON.parse(fs.readFileSync(path.resolve(json)))
|
|
85
|
+
} else {
|
|
86
|
+
return JSON.parse(json)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function runCommand(env, user, command, queryParams, data) {
|
|
91
|
+
let res = await fetch(`${env.protocol}://${env.host}/Admin/Api/${command}?` + new URLSearchParams(queryParams), {
|
|
92
|
+
method: 'POST',
|
|
93
|
+
body: JSON.stringify(data),
|
|
94
|
+
headers: {
|
|
95
|
+
'Authorization': `Bearer ${user.apiKey}`,
|
|
96
|
+
'Content-Type': 'application/json'
|
|
97
|
+
},
|
|
98
|
+
agent: getAgent(env.protocol)
|
|
99
|
+
})
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
throw createCommandError(`Error when doing request ${res.url}`, res.status, await parseJsonSafe(res));
|
|
102
|
+
}
|
|
103
|
+
return await res.json()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function createCommandOutput(argv) {
|
|
107
|
+
const response = {
|
|
108
|
+
ok: true,
|
|
109
|
+
command: 'command',
|
|
110
|
+
operation: argv.list ? 'list' : 'run',
|
|
111
|
+
status: 200,
|
|
112
|
+
data: [],
|
|
113
|
+
errors: [],
|
|
114
|
+
meta: {
|
|
115
|
+
commandName: argv.command
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
json: argv.output === 'json',
|
|
121
|
+
response,
|
|
122
|
+
log(value) {
|
|
123
|
+
if (!this.json) {
|
|
124
|
+
console.log(value);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
verboseLog(...args) {
|
|
128
|
+
if (argv.verbose && !this.json) {
|
|
129
|
+
console.info(...args);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
addData(entry) {
|
|
133
|
+
response.data.push(entry);
|
|
134
|
+
},
|
|
135
|
+
fail(err) {
|
|
136
|
+
response.ok = false;
|
|
137
|
+
response.status = err?.status || 1;
|
|
138
|
+
response.errors.push({
|
|
139
|
+
message: err?.message || 'Unknown command error.',
|
|
140
|
+
details: err?.details ?? null
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
finish() {
|
|
144
|
+
if (this.json) {
|
|
145
|
+
console.log(JSON.stringify(response, null, 2));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function createCommandError(message, status, details = null) {
|
|
152
|
+
const error = new Error(message);
|
|
153
|
+
error.status = status;
|
|
154
|
+
error.details = details;
|
|
155
|
+
return error;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function parseJsonSafe(res) {
|
|
159
|
+
try {
|
|
160
|
+
return await res.json();
|
|
161
|
+
} catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
package/bin/commands/config.js
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import os from 'os';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
|
|
4
|
-
const configLocation = os.homedir() + '/.dwc';
|
|
5
|
-
let localConfig;
|
|
6
|
-
|
|
7
|
-
export function configCommand() {
|
|
8
|
-
return {
|
|
9
|
-
command: 'config',
|
|
10
|
-
describe: 'Edit the configs located in
|
|
11
|
-
handler: (argv) => handleConfig(argv),
|
|
12
|
-
builder: {
|
|
13
|
-
prop: {
|
|
14
|
-
type: 'string',
|
|
15
|
-
describe: 'Path to your config property, i.e --env.dev.host=newHost:1000'
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function setupConfig() {
|
|
22
|
-
try {
|
|
23
|
-
localConfig = JSON.parse(fs.readFileSync(configLocation));
|
|
24
|
-
} catch (e) {
|
|
25
|
-
localConfig = {}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getConfig() {
|
|
30
|
-
return localConfig;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function handleConfig(argv) {
|
|
34
|
-
Object.keys(argv).forEach(a => {
|
|
35
|
-
if (a != '_' && a != '$0') {
|
|
36
|
-
resolveConfig(a, argv[a],
|
|
37
|
-
updateConfig();
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function updateConfig() {
|
|
43
|
-
fs.writeFileSync(configLocation, JSON.stringify(localConfig));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function resolveConfig(key, obj, conf) {
|
|
47
|
-
if (typeof obj !== 'object' || !(obj instanceof Object)) {
|
|
48
|
-
return obj;
|
|
49
|
-
}
|
|
50
|
-
Object.keys(obj).forEach(a => {
|
|
51
|
-
conf[a] = conf[a] || {};
|
|
52
|
-
conf[a] = resolveConfig(key, obj[a], conf[a]);
|
|
53
|
-
})
|
|
54
|
-
return conf;
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
|
|
4
|
+
const configLocation = os.homedir() + '/.dwc';
|
|
5
|
+
let localConfig;
|
|
6
|
+
|
|
7
|
+
export function configCommand() {
|
|
8
|
+
return {
|
|
9
|
+
command: 'config',
|
|
10
|
+
describe: 'Edit the configs located in ~/.dwc',
|
|
11
|
+
handler: (argv) => handleConfig(argv),
|
|
12
|
+
builder: {
|
|
13
|
+
prop: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
describe: 'Path to your config property, i.e --env.dev.host=newHost:1000'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function setupConfig() {
|
|
22
|
+
try {
|
|
23
|
+
localConfig = JSON.parse(fs.readFileSync(configLocation));
|
|
24
|
+
} catch (e) {
|
|
25
|
+
localConfig = {}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getConfig() {
|
|
30
|
+
return localConfig;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function handleConfig(argv) {
|
|
34
|
+
Object.keys(argv).forEach(a => {
|
|
35
|
+
if (a != '_' && a != '$0') {
|
|
36
|
+
localConfig[a] = resolveConfig(a, argv[a], localConfig[a] || {});
|
|
37
|
+
updateConfig();
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function updateConfig() {
|
|
43
|
+
fs.writeFileSync(configLocation, JSON.stringify(localConfig));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function resolveConfig(key, obj, conf) {
|
|
47
|
+
if (typeof obj !== 'object' || !(obj instanceof Object)) {
|
|
48
|
+
return obj;
|
|
49
|
+
}
|
|
50
|
+
Object.keys(obj).forEach(a => {
|
|
51
|
+
conf[a] = conf[a] || {};
|
|
52
|
+
conf[a] = resolveConfig(key, obj[a], conf[a]);
|
|
53
|
+
})
|
|
54
|
+
return conf;
|
|
55
55
|
}
|
package/bin/commands/database.js
CHANGED
|
@@ -1,72 +1,66 @@
|
|
|
1
|
-
import fetch from 'node-fetch';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import _path from 'path';
|
|
4
|
-
import { setupEnv, getAgent } from './env.js';
|
|
5
|
-
import { setupUser } from './login.js';
|
|
6
|
-
|
|
7
|
-
export function databaseCommand() {
|
|
8
|
-
return {
|
|
9
|
-
command: 'database [path]',
|
|
10
|
-
describe: 'Handles database',
|
|
11
|
-
builder: (yargs) => {
|
|
12
|
-
return yargs
|
|
13
|
-
.positional('path', {
|
|
14
|
-
describe: 'Path to the .bacpac file',
|
|
15
|
-
default: '.'
|
|
16
|
-
})
|
|
17
|
-
.option('export', {
|
|
18
|
-
alias: 'e',
|
|
19
|
-
type: 'boolean',
|
|
20
|
-
description: 'Exports the solutions database to a .bacpac file at [path]'
|
|
21
|
-
})
|
|
22
|
-
},
|
|
23
|
-
handler: (argv) => {
|
|
24
|
-
if (argv.verbose) console.info(`Handling database with path: ${argv.path}`)
|
|
25
|
-
handleDatabase(argv)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function handleDatabase(argv) {
|
|
31
|
-
let env = await setupEnv(argv);
|
|
32
|
-
let user = await setupUser(argv, env);
|
|
33
|
-
|
|
34
|
-
if (argv.export) {
|
|
35
|
-
await download(env, user, argv.path, argv.verbose);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function download(env, user, path, verbose) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
res.body.on("error", reject);
|
|
67
|
-
fileStream.on("finish", resolve);
|
|
68
|
-
});
|
|
69
|
-
console.log(`Finished downloading`);
|
|
70
|
-
return res;
|
|
71
|
-
});
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import _path from 'path';
|
|
4
|
+
import { setupEnv, getAgent } from './env.js';
|
|
5
|
+
import { setupUser } from './login.js';
|
|
6
|
+
|
|
7
|
+
export function databaseCommand() {
|
|
8
|
+
return {
|
|
9
|
+
command: 'database [path]',
|
|
10
|
+
describe: 'Handles database',
|
|
11
|
+
builder: (yargs) => {
|
|
12
|
+
return yargs
|
|
13
|
+
.positional('path', {
|
|
14
|
+
describe: 'Path to the .bacpac file',
|
|
15
|
+
default: '.'
|
|
16
|
+
})
|
|
17
|
+
.option('export', {
|
|
18
|
+
alias: 'e',
|
|
19
|
+
type: 'boolean',
|
|
20
|
+
description: 'Exports the solutions database to a .bacpac file at [path]'
|
|
21
|
+
})
|
|
22
|
+
},
|
|
23
|
+
handler: async (argv) => {
|
|
24
|
+
if (argv.verbose) console.info(`Handling database with path: ${argv.path}`)
|
|
25
|
+
await handleDatabase(argv)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function handleDatabase(argv) {
|
|
31
|
+
let env = await setupEnv(argv);
|
|
32
|
+
let user = await setupUser(argv, env);
|
|
33
|
+
|
|
34
|
+
if (argv.export) {
|
|
35
|
+
await download(env, user, argv.path, argv.verbose);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function download(env, user, path, verbose) {
|
|
40
|
+
const res = await fetch(`${env.protocol}://${env.host}/Admin/Api/DatabaseDownload`, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: {
|
|
43
|
+
'Authorization': `Bearer ${user.apiKey}`,
|
|
44
|
+
'content-type': 'application/json'
|
|
45
|
+
},
|
|
46
|
+
agent: getAgent(env.protocol)
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (verbose) console.log(res)
|
|
50
|
+
const header = res.headers.get('Content-Disposition');
|
|
51
|
+
const parts = header?.split(';');
|
|
52
|
+
if (!parts || !header.includes('attachment')) {
|
|
53
|
+
console.log('Failed download, check users database permissions')
|
|
54
|
+
if (verbose) console.log(await res.json())
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const filename = parts[1].split('=')[1];
|
|
59
|
+
const fileStream = fs.createWriteStream(_path.resolve(`${_path.resolve(path)}/${filename}`));
|
|
60
|
+
await new Promise((resolve, reject) => {
|
|
61
|
+
res.body.pipe(fileStream);
|
|
62
|
+
res.body.on("error", reject);
|
|
63
|
+
fileStream.on("finish", resolve);
|
|
64
|
+
});
|
|
65
|
+
console.log(`Finished downloading`);
|
|
72
66
|
}
|