@coderich/sandman 0.0.3 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coderich/sandman",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "main": "index.js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -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
@@ -11,7 +11,7 @@ const resolveSymbol = Symbol('resolve');
11
11
 
12
12
  module.exports = class Sandman extends EventEmitter {
13
13
  #configClient; #configDir; #options; #watcher; #readline; #mergeData = {}; #cli;
14
- #captureCandidates = false; #candidates = []; #tabCounter = 0; #candidateIndex = 0; #line; #lastToken;
14
+ #captureCandidates = false; #candidates = []; #tabCounter = 0; #candidateIndex; #line; #lastToken;
15
15
 
16
16
  constructor(configDir, options) {
17
17
  super();
@@ -37,7 +37,6 @@ module.exports = class Sandman extends EventEmitter {
37
37
  resolve: {
38
38
  value: (...args) => {
39
39
  this.#configClient.resolve(...args);
40
- this.#prompt();
41
40
  return this.#cli;
42
41
  },
43
42
  configurable: true,
@@ -89,6 +88,7 @@ module.exports = class Sandman extends EventEmitter {
89
88
  get: (...args) => this.#get(...args),
90
89
  set: (key = '', value = null) => this.#configClient.set(key, value),
91
90
  del: (key = '') => this.#configClient.del(key),
91
+ curl: key => FetchService.toCURL(this.#get(key, {}).request),
92
92
  quit: () => process.exit(),
93
93
  }, {
94
94
  get(obj, prop, receiver) {
@@ -96,8 +96,9 @@ module.exports = class Sandman extends EventEmitter {
96
96
 
97
97
  if (typeof value === 'function') {
98
98
  return (...args) => {
99
+ self.#readline.pause();
99
100
  const result = value(...args);
100
- setImmediate(() => self.#prompt());
101
+ Promise.resolve().then(() => result).catch(() => null).finally(() => self.#prompt());
101
102
  return result;
102
103
  };
103
104
  }
@@ -154,7 +155,8 @@ module.exports = class Sandman extends EventEmitter {
154
155
  });
155
156
 
156
157
  const candidates = Array.from(new Set(startsWithCandidates.concat(requestKeyCandidates)));
157
- 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];
158
160
  return [candidates, lastToken];
159
161
  },
160
162
  });
@@ -169,14 +171,8 @@ module.exports = class Sandman extends EventEmitter {
169
171
  Readline.clearLine(process.stdout, 0);
170
172
  this.#readline.prompt();
171
173
  } else if (this.#tabCounter > 2 && this.#candidates.length) {
172
- let value = this.#candidates.at(this.#candidateIndex++);
173
-
174
- if (!value) {
175
- this.#candidateIndex = 0;
176
- value = this.#candidates.at(this.#candidateIndex++);
177
- }
178
-
179
- 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);
180
176
  this.#readline.line = value;
181
177
  this.#readline.cursor = value.length;
182
178
  this.#readline.prompt(true);