cloudron 6.0.0 → 7.0.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/test/test.js CHANGED
@@ -1,31 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- /* global it:false */
4
- /* global describe:false */
5
- /* global before:false */
6
- /* global after:false */
3
+ import { after, before, describe, it } from 'mocha';
4
+ import assert from 'node:assert/strict';
5
+ import child_process from 'node:child_process';
6
+ import crypto from 'node:crypto';
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
7
9
 
8
- 'use strict';
10
+ import util from 'node:util';
9
11
 
10
- var child_process = require('child_process'),
11
- crypto = require('crypto'),
12
- expect = require('expect.js'),
13
- fs = require('fs'),
14
- path = require('path'),
15
- safe = require('safetydance'),
16
- util = require('util');
12
+ import safe from '@cloudron/safetydance';
17
13
 
18
- var cloudron = process.env.CLOUDRON;
19
- var username = process.env.USERNAME;
20
- var password = process.env.PASSWORD;
21
- var applocation = 'test';
22
- var app;
14
+ const cloudron = process.env.CLOUDRON;
15
+ const username = process.env.USERNAME;
16
+ const password = process.env.PASSWORD;
23
17
 
24
- var CLI = path.resolve(__dirname + '/../bin/cloudron');
18
+ const applocation = 'test';
19
+ let app;
20
+
21
+ const CLI = path.resolve(import.meta.dirname + '/../bin/cloudron');
25
22
 
26
23
  function md5(file) {
27
- var data = fs.readFileSync(file);
28
- var hash = crypto.createHash('md5').update(data).digest('hex');
24
+ const data = fs.readFileSync(file);
25
+ const hash = crypto.createHash('md5').update(data).digest('hex');
29
26
  return hash;
30
27
  }
31
28
 
