spyne-cli 0.6.7 → 0.7.0

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.
Files changed (93) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +90 -38
  3. package/index.js +123 -21
  4. package/package.json +24 -6
  5. package/src/cli/args.js +197 -0
  6. package/src/cli/render.js +184 -0
  7. package/src/core/create-app.js +232 -0
  8. package/src/core/generate-module.js +146 -0
  9. package/src/registry.js +174 -0
  10. package/src/spyne-file-prompt.js +77 -30
  11. package/src/templates/generate-prompt-input-fields.js +1 -1
  12. package/src/ui.js +5 -1
  13. package/lib/ansi.js +0 -116
  14. package/lib/combos.js +0 -75
  15. package/lib/completer.js +0 -52
  16. package/lib/interpolate.js +0 -266
  17. package/lib/keypress.js +0 -243
  18. package/lib/placeholder.js +0 -63
  19. package/lib/prompt.js +0 -485
  20. package/lib/prompts/autocomplete.js +0 -113
  21. package/lib/prompts/basicauth.js +0 -41
  22. package/lib/prompts/confirm.js +0 -13
  23. package/lib/prompts/editable.js +0 -136
  24. package/lib/prompts/form.js +0 -196
  25. package/lib/prompts/index.js +0 -28
  26. package/lib/prompts/input.js +0 -55
  27. package/lib/prompts/invisible.js +0 -11
  28. package/lib/prompts/list.js +0 -36
  29. package/lib/prompts/multiselect.js +0 -11
  30. package/lib/prompts/numeral.js +0 -1
  31. package/lib/prompts/password.js +0 -18
  32. package/lib/prompts/quiz.js +0 -37
  33. package/lib/prompts/scale.js +0 -237
  34. package/lib/prompts/select.js +0 -139
  35. package/lib/prompts/snippet.js +0 -185
  36. package/lib/prompts/sort.js +0 -37
  37. package/lib/prompts/survey.js +0 -163
  38. package/lib/prompts/text.js +0 -1
  39. package/lib/prompts/toggle.js +0 -109
  40. package/lib/render.js +0 -33
  41. package/lib/roles.js +0 -46
  42. package/lib/state.js +0 -69
  43. package/lib/styles.js +0 -144
  44. package/lib/symbols.js +0 -66
  45. package/lib/theme.js +0 -11
  46. package/lib/timer.js +0 -38
  47. package/lib/types/array.js +0 -658
  48. package/lib/types/auth.js +0 -29
  49. package/lib/types/boolean.js +0 -88
  50. package/lib/types/index.js +0 -7
  51. package/lib/types/number.js +0 -86
  52. package/lib/types/string.js +0 -185
  53. package/lib/utils.js +0 -268
  54. package/mocha.conf.cjs +0 -16
  55. package/src/app/channels/.gitkeep +0 -0
  56. package/src/app/channels/channel-custom.js +0 -1
  57. package/src/app/components/.gitkeep +0 -0
  58. package/src/app/traits/.gitkeep +0 -0
  59. package/src/hello-world-app-source/README.md +0 -15
  60. package/src/hello-world-app-source/apache-htaccess +0 -20
  61. package/src/hello-world-app-source/karma.conf.js +0 -75
  62. package/src/hello-world-app-source/package.json +0 -50
  63. package/src/hello-world-app-source/src/app/app-view.js +0 -38
  64. package/src/hello-world-app-source/src/app/channels/.gitkeep +0 -0
  65. package/src/hello-world-app-source/src/app/components/.gitkeep +0 -0
  66. package/src/hello-world-app-source/src/app/traits/.gitkeep +0 -0
  67. package/src/hello-world-app-source/src/index.js +0 -16
  68. package/src/hello-world-app-source/src/index.tmpl.html +0 -12
  69. package/src/hello-world-app-source/src/scss/01-vendors/normalize.css +0 -349
  70. package/src/hello-world-app-source/src/scss/02-variables/mixins.scss +0 -0
  71. package/src/hello-world-app-source/src/scss/03-components/.gitkeep +0 -0
  72. package/src/hello-world-app-source/src/scss/main.scss +0 -15
  73. package/src/hello-world-app-source/src/static/data/.gitkeep +0 -0
  74. package/src/hello-world-app-source/src/static/fonts/.gitkeep +0 -0
  75. package/src/hello-world-app-source/src/static/imgs/.gitkeep +0 -0
  76. package/src/hello-world-app-source/src/tests/unit-tests/index.test.js +0 -10
  77. package/src/hello-world-app-source/webpack.config.js +0 -178
  78. package/src/spyne-app-create.js +0 -209
  79. package/src/spyne-app-creator.js +0 -119
  80. package/src/spyne-starter-app-create.js +0 -147
  81. package/tests/create-spyne-app.test.js +0 -63
  82. package/tests/generate-file-prompt.test.js +0 -45
  83. package/tests/generate-file-string.test.js +0 -66
  84. package/tests/generate-prompt-input-fields-methods.test.js +0 -177
  85. package/tests/generate-prompt-input-fields.test.js +0 -179
  86. package/tests/generate-prompt-input-object.test.js +0 -39
  87. package/tests/generate-prompt-output.test.js +0 -58
  88. package/tests/index.test.js +0 -11
  89. package/tests/mocks/answers.js +0 -33
  90. package/tests/mocks/answers.json +0 -33
  91. package/tests/mocks/enquirer-data.js +0 -411
  92. package/tests/mocks/enquirer-data.json +0 -409
  93. package/tests/utils/file-utils.test.js +0 -84
