@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.
@@ -1,34 +1,34 @@
1
1
  import fetch from 'node-fetch';
2
2
  import path from 'path';
3
- import { setupEnv, getAgent } from './env.js';
3
+ import { setupEnv, getAgent, createCommandError } from './env.js';
4
4
  import { setupUser } from './login.js';
5
5
  import { uploadFiles, resolveFilePath } from './files.js';
6
6
 
7
7
  export function installCommand() {
8
8
  return {
9
- command: 'install [filePath]',
10
- describe: 'Installs the addin on the given path, allowed file extensions are .dll, .nupkg',
9
+ command: 'install <filePath>',
10
+ describe: 'Installs the addin on the given path, allowed file extensions are .dll, .nupkg',
11
11
  builder: (yargs) => {
12
12
  return yargs
13
- .positional('filePath', {
14
- describe: 'Path to the file to install'
15
- })
16
- .option('queue', {
17
- alias: 'q',
18
- type: 'boolean',
19
- describe: 'Queues the install for next Dynamicweb recycle'
20
- })
21
- .option('output', {
22
- choices: ['json'],
23
- describe: 'Outputs a single JSON response for automation-friendly parsing'
24
- })
13
+ .positional('filePath', {
14
+ describe: 'Path to the file to install'
15
+ })
16
+ .option('queue', {
17
+ alias: 'q',
18
+ type: 'boolean',
19
+ describe: 'Queues the install for next Dynamicweb recycle'
20
+ })
21
+ .option('output', {
22
+ choices: ['json'],
23
+ describe: 'Outputs a single JSON response for automation-friendly parsing'
24
+ })
25
25
  },
26
26
  handler: async (argv) => {
27
27
  const output = createInstallOutput(argv);
28
28
 
29
29
  try {
30
30
  output.verboseLog(`Installing file located at: ${argv.filePath}`);
31
- await handleInstall(argv, output)
31
+ await handleInstall(argv, output);
32
32
  } catch (err) {
33
33
  output.fail(err);
34
34
  process.exitCode = 1;
@@ -40,18 +40,15 @@ export function installCommand() {
40
40
  }
41
41
 
42
42
  async function handleInstall(argv, output) {
43
- let env = await setupEnv(argv);
43
+ let env = await setupEnv(argv, output);
44
44
  let user = await setupUser(argv, env);
45
45
  let resolvedPath = resolveFilePath(argv.filePath);
46
- output.mergeMeta({
47
- resolvedPath
48
- });
49
- await uploadFiles(env, user, [ resolvedPath ], 'System/AddIns/Local', false, true, output);
50
- await installAddin(env, user, resolvedPath, argv.queue, output)
46
+ await uploadFiles(env, user, [resolvedPath], 'System/AddIns/Local', false, true, output);
47
+ await installAddin(env, user, resolvedPath, argv.queue, output);
51
48
  }
52
49
 
53
50
  async function installAddin(env, user, resolvedPath, queue, output) {
54
- output.log('Installing addin')
51
+ output.log('Installing addin');
55
52
  let filename = path.basename(resolvedPath);
56
53
  let data = {
57
54
  'Queue': queue,
@@ -59,41 +56,57 @@ async function installAddin(env, user, resolvedPath, queue, output) {
59
56
  `${filename.substring(0, filename.lastIndexOf('.')) || filename}|${path.extname(resolvedPath)}`
60
57
  ]
61
58
  }
62
- let res = await fetch(`${env.protocol}://${env.host}/Admin/Api/AddinInstall`, {
63
- method: 'POST',
64
- body: JSON.stringify(data),
65
- headers: {
66
- 'Content-Type': 'application/json',
67
- 'Authorization': `Bearer ${user.apiKey}`
68
- },
69
- agent: getAgent(env.protocol)
70
- });
59
+ const controller = new AbortController();
60
+ const timeoutId = setTimeout(() => controller.abort(), 30_000);
61
+
62
+ let res;
63
+ try {
64
+ res = await fetch(`${env.protocol}://${env.host}/Admin/Api/AddinInstall`, {
65
+ method: 'POST',
66
+ body: JSON.stringify(data),
67
+ headers: {
68
+ 'Content-Type': 'application/json',
69
+ 'Authorization': `Bearer ${user.apiKey}`
70
+ },
71
+ agent: getAgent(env.protocol),
72
+ signal: controller.signal
73
+ });
74
+ } catch (err) {
75
+ if (err.name === 'AbortError') {
76
+ throw createCommandError('Addin installation request timed out.', 408);
77
+ }
78
+ throw err;
79
+ } finally {
80
+ clearTimeout(timeoutId);
81
+ }
71
82
 
72
83
  if (res.ok) {
73
- const body = await res.json();
84
+ const body = await parseJsonSafe(res);
85
+ output.verboseLog(body);
74
86
  output.addData({
75
87
  type: 'install',
88
+ filePath: resolvedPath,
76
89
  filename,
77
90
  queued: Boolean(queue),
78
91
  response: body
79
92
  });
80
- output.log(`Addin installed`)
81
- }
82
- else {
83
- throw createInstallError('Addin install failed.', res.status, await parseJsonSafe(res));
93
+ output.log('Addin installed');
94
+ } else {
95
+ const body = await parseJsonSafe(res);
96
+ throw createCommandError('Addin installation failed.', res.status, body);
84
97
  }
85
98
  }
86
99
 
87
- export function createInstallOutput(argv) {
100
+ function createInstallOutput(argv) {
88
101
  const response = {
89
102
  ok: true,
90
103
  command: 'install',
91
- operation: 'install',
104
+ operation: argv.queue ? 'queue' : 'install',
92
105
  status: 200,
93
106
  data: [],
94
107
  errors: [],
95
108
  meta: {
96
- queued: Boolean(argv.queue)
109
+ filePath: argv.filePath
97
110
  }
98
111
  };
99
112
 
@@ -113,7 +126,8 @@ export function createInstallOutput(argv) {
113
126
  addData(entry) {
114
127
  response.data.push(entry);
115
128
  },
116
- mergeMeta(meta) {
129
+ mergeMeta(metaOrFn) {
130
+ const meta = typeof metaOrFn === 'function' ? metaOrFn(response.meta) : metaOrFn;
117
131
  response.meta = {
118
132
  ...response.meta,
119
133
  ...meta
@@ -135,12 +149,6 @@ export function createInstallOutput(argv) {
135
149
  };
136
150
  }
137
151
 
138
- function createInstallError(message, status, details = null) {
139
- const error = new Error(message);
140
- error.status = status;
141
- error.details = details;
142
- return error;
143
- }
144
152
 
145
153
  async function parseJsonSafe(res) {
146
154
  try {