@coderich/sandman 0.0.1 → 0.0.3

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.1",
3
+ "version": "0.0.3",
4
4
  "main": "index.js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -13,7 +13,9 @@ exports.fetch = (req) => {
13
13
  };
14
14
 
15
15
  exports.normalizeRequest = (req) => {
16
+ req.path ??= '';
16
17
  req.method ??= 'get'; req.headers ??= {}; req.params ??= {};
18
+ req.url += req.path;
17
19
  req.url = Object.entries(req.params).reduce((url, [key, value]) => { url.searchParams.append(key, value); return url; }, new URL(req.url)).toString();
18
20
  req.headers = Object.entries(req.headers).reduce((prev, [key, value]) => Object.assign(prev, { [key.toLowerCase()]: value }), {});
19
21
  const [contentType] = req.headers['content-type']?.split(';') || [];
@@ -50,8 +52,8 @@ exports.normalizeRequest = (req) => {
50
52
  exports.decorateRequest = (mergeData, key, request) => {
51
53
  const toMerge = key.split('.').reduce((prev, k, i, arr) => {
52
54
  const $key = arr.slice(0, i).join('.');
53
- return Merge(prev, mergeData[$key]?.request);
54
- }, { ...mergeData.request });
55
+ return Merge({}, prev, mergeData[$key]?.request);
56
+ }, Merge({}, mergeData.request));
55
57
 
56
- return Merge(toMerge, request);
58
+ return Merge({}, toMerge, request);
57
59
  };
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');
@@ -6,8 +7,11 @@ const { get, flatten } = require('@coderich/util');
6
7
  const FetchService = require('./FetchService');
7
8
  const ConfigClient = require('./ConfigClient');
8
9
 
10
+ const resolveSymbol = Symbol('resolve');
11
+
9
12
  module.exports = class Sandman extends EventEmitter {
10
13
  #configClient; #configDir; #options; #watcher; #readline; #mergeData = {}; #cli;
14
+ #captureCandidates = false; #candidates = []; #tabCounter = 0; #candidateIndex = 0; #line; #lastToken;
11
15
 
12
16
  constructor(configDir, options) {
13
17
  super();
@@ -29,7 +33,16 @@ module.exports = class Sandman extends EventEmitter {
29
33
  }
30
34
 
31
35
  cli() {
32
- return this.#cli;
36
+ return Object.defineProperties(this.#cli, {
37
+ resolve: {
38
+ value: (...args) => {
39
+ this.#configClient.resolve(...args);
40
+ this.#prompt();
41
+ return this.#cli;
42
+ },
43
+ configurable: true,
44
+ },
45
+ });
33
46
  }
34
47
 
35
48
  #run(key) {
@@ -59,8 +72,10 @@ module.exports = class Sandman extends EventEmitter {
59
72
  const value = get(config, key);
60
73
 
61
74
  if (value?.request) {
62
- const request = FetchService.decorateRequest(this.#mergeData, key, value.request);
63
- this.#configClient.merge({ [key]: { request } });
75
+ const $request = FetchService.decorateRequest(this.#mergeData, key, value.request);
76
+ const request = this.#configClient.set(resolveSymbol, $request).get(resolveSymbol);
77
+ this.#configClient.del(resolveSymbol);
78
+ return Merge({}, value, { request });
64
79
  }
65
80
 
66
81
  return this.#configClient.get(key, ...rest);
@@ -106,7 +121,7 @@ module.exports = class Sandman extends EventEmitter {
106
121
  const paths = lastToken.split('.');
107
122
  const path = paths.at(-1);
108
123
 
109
- // Specific request data selector
124
+ // Specific request.data selector
110
125
  if (lastToken.startsWith('.')) {
111
126
  const api = this.#get(tokens.at(-2));
112
127
  if (!api?.request) return [[], path];
@@ -120,34 +135,51 @@ module.exports = class Sandman extends EventEmitter {
120
135
 
121
136
  // These keys follow the typing of the user
122
137
  const startsWithCandidates = Array.from(new Set(flatKeys.map((flatKey) => {
123
- return flatKey.split('.').slice(0, paths.length).join('.'); // So we can pluck off the last one
138
+ return flatKey.split('.').slice(0, paths.length).join('.');
124
139
  }))).filter((c) => {
125
140
  return c.toLowerCase().startsWith(lastToken.toLowerCase());
126
- }).map(p => p.split('.').at(-1)); // Here!
141
+ }); // .map(p => p.split('.').at(-1)); // Here!
127
142
 
128
143
  // These are shortcut keys to requests
129
144
  const requestKeyCandidates = Array.from(new Set(flatKeys.map((flatKey) => {
130
145
  const keys = flatKey.split('.');
131
146
  const index = keys.indexOf('request');
132
- const typedPath = keys.slice(0, paths.length - 1).join('.');
133
- const autocompletePath = keys.slice(paths.length - 1, index).join('.');
134
- return index > 0 && lastToken.toLowerCase().startsWith(typedPath.toLowerCase()) && autocompletePath;
147
+ return index && flatKey.split('.').slice(0, index).join('.');
148
+ // const typedPath = keys.slice(0, paths.length - 1).join('.');
149
+ // const autocompletePath = keys.slice(paths.length - 1, index).join('.');
150
+ // return index > 0 && lastToken.toLowerCase().startsWith(typedPath.toLowerCase()) && autocompletePath;
135
151
  }).filter(Boolean))).filter((c) => {
136
- return c.toLowerCase().includes(path.toLowerCase());
152
+ return c.toLowerCase().includes(lastToken.toLowerCase());
153
+ // return c.toLowerCase().includes(path.toLowerCase());
137
154
  });
138
155
 
139
156
  const candidates = Array.from(new Set(startsWithCandidates.concat(requestKeyCandidates)));
140
-
141
- return [candidates, path];
157
+ if (this.#captureCandidates) { this.#candidates = candidates; this.#line = line; this.#lastToken = lastToken; }
158
+ return [candidates, lastToken];
142
159
  },
143
160
  });
144
161
 
145
162
  process.stdin.on('keypress', (ch, key) => {
163
+ if (key && key.name === 'tab') this.#tabCounter++; else this.#tabCounter = 0;
164
+ this.#captureCandidates = this.#tabCounter === 2;
165
+
146
166
  if (key && key.name === 'escape') {
147
167
  this.#readline.line = '';
148
168
  Readline.cursorTo(process.stdout, 0);
149
169
  Readline.clearLine(process.stdout, 0);
150
170
  this.#readline.prompt();
171
+ } 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);
180
+ this.#readline.line = value;
181
+ this.#readline.cursor = value.length;
182
+ this.#readline.prompt(true);
151
183
  }
152
184
  });
153
185
  }
@@ -165,10 +197,12 @@ module.exports = class Sandman extends EventEmitter {
165
197
  if (['add', 'change'].includes(event)) {
166
198
  const api = ConfigClient.parseFile(path);
167
199
  if (key) this.#configClient.set(key, api);
168
- else this.#configClient.merge(api);
200
+ else this.#configClient.merge(api); // index.yaml
169
201
  if (api.request) this.emit('save', { key, api });
202
+ this.#prompt();
170
203
  } else if (['unlink', 'unlinkDir'].includes(event)) {
171
204
  this.#configClient.del(key);
205
+ this.#prompt();
172
206
  }
173
207
  });
174
208
  }
package/src/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const Sandman = require('./Sandman');
2
2
 
3
- module.exports = (configDir, options) => {
4
- return new Sandman(configDir, options);
3
+ module.exports = (configDir) => {
4
+ return new Sandman(configDir);
5
5
  };