@@ -1,266 +0,0 @@
1
- 'use strict';
2
-
3
- const colors = require('ansi-colors');
4
- const clean = (str = '') => {
5
- return typeof str === 'string' ? str.replace(/^['"]|['"]$/g, '') : '';
6
- };
7
-
8
- /**
9
- * This file contains the interpolation and rendering logic for
10
- * the Snippet prompt.
11
- */
12
-
13
- class Item {
14
- constructor(token) {
15
- this.name = token.key;
16
- this.field = token.field || {};
17
- this.value = clean(token.initial || this.field.initial || '');
18
- this.message = token.message || this.name;
19
- this.cursor = 0;
20
- this.input = '';
21
- this.lines = [];
22
- }
23
- }
24
-
25
- const tokenize = async(options = {}, defaults = {}, fn = token => token) => {
26
- let unique = new Set();
27
- let fields = options.fields || [];
28
- let input = options.template;
29
- let tabstops = [];
30
- let items = [];
31
- let keys = [];
32
- let line = 1;
33
-
34
- if (typeof input === 'function') {
35
- input = await input();
36
- }
37
-
38
- let i = -1;
39
- let next = () => input[++i];
40
- let peek = () => input[i + 1];
41
- let push = token => {
42
- token.line = line;
43
- tabstops.push(token);
44
- };
45
-
46
- push({ type: 'bos', value: '' });
47
-
48
- while (i < input.length - 1) {
49
- let value = next();
50
-
51
- if (/^[^\S\n ]$/.test(value)) {
52
- push({ type: 'text', value });
53
- continue;
54
- }
55
-
56
- if (value === '\n') {
57
- push({ type: 'newline', value });
58
- line++;
59
- continue;
60
- }
61
-
62
- if (value === '\\') {
63
- value += next();
64
- push({ type: 'text', value });
65
- continue;
66
- }
67
-
68
- if ((value === '$' || value === '#' || value === '{') && peek() === '{') {
69
- let n = next();
70
- value += n;
71
-
72
- let token = { type: 'template', open: value, inner: '', close: '', value };
73
- let ch;
74
-
75
- while ((ch = next())) {
76
- if (ch === '}') {
77
- if (peek() === '}') ch += next();
78
- token.value += ch;
79
- token.close = ch;
80
- break;
81
- }
82
-
83
- if (ch === ':') {
84
- token.initial = '';
85
- token.key = token.inner;
86
- } else if (token.initial !== void 0) {
87
- token.initial += ch;
88
- }
89
-
90
- token.value += ch;
91
- token.inner += ch;
92
- }
93
-
94
- token.template = token.open + (token.initial || token.inner) + token.close;
95
- token.key = token.key || token.inner;
96
-
97
- if (defaults.hasOwnProperty(token.key)) {
98
- token.initial = defaults[token.key];
99
- }
100
-
101
- token = fn(token);
102
- push(token);
103
-
104
- keys.push(token.key);
105
- unique.add(token.key);
106
-
107
- let item = items.find(item => item.name === token.key);
108
- token.field = fields.find(ch => ch.name === token.key);
109
-
110
- if (!item) {
111
- item = new Item(token);
112
- items.push(item);
113
- }
114
-
115
- item.lines.push(token.line - 1);
116
- continue;
117
- }
118
-
119
- let last = tabstops[tabstops.length - 1];
120
- if (last.type === 'text' && last.line === line) {
121
- last.value += value;
122
- } else {
123
- push({ type: 'text', value });
124
- }
125
- }
126
-
127
- push({ type: 'eos', value: '' });
128
- return { input, tabstops, unique, keys, items };
129
- };
130
-
131
- module.exports = async prompt => {
132
- let options = prompt.options;
133
- let required = new Set(options.required === true ? [] : (options.required || []));
134
- let defaults = { ...options.values, ...options.initial };
135
- let { tabstops, items, keys } = await tokenize(options, defaults);
136
-
137
- let result = createFn('result', prompt, options);
138
- let format = createFn('format', prompt, options);
139
- let isValid = createFn('validate', prompt, options, true);
140
- let isVal = prompt.isValue.bind(prompt);
141
-
142
- return async(state = {}, submitted = false) => {
143
- let index = 0;
144
-
145
- state.required = required;
146
- state.items = items;
147
- state.keys = keys;
148
- state.output = '';
149
-
150
- let validate = async(value, state, item, index) => {
151
- let error = await isValid(value, state, item, index);
152
- if (error === false) {
153
- return 'Invalid field ' + item.name;
154
- }
155
- return error;
156
- };
157
-
158
- for (let token of tabstops) {
159
- let value = token.value;
160
- let key = token.key;
161
-
162
- if (token.type !== 'template') {
163
- if (value) state.output += value;
164
- continue;
165
- }
166
-
167
- if (token.type === 'template') {
168
- let item = items.find(ch => ch.name === key);
169
-
170
- if (options.required === true) {
171
- state.required.add(item.name);
172
- }
173
-
174
- let val = [item.input, state.values[item.value], item.value, value].find(isVal);
175
- let field = item.field || {};
176
- let message = field.message || token.inner;
177
-
178
- if (submitted) {
179
- let error = await validate(state.values[key], state, item, index);
180
- if ((error && typeof error === 'string') || error === false) {
181
- state.invalid.set(key, error);
182
- continue;
183
- }
184
-
185
- state.invalid.delete(key);
186
- let res = await result(state.values[key], state, item, index);
187
- state.output += colors.unstyle(res);
188
- continue;
189
- }
190
-
191
- item.placeholder = false;
192
-
193
- let before = value;
194
- value = await format(value, state, item, index);
195
-
196
- if (val !== value) {
197
- state.values[key] = val;
198
- value = prompt.styles.typing(val);
199
- state.missing.delete(message);
200
-
201
- } else {
202
- state.values[key] = void 0;
203
- val = `<${message}>`;
204
- value = prompt.styles.primary(val);
205
- item.placeholder = true;
206
-
207
- if (state.required.has(key)) {
208
- state.missing.add(message);
209
- }
210
- }
211
-
212
- if (state.missing.has(message) && state.validating) {
213
- value = prompt.styles.warning(val);
214
- }
215
-
216
- if (state.invalid.has(key) && state.validating) {
217
- value = prompt.styles.danger(val);
218
- }
219
-
220
- if (index === state.index) {
221
- if (before !== value) {
222
- value = prompt.styles.underline(value);
223
- } else {
224
- value = prompt.styles.heading(colors.unstyle(value));
225
- }
226
- }
227
-
228
- index++;
229
- }
230
-
231
- if (value) {
232
- state.output += value;
233
- }
234
- }
235
-
236
- let lines = state.output.split('\n').map(l => ' ' + l);
237
- let len = items.length;
238
- let done = 0;
239
-
240
- for (let item of items) {
241
- if (state.invalid.has(item.name)) {
242
- item.lines.forEach(i => {
243
- if (lines[i][0] !== ' ') return;
244
- lines[i] = state.styles.danger(state.symbols.bullet) + lines[i].slice(1);
245
- });
246
- }
247
-
248
- if (prompt.isValue(state.values[item.name])) {
249
- done++;
250
- }
251
- }
252
-
253
- state.completed = ((done / len) * 100).toFixed(0);
254
- state.output = lines.join('\n');
255
- return state.output;
256
- };
257
- };
258
-
259
- function createFn(prop, prompt, options, fallback) {
260
- return (value, state, item, index) => {
261
- if (typeof item.field[prop] === 'function') {
262
- return item.field[prop].call(prompt, value, state, item, index);
263
- }
264
- return [fallback, value].find(v => prompt.isValue(v));
265
- };
266
- }
package/lib/keypress.js DELETED
@@ -1,243 +0,0 @@
1
- 'use strict';
2
-
3
- const readline = require('readline');
4
- const combos = require('./combos');
5
-
6
- /* eslint-disable no-control-regex */
7
- const metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
8
- const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
9
- const keyName = {
10
- /* xterm/gnome ESC O letter */
11
- 'OP': 'f1',
12
- 'OQ': 'f2',
13
- 'OR': 'f3',
14
- 'OS': 'f4',
15
- /* xterm/rxvt ESC [ number ~ */
16
- '[11~': 'f1',
17
- '[12~': 'f2',
18
- '[13~': 'f3',
19
- '[14~': 'f4',
20
- /* from Cygwin and used in libuv */
21
- '[[A': 'f1',
22
- '[[B': 'f2',
23
- '[[C': 'f3',
24
- '[[D': 'f4',
25
- '[[E': 'f5',
26
- /* common */
27
- '[15~': 'f5',
28
- '[17~': 'f6',
29
- '[18~': 'f7',
30
- '[19~': 'f8',
31
- '[20~': 'f9',
32
- '[21~': 'f10',
33
- '[23~': 'f11',
34
- '[24~': 'f12',
35
- /* xterm ESC [ letter */
36
- '[A': 'up',
37
- '[B': 'down',
38
- '[C': 'right',
39
- '[D': 'left',
40
- '[E': 'clear',
41
- '[F': 'end',
42
- '[H': 'home',
43
- /* xterm/gnome ESC O letter */
44
- 'OA': 'up',
45
- 'OB': 'down',
46
- 'OC': 'right',
47
- 'OD': 'left',
48
- 'OE': 'clear',
49
- 'OF': 'end',
50
- 'OH': 'home',
51
- /* xterm/rxvt ESC [ number ~ */
52
- '[1~': 'home',
53
- '[2~': 'insert',
54
- '[3~': 'delete',
55
- '[4~': 'end',
56
- '[5~': 'pageup',
57
- '[6~': 'pagedown',
58
- /* putty */
59
- '[[5~': 'pageup',
60
- '[[6~': 'pagedown',
61
- /* rxvt */
62
- '[7~': 'home',
63
- '[8~': 'end',
64
- /* rxvt keys with modifiers */
65
- '[a': 'up',
66
- '[b': 'down',
67
- '[c': 'right',
68
- '[d': 'left',
69
- '[e': 'clear',
70
-
71
- '[2$': 'insert',
72
- '[3$': 'delete',
73
- '[5$': 'pageup',
74
- '[6$': 'pagedown',
75
- '[7$': 'home',
76
- '[8$': 'end',
77
-
78
- 'Oa': 'up',
79
- 'Ob': 'down',
80
- 'Oc': 'right',
81
- 'Od': 'left',
82
- 'Oe': 'clear',
83
-
84
- '[2^': 'insert',
85
- '[3^': 'delete',
86
- '[5^': 'pageup',
87
- '[6^': 'pagedown',
88
- '[7^': 'home',
89
- '[8^': 'end',
90
- /* misc. */
91
- '[Z': 'tab',
92
- }
93
-
94
- function isShiftKey(code) {
95
- return ['[a', '[b', '[c', '[d', '[e', '[2$', '[3$', '[5$', '[6$', '[7$', '[8$', '[Z'].includes(code)
96
- }
97
-
98
- function isCtrlKey(code) {
99
- return [ 'Oa', 'Ob', 'Oc', 'Od', 'Oe', '[2^', '[3^', '[5^', '[6^', '[7^', '[8^'].includes(code)
100
- }
101
-
102
- const keypress = (s = '', event = {}) => {
103
- let parts;
104
- let key = {
105
- name: event.name,
106
- ctrl: false,
107
- meta: false,
108
- shift: false,
109
- option: false,
110
- sequence: s,
111
- raw: s,
112
- ...event
113
- };
114
-
115
- if (Buffer.isBuffer(s)) {
116
- if (s[0] > 127 && s[1] === void 0) {
117
- s[0] -= 128;
118
- s = '\x1b' + String(s);
119
- } else {
120
- s = String(s);
121
- }
122
- } else if (s !== void 0 && typeof s !== 'string') {
123
- s = String(s);
124
- } else if (!s) {
125
- s = key.sequence || '';
126
- }
127
-
128
- key.sequence = key.sequence || s || key.name;
129
-
130
- if (s === '\r') {
131
- // carriage return
132
- key.raw = void 0;
133
- key.name = 'return';
134
- } else if (s === '\n') {
135
- // enter, should have been called linefeed
136
- key.name = 'enter';
137
- } else if (s === '\t') {
138
- // tab
139
- key.name = 'tab';
140
- } else if (s === '\b' || s === '\x7f' || s === '\x1b\x7f' || s === '\x1b\b') {
141
- // backspace or ctrl+h
142
- key.name = 'backspace';
143
- key.meta = s.charAt(0) === '\x1b';
144
- } else if (s === '\x1b' || s === '\x1b\x1b') {
145
- // escape key
146
- key.name = 'escape';
147
- key.meta = s.length === 2;
148
- } else if (s === ' ' || s === '\x1b ') {
149
- key.name = 'space';
150
- key.meta = s.length === 2;
151
- } else if (s <= '\x1a') {
152
- // ctrl+letter
153
- key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
154
- key.ctrl = true;
155
- } else if (s.length === 1 && s >= '0' && s <= '9') {
156
- // number
157
- key.name = 'number';
158
- } else if (s.length === 1 && s >= 'a' && s <= 'z') {
159
- // lowercase letter
160
- key.name = s;
161
- } else if (s.length === 1 && s >= 'A' && s <= 'Z') {
162
- // shift+letter
163
- key.name = s.toLowerCase();
164
- key.shift = true;
165
- } else if ((parts = metaKeyCodeRe.exec(s))) {
166
- // meta+character key
167
- key.meta = true;
168
- key.shift = /^[A-Z]$/.test(parts[1]);
169
- } else if ((parts = fnKeyRe.exec(s))) {
170
- let segs = [...s];
171
-
172
- if (segs[0] === '\u001b' && segs[1] === '\u001b') {
173
- key.option = true;
174
- }
175
-
176
- // ansi escape sequence
177
- // reassemble the key code leaving out leading \x1b's,
178
- // the modifier key bitflag and any meaningless "1;" sequence
179
- let code = [parts[1], parts[2], parts[4], parts[6]].filter(Boolean).join('');
180
- let modifier = (parts[3] || parts[5] || 1) - 1;
181
-
182
- // Parse the key modifier
183
- key.ctrl = !!(modifier & 4);
184
- key.meta = !!(modifier & 10);
185
- key.shift = !!(modifier & 1);
186
- key.code = code;
187
-
188
- key.name = keyName[code];
189
- key.shift = isShiftKey(code) || key.shift;
190
- key.ctrl = isCtrlKey(code) || key.ctrl;
191
- }
192
- return key;
193
- };
194
-
195
- keypress.listen = (options = {}, onKeypress) => {
196
- let { stdin } = options;
197
-
198
- if (!stdin || (stdin !== process.stdin && !stdin.isTTY)) {
199
- throw new Error('Invalid stream passed');
200
- }
201
-
202
- let rl = readline.createInterface({ terminal: true, input: stdin });
203
- readline.emitKeypressEvents(stdin, rl);
204
-
205
- let on = (buf, key) => onKeypress(buf, keypress(buf, key), rl);
206
- let isRaw = stdin.isRaw;
207
-
208
- if (stdin.isTTY) stdin.setRawMode(true);
209
- stdin.on('keypress', on);
210
- rl.resume();
211
-
212
- let off = () => {
213
- if (stdin.isTTY) stdin.setRawMode(isRaw);
214
- stdin.removeListener('keypress', on);
215
- rl.pause();
216
- rl.close();
217
- };
218
-
219
- return off;
220
- };
221
-
222
- keypress.action = (buf, key, customActions) => {
223
- let obj = { ...combos, ...customActions };
224
- if (key.ctrl) {
225
- key.action = obj.ctrl[key.name];
226
- return key;
227
- }
228
-
229
- if (key.option && obj.option) {
230
- key.action = obj.option[key.name];
231
- return key;
232
- }
233
-
234
- if (key.shift) {
235
- key.action = obj.shift[key.name];
236
- return key;
237
- }
238
-
239
- key.action = obj.keys[key.name];
240
- return key;
241
- };
242
-
243
- module.exports = keypress;
@@ -1,63 +0,0 @@
1
- 'use strict';
2
-
3
- const utils = require('./utils');
4
-
5
- /**
6
- * Render a placeholder value with cursor and styling based on the
7
- * position of the cursor.
8
- *
9
- * @param {Object} `prompt` Prompt instance.
10
- * @param {String} `input` Input string.
11
- * @param {String} `initial` The initial user-provided value.
12
- * @param {Number} `pos` Current cursor position.
13
- * @param {Boolean} `showCursor` Render a simulated cursor using the inverse primary style.
14
- * @return {String} Returns the styled placeholder string.
15
- * @api public
16
- */
17
-
18
- module.exports = (prompt, options = {}) => {
19
- prompt.cursorHide();
20
-
21
- let { input = '', initial = '', pos, showCursor = true, color } = options;
22
- let style = color || prompt.styles.placeholder;
23
- let inverse = utils.inverse(prompt.styles.primary);
24
- let blinker = str => inverse(prompt.styles.black(str));
25
- let output = input;
26
- let char = ' ';
27
- let reverse = blinker(char);
28
-
29
- if (prompt.blink && prompt.blink.off === true) {
30
- blinker = str => str;
31
- reverse = '';
32
- }
33
-
34
- if (showCursor && pos === 0 && initial === '' && input === '') {
35
- return blinker(char);
36
- }
37
-
38
- if (showCursor && pos === 0 && (input === initial || input === '')) {
39
- return blinker(initial[0]) + style(initial.slice(1));
40
- }
41
-
42
- initial = utils.isPrimitive(initial) ? `${initial}` : '';
43
- input = utils.isPrimitive(input) ? `${input}` : '';
44
-
45
- let placeholder = initial && initial.startsWith(input) && initial !== input;
46
- let cursor = placeholder ? blinker(initial[input.length]) : reverse;
47
-
48
- if (pos !== input.length && showCursor === true) {
49
- output = input.slice(0, pos) + blinker(input[pos]) + input.slice(pos + 1);
50
- cursor = '';
51
- }
52
-
53
- if (showCursor === false) {
54
- cursor = '';
55
- }
56
-
57
- if (placeholder) {
58
- let raw = prompt.styles.unstyle(output + cursor);
59
- return output + cursor + style(initial.slice(raw.length));
60
- }
61
-
62
- return output + cursor;
63
- };