@coderich/sandman 0.0.2 → 0.0.4
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/package.json +1 -1
- package/src/FetchService.js +47 -0
- package/src/Sandman.js +13 -16
package/package.json
CHANGED
package/src/FetchService.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const Merge = require('lodash.merge');
|
|
2
2
|
|
|
3
|
+
function shq(s) { return `'${String(s).replace(/'/g, `'"'"'`)}'`; }
|
|
4
|
+
|
|
3
5
|
exports.fetch = (req) => {
|
|
4
6
|
return new Promise((resolve, reject) => {
|
|
5
7
|
const { url, ...params } = exports.normalizeRequest({ ...req });
|
|
@@ -57,3 +59,48 @@ exports.decorateRequest = (mergeData, key, request) => {
|
|
|
57
59
|
|
|
58
60
|
return Merge({}, toMerge, request);
|
|
59
61
|
};
|
|
62
|
+
|
|
63
|
+
exports.toCURL = (request, { pretty = true, redactAuth = false } = {}) => {
|
|
64
|
+
if (!request) return '<no request>';
|
|
65
|
+
|
|
66
|
+
const { url, path, method, headers, params, data } = request;
|
|
67
|
+
|
|
68
|
+
const base = new URL(url);
|
|
69
|
+
const full = new URL(path || '', base);
|
|
70
|
+
|
|
71
|
+
// append query params
|
|
72
|
+
for (const [k, v] of Object.entries(params || {})) {
|
|
73
|
+
if (v == null) continue;
|
|
74
|
+
Array.isArray(v) ? v.forEach(x => full.searchParams.append(k, String(x))) : full.searchParams.append(k, String(v));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const parts = ['curl', '-sS'];
|
|
78
|
+
if (method) parts.push('-X', method.toUpperCase());
|
|
79
|
+
|
|
80
|
+
// headers
|
|
81
|
+
const hdrs = { ...headers };
|
|
82
|
+
for (const k of Object.keys(hdrs)) {
|
|
83
|
+
if (redactAuth && /^authorization$/i.test(k)) {
|
|
84
|
+
hdrs[k] = hdrs[k].replace(/(?<=^.{6}).+/, '***REDACTED***');
|
|
85
|
+
}
|
|
86
|
+
parts.push('-H', shq(`${k}: ${hdrs[k]}`));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// body (skip for GET)
|
|
90
|
+
if (data != null && !/^GET$/i.test(method)) {
|
|
91
|
+
if (typeof data === 'string') {
|
|
92
|
+
parts.push('--data-raw', shq(data));
|
|
93
|
+
} else if (data instanceof URLSearchParams) {
|
|
94
|
+
parts.push('-H', shq('Content-Type: application/x-www-form-urlencoded'));
|
|
95
|
+
parts.push('--data', shq(data.toString()));
|
|
96
|
+
} else if (typeof data === 'object') {
|
|
97
|
+
// JSON by default
|
|
98
|
+
const hasCT = Object.keys(hdrs).some(h => /^content-type$/i.test(h));
|
|
99
|
+
if (!hasCT) parts.push('-H', shq('Content-Type: application/json'));
|
|
100
|
+
parts.push('--data-raw', shq(JSON.stringify(data)));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
parts.push(shq(full.toString()));
|
|
105
|
+
return pretty ? parts.join(' \\\n ') : parts.join(' ');
|
|
106
|
+
};
|
package/src/Sandman.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const Path = require('path');
|
|
2
|
+
const Merge = require('lodash.merge');
|
|
2
3
|
const Readline = require('readline');
|
|
3
4
|
const Chokidar = require('chokidar');
|
|
4
5
|
const EventEmitter = require('events');
|
|
@@ -10,7 +11,7 @@ const resolveSymbol = Symbol('resolve');
|
|
|
10
11
|
|
|
11
12
|
module.exports = class Sandman extends EventEmitter {
|
|
12
13
|
#configClient; #configDir; #options; #watcher; #readline; #mergeData = {}; #cli;
|
|
13
|
-
#captureCandidates = false; #candidates = []; #tabCounter = 0; #candidateIndex
|
|
14
|
+
#captureCandidates = false; #candidates = []; #tabCounter = 0; #candidateIndex; #line; #lastToken;
|
|
14
15
|
|
|
15
16
|
constructor(configDir, options) {
|
|
16
17
|
super();
|
|
@@ -36,7 +37,6 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
36
37
|
resolve: {
|
|
37
38
|
value: (...args) => {
|
|
38
39
|
this.#configClient.resolve(...args);
|
|
39
|
-
this.#prompt();
|
|
40
40
|
return this.#cli;
|
|
41
41
|
},
|
|
42
42
|
configurable: true,
|
|
@@ -71,10 +71,10 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
71
71
|
const value = get(config, key);
|
|
72
72
|
|
|
73
73
|
if (value?.request) {
|
|
74
|
-
const request = FetchService.decorateRequest(this.#mergeData, key, value.request);
|
|
75
|
-
const
|
|
74
|
+
const $request = FetchService.decorateRequest(this.#mergeData, key, value.request);
|
|
75
|
+
const request = this.#configClient.set(resolveSymbol, $request).get(resolveSymbol);
|
|
76
76
|
this.#configClient.del(resolveSymbol);
|
|
77
|
-
return
|
|
77
|
+
return Merge({}, value, { request });
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return this.#configClient.get(key, ...rest);
|
|
@@ -88,6 +88,7 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
88
88
|
get: (...args) => this.#get(...args),
|
|
89
89
|
set: (key = '', value = null) => this.#configClient.set(key, value),
|
|
90
90
|
del: (key = '') => this.#configClient.del(key),
|
|
91
|
+
curl: key => FetchService.toCURL(this.#get(key, {}).request),
|
|
91
92
|
quit: () => process.exit(),
|
|
92
93
|
}, {
|
|
93
94
|
get(obj, prop, receiver) {
|
|
@@ -95,8 +96,9 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
95
96
|
|
|
96
97
|
if (typeof value === 'function') {
|
|
97
98
|
return (...args) => {
|
|
99
|
+
self.#readline.pause();
|
|
98
100
|
const result = value(...args);
|
|
99
|
-
|
|
101
|
+
Promise.resolve().then(() => result).catch(() => null).finally(() => self.#prompt());
|
|
100
102
|
return result;
|
|
101
103
|
};
|
|
102
104
|
}
|
|
@@ -153,7 +155,8 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
153
155
|
});
|
|
154
156
|
|
|
155
157
|
const candidates = Array.from(new Set(startsWithCandidates.concat(requestKeyCandidates)));
|
|
156
|
-
if (this.#captureCandidates) { this.#candidates = candidates; this.#line = line; this.#lastToken = lastToken; }
|
|
158
|
+
if (this.#captureCandidates) { this.#candidates = candidates; this.#line = line; this.#lastToken = lastToken; this.#candidateIndex = -1; }
|
|
159
|
+
if (candidates.length === 1 && candidates[0] === lastToken) return [[], lastToken];
|
|
157
160
|
return [candidates, lastToken];
|
|
158
161
|
},
|
|
159
162
|
});
|
|
@@ -168,14 +171,8 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
168
171
|
Readline.clearLine(process.stdout, 0);
|
|
169
172
|
this.#readline.prompt();
|
|
170
173
|
} else if (this.#tabCounter > 2 && this.#candidates.length) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (!value) {
|
|
174
|
-
this.#candidateIndex = 0;
|
|
175
|
-
value = this.#candidates.at(this.#candidateIndex++);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
value = this.#line.replace(this.#lastToken, value);
|
|
174
|
+
const candidate = this.#candidates[this.#candidateIndex = ++this.#candidateIndex % this.#candidates.length];
|
|
175
|
+
const value = this.#line.replace(this.#lastToken, candidate);
|
|
179
176
|
this.#readline.line = value;
|
|
180
177
|
this.#readline.cursor = value.length;
|
|
181
178
|
this.#readline.prompt(true);
|
|
@@ -196,7 +193,7 @@ module.exports = class Sandman extends EventEmitter {
|
|
|
196
193
|
if (['add', 'change'].includes(event)) {
|
|
197
194
|
const api = ConfigClient.parseFile(path);
|
|
198
195
|
if (key) this.#configClient.set(key, api);
|
|
199
|
-
else this.#configClient.merge(api);
|
|
196
|
+
else this.#configClient.merge(api); // index.yaml
|
|
200
197
|
if (api.request) this.emit('save', { key, api });
|
|
201
198
|
this.#prompt();
|
|
202
199
|
} else if (['unlink', 'unlinkDir'].includes(event)) {
|