@@ -36,7 +33,7 @@ function cli(args, options) {
36
33
  args = args.map(function (e) { return e[0] === '"' ? e.slice(1, -1) : e; }); // remove the quotes
37
34
 
38
35
  try {
39
- var cp = child_process.spawnSync(CLI, args, { stdio: [ options.stdin || 'pipe', options.stdout || 'pipe', 'pipe' ], encoding: options.encoding || 'utf8' });
36
+ const cp = child_process.spawnSync(CLI, args, { stdio: [ options.stdin || 'pipe', options.stdout || 'pipe', 'pipe' ], encoding: options.encoding || 'utf8' });
40
37
  return cp;
41
38
  } catch (e) {
42
39
  console.error(e);
@@ -44,250 +41,224 @@ function cli(args, options) {
44
41
  }
45
42
  }
46
43
 
47
- before(function (done) {
48
- if (!process.env.CLOUDRON) return done(new Error('CLOUDRON env var not set'));
49
- if (!process.env.USERNAME) return done(new Error('USERNAME env var not set'));
50
- if (!process.env.PASSWORD) return done(new Error('PASSWORD env var not set'));
51
-
52
- done();
44
+ before(() => {
45
+ if (!process.env.CLOUDRON) throw new Error('CLOUDRON env const not set');
46
+ if (!process.env.USERNAME) throw new Error('USERNAME env const not set');
47
+ if (!process.env.PASSWORD) throw new Error('PASSWORD env const not set');
53
48
  });
54
49
 
55
- after(function (done) {
56
- done();
57
- });
58
-
59
- describe('Login', function () {
60
- it('can login', function (done) {
61
- var out = cli(util.format('login %s --username %s --password %s', cloudron, username, password));
62
-
63
- if (out.stdout.indexOf('Existing token still valid.') !== -1) return done();
50
+ describe('Login', () => {
51
+ it('can login', () => {
52
+ const out = cli(util.format('login %s --username %s --password %s', cloudron, username, password));
64
53
 
65
- expect(out.stdout.indexOf('Login successful')).to.not.be(-1);
54
+ if (out.stdout.indexOf('Existing token still valid.') !== -1) return;
66
55
 
67
- done();
56
+ assert.ok(out.stdout.includes('Login successful'));
68
57
  });
69
58
  });
70
59
 
71
60
  describe('App install', function () {
72
- this.timeout(60000);
73
-
74
- it('can install app', function () {
61
+ it('can install app', () => {
75
62
  console.log('Installing app, this can take a while');
76
- var out = cli('install --appstore-id com.hastebin.cloudronapp --location ' + applocation);
77
- expect(out.stdout).to.contain('App is installed');
63
+ const out = cli('install --appstore-id com.hastebin.cloudronapp --location ' + applocation);
64
+ assert.ok(out.stdout.includes('App is installed'));
78
65
  });
79
66
  });
80
67
 
81
- describe('Inspect', function () {
82
- it('can inspect app', function () {
83
- var inspect = JSON.parse(cli('inspect').stdout);
68
+ describe('Inspect', () => {
69
+ it('can inspect app', () => {
70
+ const inspect = JSON.parse(cli('inspect').stdout);
84
71
  app = inspect.apps.filter(function (a) { return a.location === applocation; })[0];
85
- expect(app).to.not.be(null);
72
+ assert.notStrictEqual(app, undefined);
86
73
  });
87
74
  });
88
75
 
89
76
  describe('Exec', function () {
90
- this.timeout(30000);
91
-
92
- it('can execute a command and see stdout', function () {
93
- var out = cli(util.format('exec --app %s -- ls -l /app/code', app.id));
94
- expect(out.stdout).to.contain('total');
77
+ it('can execute a command and see stdout', () => {
78
+ const out = cli(util.format('exec --app %s -- ls -l /app/code', app.id));
79
+ assert.ok(out.stdout.includes('total'));
95
80
  });
96
81
 
97
- it('can execute a command and see stderr', function () {
98
- var out = cli(util.format('exec --app %s -- ls /blah', app.id));
99
- expect(out.stderr).to.contain('ls: cannot access');
82
+ it('can execute a command and see stderr', () => {
83
+ const out = cli(util.format('exec --app %s -- ls /blah', app.id));
84
+ assert.ok(out.stderr.includes('ls: cannot access'));
100
85
  });
101
86
 
102
- it('can get binary file in stdout', function (done) {
103
- var outstream = fs.createWriteStream('/tmp/clitest.ls');
104
- outstream.on('open', function () { // execSync underlying stream needs an fd which is available only after open event
105
- cli(util.format('exec --app %s -- cat /bin/ls', app.id), { stdout: outstream, encoding: 'binary' });
106
- var result = cli(util.format('exec --app %s md5sum /bin/ls', app.id));
87
+ it('can get binary file in stdout', async () => {
88
+ const outstream = fs.createWriteStream('/tmp/clitest.ls');
89
+ await new Promise((resolve) => outstream.on('open', resolve));
90
+
91
+ cli(util.format('exec --app %s -- cat /bin/ls', app.id), { stdout: outstream, encoding: 'binary' });
92
+ const result = cli(util.format('exec --app %s md5sum /bin/ls', app.id));
107
93
 
108
- expect(result.output[1]).to.contain(md5('/tmp/clitest.ls'));
94
+ assert.ok(result.output[1].includes(md5('/tmp/clitest.ls')));
109
95
 
110
- fs.unlinkSync('/tmp/clitest.ls');
111
- done();
112
- });
96
+ fs.unlinkSync('/tmp/clitest.ls');
113
97
  });
114
98
 
115
- it('can pipe stdin to exec command', function (done) {
116
- var randomBytes = require('crypto').randomBytes(256);
99
+ it('can pipe stdin to exec command', async () => {
100
+ const randomBytes = crypto.randomBytes(256);
117
101
  fs.writeFileSync('/tmp/randombytes', randomBytes);
118
- var randomBytesMd5 = crypto.createHash('md5').update(randomBytes).digest('hex');
119
-
120
- var instream = fs.createReadStream('/tmp/randombytes');
121
- instream.on('open', function () {
122
- cli(util.format('exec --app %s -- bash -c "cat - > /app/data/sauce"', app.id), { stdin: instream });
123
- var out = cli(util.format('exec --app %s md5sum /app/data/sauce', app.id));
124
- expect(out.stdout).to.contain(randomBytesMd5);
125
- done();
126
- });
102
+ const randomBytesMd5 = crypto.createHash('md5').update(randomBytes).digest('hex');
103
+
104
+ const instream = fs.createReadStream('/tmp/randombytes');
105
+ await new Promise((resolve) => instream.on('open', resolve));
106
+
107
+ cli(util.format('exec --app %s -- bash -c "cat - > /app/data/sauce"', app.id), { stdin: instream });
108
+ const out = cli(util.format('exec --app %s md5sum /app/data/sauce', app.id));
109
+ assert.ok(out.stdout.includes(randomBytesMd5));
127
110
  });
128
111
  });
129
112
 
130
113
  describe('Push', function () {
131
- this.timeout(30000);
114
+ const RANDOM_FILE = '/tmp/randombytes';
132
115
 
133
- var RANDOM_FILE = '/tmp/randombytes';
134
-
135
- it('can push a binary file', function () {
136
- var randomBytes = crypto.randomBytes(500);
116
+ it('can push a binary file', () => {
117
+ const randomBytes = crypto.randomBytes(500);
137
118
  fs.writeFileSync(RANDOM_FILE, randomBytes);
138
119
 
139
120
  cli(util.format('push --app %s %s /tmp/push1', app.id, RANDOM_FILE));
140
- var out = cli(util.format('exec --app %s md5sum /tmp/push1', app.id));
141
- expect(out.stdout).to.contain(md5(RANDOM_FILE));
121
+ const out = cli(util.format('exec --app %s md5sum /tmp/push1', app.id));
122
+ assert.ok(out.stdout.includes(md5(RANDOM_FILE)));
142
123
  fs.unlinkSync(RANDOM_FILE);
143
124
  });
144
125
 
145
- it('can push to directory', function () {
146
- var testFile = __dirname + '/test.js';
126
+ it('can push to directory', () => {
127
+ const testFile = import.meta.dirname + '/test.js';
147
128
  cli(util.format('push --app %s %s /tmp/', app.id, testFile));
148
- var out = cli(util.format('exec --app %s md5sum /tmp/test.js', app.id));
149
- expect(out.stdout).to.contain(md5(testFile));
129
+ const out = cli(util.format('exec --app %s md5sum /tmp/test.js', app.id));
130
+ assert.ok(out.stdout.includes(md5(testFile)));
150
131
  });
151
132
 
152
- it('can push stdin', function (done) {
153
- var randomBytes = crypto.randomBytes(500);
133
+ it('can push stdin', async () => {
134
+ const randomBytes = crypto.randomBytes(500);
154
135
  fs.writeFileSync(RANDOM_FILE, randomBytes);
155
136
 
156
- var istream = fs.createReadStream(RANDOM_FILE);
157
- istream.on('open', function () { // exec requires underlying fd
158
- cli(util.format('push --app %s - /run/testcopy.js', app.id), { stdin: istream });
159
- var out = cli(util.format('exec --app %s md5sum /run/testcopy.js', app.id));
160
- expect(out.stdout).to.contain(md5(RANDOM_FILE));
161
- fs.unlinkSync(RANDOM_FILE);
162
- done();
163
- });
137
+ const istream = fs.createReadStream(RANDOM_FILE);
138
+ await new Promise((resolve) => istream.on('open', resolve));
139
+
140
+ cli(util.format('push --app %s - /run/testcopy.js', app.id), { stdin: istream });
141
+ const out = cli(util.format('exec --app %s md5sum /run/testcopy.js', app.id));
142
+ assert.ok(out.stdout.includes(md5(RANDOM_FILE)));
143
+ fs.unlinkSync(RANDOM_FILE);
164
144
  });
165
145
 
166
- it('can push a directory', function () {
167
- var testDir = __dirname, testFile = __dirname + '/test.js';
146
+ it('can push a directory', () => {
147
+ const testDir = import.meta.dirname, testFile = import.meta.dirname + '/test.js';
168
148
  cli(util.format('push --app %s %s /run', app.id, testDir));
169
- var out = cli(util.format('exec --app %s md5sum /run/' + path.basename(__dirname) + '/test.js', app.id));
170
- expect(out.stdout).to.contain(md5(testFile));
149
+ const out = cli(util.format('exec --app %s md5sum /run/' + path.basename(import.meta.dirname) + '/test.js', app.id));
150
+ assert.ok(out.stdout.includes(md5(testFile)));
171
151
  });
172
152
 
173
- it('can push a large file', function () {
153
+ it('can push a large file', () => {
174
154
  child_process.execSync('dd if=/dev/urandom of=' + RANDOM_FILE + ' bs=10M count=1');
175
155
  cli(util.format('push --app %s %s /tmp/push1', app.id, RANDOM_FILE));
176
- var out = cli(util.format('exec --app %s md5sum /tmp/push1', app.id));
177
- expect(out.stdout).to.contain(md5(RANDOM_FILE));
156
+ const out = cli(util.format('exec --app %s md5sum /tmp/push1', app.id));
157
+ assert.ok(out.stdout.includes(md5(RANDOM_FILE)));
178
158
  fs.unlinkSync(RANDOM_FILE);
179
159
  });
180
160
  });
181
161
 
182
162
  describe('Pull', function () {
183
- this.timeout(30000);
163
+ const RANDOM_FILE = '/tmp/randombytes';
184
164
 
185
- var RANDOM_FILE = '/tmp/randombytes';
186
-
187
- before(function () {
188
- var randomBytes = crypto.randomBytes(20000);
165
+ before(() => {
166
+ const randomBytes = crypto.randomBytes(20000);
189
167
  fs.writeFileSync(RANDOM_FILE, randomBytes);
190
168
 
191
169
  cli(util.format('push --app %s /tmp/randombytes /tmp/randombytes', app.id));
192
170
  });
193
171
 
194
- after(function () {
172
+ after(() => {
195
173
  fs.unlinkSync(RANDOM_FILE);
196
174
  });
197
175
 
198
- it('can pull a binary file', function () {
176
+ it('can pull a binary file', () => {
199
177
  cli(util.format('pull --app %s /tmp/randombytes /tmp/pullfiletest', app.id));
200
- expect(md5('/tmp/pullfiletest')).to.be(md5('/tmp/randombytes'));
178
+ assert.strictEqual(md5('/tmp/pullfiletest'), md5('/tmp/randombytes'));
201
179
  fs.unlinkSync('/tmp/pullfiletest');
202
180
  });
203
181
 
204
- it('can pull a directory', function () {
182
+ it('can pull a directory', () => {
205
183
  fs.rmSync('/tmp/pulldir', { recursive: true, force: true });
206
184
  safe.fs.mkdirSync('/tmp/pulldir');
207
185
  cli(util.format('pull --app %s /app/code/ /tmp/pulldir', app.id));
208
- expect(fs.existsSync('/tmp/pulldir/README.md')).to.be.ok();
209
- expect(fs.existsSync('/tmp/pulldir/static/robots.txt')).to.be.ok();
210
- expect(fs.existsSync('/tmp/pulldir/.gitignore')).to.be.ok();
186
+ assert.ok(fs.existsSync('/tmp/pulldir/README.md'));
187
+ assert.ok(fs.existsSync('/tmp/pulldir/static/robots.txt'));
188
+ assert.ok(fs.existsSync('/tmp/pulldir/.gitignore'));
211
189
 
212
- var result = cli(util.format('exec --app %s md5sum /app/code/node_modules/uglify-js/bin/uglifyjs', app.id));
213
- expect(result.output[1]).to.contain(md5('/tmp/pulldir/node_modules/uglify-js/bin/uglifyjs'));
190
+ const result = cli(util.format('exec --app %s md5sum /app/code/node_modules/uglify-js/bin/uglifyjs', app.id));
191
+ assert.ok(result.output[1].includes(md5('/tmp/pulldir/node_modules/uglify-js/bin/uglifyjs')));
214
192
 
215
193
  fs.rmSync('/tmp/pulldir', { recursive: true, force: true });
216
194
  });
217
195
 
218
- it('can pull to directory', function () {
196
+ it('can pull to directory', () => {
219
197
  safe.fs.unlinkSync('/tmp/pulledreadme.md');
220
198
  cli(util.format('pull --app %s /app/code/README.md /tmp/pulledreadme.md', app.id));
221
199
 
222
- var result = cli(util.format('exec --app %s md5sum /app/code/README.md', app.id));
223
- expect(result.output[1]).to.contain(md5('/tmp/pulledreadme.md'));
200
+ const result = cli(util.format('exec --app %s md5sum /app/code/README.md', app.id));
201
+ assert.ok(result.output[1].includes(md5('/tmp/pulledreadme.md')));
224
202
 
225
203
  fs.unlinkSync('/tmp/pulledreadme.md');
226
204
  });
227
205
 
228
- it('can pull to stdout', function (done) {
206
+ it('can pull to stdout', async () => {
229
207
  safe.fs.unlinkSync('/tmp/pullfiletest');
230
- var ostream = fs.createWriteStream('/tmp/pullfiletest');
231
- ostream.on('open', function () { // exec requires underlying fd
232
- cli(util.format('pull --app %s /tmp/randombytes -', app.id), { stdout: ostream });
233
- expect(md5('/tmp/pullfiletest')).to.be(md5('/tmp/randombytes'));
234
- fs.unlinkSync('/tmp/pullfiletest');
235
- done();
236
- });
208
+ const ostream = fs.createWriteStream('/tmp/pullfiletest');
209
+ await new Promise((resolve) => ostream.on('open', resolve));
210
+
211
+ cli(util.format('pull --app %s /tmp/randombytes -', app.id), { stdout: ostream });
212
+ assert.strictEqual(md5('/tmp/pullfiletest'), md5('/tmp/randombytes'));
213
+ fs.unlinkSync('/tmp/pullfiletest');
237
214
  });
238
215
  });
239
216
 
240
- describe('Status', function () {
241
- it('can get status', function () {
242
- var out = cli('status --app ' + app.id);
243
- expect(out.stdout).to.contain('running');
217
+ describe('Status', () => {
218
+ it('can get status', () => {
219
+ const out = cli('status --app ' + app.id);
220
+ assert.ok(out.stdout.includes('running'));
244
221
  });
245
222
  });
246
223
 
247
224
  describe('Backup', function () {
248
- this.timeout(30000);
249
-
250
- var backupId;
251
-
252
- it('create succeeds', function () {
253
- var out = cli('backup create --app ' + app.id);
254
- expect(out.stdout).to.contain('App is backed up');
225
+ it('create succeeds', () => {
226
+ const out = cli('backup create --app ' + app.id);
227
+ assert.ok(out.stdout.includes('App is backed up'));
255
228
  });
256
229
 
257
- it('list succeeds', function () {
258
- var out = cli('backup list --app ' + app.id);
259
- expect(out.stdout).to.contain(app.id);
230
+ it('list succeeds', () => {
231
+ const out = cli('backup list --app ' + app.id);
232
+ assert.ok(out.stdout.includes(app.id));
260
233
 
261
- backupId = out.stdout.split('\n').reverse().filter(function (b) { return b; })[0].split(' ')[0];
234
+ /* backupId = */ out.stdout.split('\n').reverse().filter(function (b) { return b; })[0].split(' ')[0];
262
235
  });
263
236
  });
264
237
 
265
- describe('list apps', function () {
266
- it('succeeds', function () {
267
- var out = cli('list');
268
- expect(out.stdout).to.contain(app.id);
238
+ describe('list apps', () => {
239
+ it('succeeds', () => {
240
+ const out = cli('list');
241
+ assert.ok(out.stdout.includes(app.id));
269
242
  });
270
243
  });
271
244
 
272
- describe('app logs', function () {
273
- it('succeeds', function () {
274
- var out = cli('logs --app ' + app.id);
275
- expect(out.stdout).to.contain('listening on');
245
+ describe('app logs', () => {
246
+ it('succeeds', () => {
247
+ const out = cli('logs --app ' + app.id);
248
+ assert.ok(out.stdout.includes('listening on'));
276
249
  });
277
250
  });
278
251
 
279
252
  describe('Uninstall', function () {
280
- this.timeout(30000);
281
-
282
- it('can uninstall', function () {
283
- var out = cli('uninstall --app ' + app.id);
284
- expect(out.stdout).to.contain('successfully uninstalled');
253
+ it('can uninstall', () => {
254
+ const out = cli('uninstall --app ' + app.id);
255
+ assert.ok(out.stdout.includes('successfully uninstalled'));
285
256
  });
286
257
  });
287
258
 
288
- describe('Logout', function () {
289
- it('can logout', function () {
290
- var out = cli('logout');
291
- expect(out.stdout).to.contain('Logged out');
259
+ describe('Logout', () => {
260
+ it('can logout', () => {
261
+ const out = cli('logout');
262
+ assert.ok(out.stdout.includes('Logged out'));
292
263
  });
293
264
  });
package/src/superagent.js DELETED
@@ -1,225 +0,0 @@
1
- 'use strict';
2
-
3
- exports = module.exports = {
4
- head,
5
- get,
6
- put,
7
- post,
8
- patch,
9
- del,
10
- options,
11
- request
12
- };
13
-
14
- // IMPORTANT: do not require box code here . This is used by migration scripts
15
- const assert = require('assert'),
16
- consumers = require('node:stream/consumers'),
17
- debug = require('debug')('box:superagent'),
18
- fs = require('fs'),
19
- http = require('http'),
20
- https = require('https'),
21
- path = require('path'),
22
- safe = require('safetydance');
23
-
24
- class Request {
25
- #boundary;
26
- #redirectCount;
27
- #retryCount;
28
- #timer;
29
- #body;
30
- #okFunc;
31
- #options;
32
- #url;
33
-
34
- constructor(method, url) {
35
- assert.strictEqual(typeof url, 'string');
36
-
37
- this.#url = new URL(url);
38
- this.#options = {
39
- method,
40
- headers: {},
41
- signal: null // set for timeouts
42
- };
43
- this.#okFunc = ({ status }) => status >=200 && status <= 299;
44
- this.#timer = { timeout: 0, id: null, controller: null };
45
- this.#retryCount = 0;
46
- this.#body = Buffer.alloc(0);
47
- this.#redirectCount = 5;
48
- this.#boundary = null; // multipart only
49
- }
50
-
51
- async _handleResponse(url, response) {
52
- // const contentLength = response.headers['content-length'];
53
- // if (!contentLength || contentLength > 5*1024*1024*1024) throw new Error(`Response size unknown or too large: ${contentLength}`);
54
- const [consumeError, data] = await safe(consumers.buffer(response)); // have to drain response
55
- if (consumeError) throw new Error(`Error consuming body stream: ${consumeError.message}`);
56
- if (!response.complete) throw new Error('Incomplete response');
57
- const contentType = response.headers['content-type'];
58
-
59
- const result = {
60
- url: new URL(response.headers['location'] || '', url),
61
- status: response.statusCode,
62
- headers: response.headers,
63
- body: null,
64
- text: null
65
- };
66
-
67
- if (contentType?.includes('application/json')) {
68
- result.text = data.toString('utf8');
69
- if (data.byteLength !== 0) result.body = safe.JSON.parse(result.text) || {};
70
- } else if (contentType?.includes('application/x-www-form-urlencoded')) {
71
- result.text = data.toString('utf8');
72
- const searchParams = new URLSearchParams(data);
73
- result.body = Object.fromEntries(searchParams.entries());
74
- } else if (!contentType || contentType.startsWith('text/')) {
75
- result.body = data;
76
- result.text = result.body.toString('utf8');
77
- } else {
78
- result.body = data;
79
- result.text = `<binary data (${data.byteLength} bytes)>`;
80
- }
81
-
82
- return result;
83
- }
84
-
85
- async _makeRequest(url) {
86
- return new Promise((resolve, reject) => {
87
- const proto = url.protocol === 'https:' ? https : http;
88
- const request = proto.request(url, this.#options); // ClientRequest
89
-
90
- request.on('error', reject); // network error, dns error
91
- request.on('response', async (response) => {
92
- const [error, result] = await safe(this._handleResponse(url, response));
93
- if (error) reject(error); else resolve(result);
94
- });
95
-
96
- request.write(this.#body);
97
-
98
- request.end();
99
- });
100
- }
101
-
102
- async _start() {
103
- let error;
104
-
105
- for (let i = 0; i < this.#retryCount+1; i++) {
106
- if (this.#timer.timeout) this.#timer.id = setTimeout(() => this.#timer.controller.abort(), this.#timer.timeout);
107
- debug(`${this.#options.method} ${this.#url.toString()}` + (i ? ` try ${i+1}` : ''));
108
-
109
- let response, url = this.#url;
110
- for (let redirects = 0; redirects < this.#redirectCount+1; redirects++) {
111
- [error, response] = await safe(this._makeRequest(url));
112
- if (error || (response.status < 300 || response.status > 399) || (this.#options.method !== 'GET')) break;
113
- url = response.url; // follow
114
- }
115
-
116
- if (!error && !this.#okFunc({ status: response.status })) {
117
- error = new Error(`${response.status} ${http.STATUS_CODES[response.status]}`);
118
- Object.assign(error, response);
119
- }
120
-
121
- if (error) debug(`${this.#options.method} ${this.#url.toString()} ${error.message}`);
122
- if (this.#timer.timeout) clearTimeout(this.#timer.id);
123
- if (!error) return response;
124
- }
125
-
126
- throw error;
127
- }
128
-
129
- set(name, value) {
130
- this.#options.headers[name.toLowerCase()] = value;
131
- return this;
132
- }
133
-
134
- query(data) {
135
- Object.entries(data).forEach(([key, value]) => this.#url.searchParams.append(key, value));
136
- return this;
137
- }
138
-
139
- redirects(count) {
140
- this.#redirectCount = count;
141
- return this;
142
- }
143
-
144
- send(data) {
145
- const contentType = this.#options.headers['content-type'];
146
- if (!contentType || contentType === 'application/json') {
147
- this.#options.headers['content-type'] = 'application/json';
148
- this.#body = Buffer.from(JSON.stringify(data), 'utf8');
149
- this.#options.headers['content-length'] = this.#body.byteLength;
150
- } else if (contentType === 'application/x-www-form-urlencoded') {
151
- this.#body = Buffer.from((new URLSearchParams(data)).toString(), 'utf8');
152
- this.#options.headers['content-length'] = this.#body.byteLength;
153
- }
154
- return this;
155
- }
156
-
157
- timeout(msecs) {
158
- this.#timer.controller = new AbortController();
159
- this.#timer.timeout = msecs;
160
- this.#options.signal = this.#timer.controller.signal;
161
- return this;
162
- }
163
-
164
- retry(count) {
165
- this.#retryCount = Math.max(0, count);
166
- return this;
167
- }
168
-
169
- ok(func) {
170
- this.#okFunc = func;
171
- return this;
172
- }
173
-
174
- disableTLSCerts() {
175
- this.#options.rejectUnauthorized = true;
176
- return this;
177
- }
178
-
179
- auth(username, password) {
180
- this.set('Authorization', 'Basic ' + btoa(`${username}:${password}`));
181
- return this;
182
- }
183
-
184
- field(name, value) {
185
- if (!this.#boundary) this.#boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2);
186
-
187
- const partHeader = Buffer.from(`--${this.#boundary}\r\nContent-Disposition: form-data; name="${name}"\r\n\r\n`, 'utf8');
188
- const partData = Buffer.from(value, 'utf8');
189
- this.#body = Buffer.concat([this.#body, partHeader, partData, Buffer.from('\r\n', 'utf8')]);
190
-
191
- return this;
192
- }
193
-
194
- attach(name, filepathOrBuffer) { // this is only used in tests and thus simplistic
195
- if (!this.#boundary) this.#boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2);
196
-
197
- const filename = Buffer.isBuffer(filepathOrBuffer) ? name : path.basename(filepathOrBuffer);
198
- const partHeader = Buffer.from(`--${this.#boundary}\r\nContent-Disposition: form-data; name="${name}" filename="${filename}"\r\n\r\n`, 'utf8');
199
- const partData = Buffer.isBuffer(filepathOrBuffer) ? filepathOrBuffer : fs.readFileSync(filepathOrBuffer);
200
- this.#body = Buffer.concat([this.#body, partHeader, partData, Buffer.from('\r\n', 'utf8')]);
201
-
202
- return this;
203
- }
204
-
205
- then(onFulfilled, onRejected) {
206
- if (this.#boundary) {
207
- const partTrailer = Buffer.from(`--${this.#boundary}--\r\n`, 'utf8');
208
- this.#body = Buffer.concat([this.#body, partTrailer]);
209
-
210
- this.#options.headers['content-type'] = `multipart/form-data; boundary=${this.#boundary}`;
211
- this.#options.headers['content-length'] = this.#body.byteLength;
212
- }
213
-
214
- this._start().then(onFulfilled, onRejected);
215
- }
216
- }
217
-
218
- function head(url) { return new Request('HEAD', url); }
219
- function get(url) { return new Request('GET', url); }
220
- function put(url) { return new Request('PUT', url); }
221
- function post(url) { return new Request('POST', url); }
222
- function patch(url) { return new Request('PATCH', url); }
223
- function del(url) { return new Request('DELETE', url); }
224
- function options(url) { return new Request('OPTIONS', url); }
225
- function request(method, url) { return new Request(method, url); }