mepcli 0.6.1 → 1.0.0-beta.2
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/LICENSE +21 -21
- package/README.md +512 -326
- package/dist/ansi.d.ts +8 -0
- package/dist/ansi.js +8 -0
- package/dist/base.d.ts +21 -0
- package/dist/base.js +57 -0
- package/dist/core.d.ts +48 -1
- package/dist/core.js +156 -0
- package/dist/data/licenses.d.ts +2 -0
- package/dist/data/licenses.js +109 -0
- package/dist/highlight.js +58 -26
- package/dist/index.d.ts +36 -0
- package/dist/index.js +36 -0
- package/dist/input.js +0 -3
- package/dist/prompts/box.d.ts +21 -0
- package/dist/prompts/box.js +192 -0
- package/dist/prompts/breadcrumb.d.ts +22 -0
- package/dist/prompts/breadcrumb.js +302 -0
- package/dist/prompts/byte.d.ts +13 -0
- package/dist/prompts/byte.js +159 -0
- package/dist/prompts/calculator.d.ts +16 -0
- package/dist/prompts/calculator.js +213 -0
- package/dist/prompts/calendar.js +0 -5
- package/dist/prompts/code.d.ts +2 -0
- package/dist/prompts/code.js +104 -70
- package/dist/prompts/connection-string.d.ts +18 -0
- package/dist/prompts/connection-string.js +97 -0
- package/dist/prompts/curl.d.ts +39 -0
- package/dist/prompts/curl.js +285 -0
- package/dist/prompts/data-inspector.d.ts +22 -0
- package/dist/prompts/data-inspector.js +256 -0
- package/dist/prompts/dependency.d.ts +16 -0
- package/dist/prompts/dependency.js +265 -0
- package/dist/prompts/dial.d.ts +10 -0
- package/dist/prompts/dial.js +110 -0
- package/dist/prompts/diff.d.ts +10 -0
- package/dist/prompts/diff.js +101 -0
- package/dist/prompts/draw.d.ts +20 -0
- package/dist/prompts/draw.js +188 -0
- package/dist/prompts/editor.js +0 -4
- package/dist/prompts/emoji.d.ts +18 -0
- package/dist/prompts/emoji.js +228 -0
- package/dist/prompts/exec.d.ts +13 -0
- package/dist/prompts/exec.js +83 -0
- package/dist/prompts/fuzzy.d.ts +12 -0
- package/dist/prompts/fuzzy.js +136 -0
- package/dist/prompts/gauge.d.ts +21 -0
- package/dist/prompts/gauge.js +130 -0
- package/dist/prompts/heatmap.d.ts +13 -0
- package/dist/prompts/heatmap.js +141 -0
- package/dist/prompts/ip.d.ts +11 -0
- package/dist/prompts/ip.js +118 -0
- package/dist/prompts/kanban.d.ts +17 -0
- package/dist/prompts/kanban.js +228 -0
- package/dist/prompts/keypress.js +0 -2
- package/dist/prompts/license.d.ts +9 -0
- package/dist/prompts/license.js +105 -0
- package/dist/prompts/map.d.ts +15 -0
- package/dist/prompts/map.js +199 -0
- package/dist/prompts/match.d.ts +19 -0
- package/dist/prompts/match.js +275 -0
- package/dist/prompts/miller.d.ts +15 -0
- package/dist/prompts/miller.js +221 -0
- package/dist/prompts/multi-column-select.d.ts +10 -0
- package/dist/prompts/multi-column-select.js +166 -0
- package/dist/prompts/number.js +0 -2
- package/dist/prompts/otp.d.ts +10 -0
- package/dist/prompts/otp.js +91 -0
- package/dist/prompts/pattern.d.ts +22 -0
- package/dist/prompts/pattern.js +249 -0
- package/dist/prompts/quiz-select.d.ts +10 -0
- package/dist/prompts/quiz-select.js +104 -0
- package/dist/prompts/quiz-text.d.ts +11 -0
- package/dist/prompts/quiz-text.js +82 -0
- package/dist/prompts/regex.d.ts +13 -0
- package/dist/prompts/regex.js +131 -0
- package/dist/prompts/region.d.ts +11 -0
- package/dist/prompts/region.js +164 -0
- package/dist/prompts/schedule.d.ts +18 -0
- package/dist/prompts/schedule.js +221 -0
- package/dist/prompts/scroll.d.ts +13 -0
- package/dist/prompts/scroll.js +152 -0
- package/dist/prompts/seat.d.ts +17 -0
- package/dist/prompts/seat.js +165 -0
- package/dist/prompts/select-range.d.ts +8 -0
- package/dist/prompts/select-range.js +136 -0
- package/dist/prompts/select.d.ts +9 -9
- package/dist/prompts/semver.d.ts +6 -0
- package/dist/prompts/semver.js +32 -0
- package/dist/prompts/shortcut.d.ts +9 -0
- package/dist/prompts/shortcut.js +135 -0
- package/dist/prompts/slot.d.ts +16 -0
- package/dist/prompts/slot.js +107 -0
- package/dist/prompts/snippet.js +0 -3
- package/dist/prompts/sort-grid.d.ts +16 -0
- package/dist/prompts/sort-grid.js +146 -0
- package/dist/prompts/sort.js +0 -1
- package/dist/prompts/spreadsheet.d.ts +21 -0
- package/dist/prompts/spreadsheet.js +239 -0
- package/dist/prompts/text.d.ts +9 -7
- package/dist/prompts/text.js +52 -0
- package/dist/prompts/time.d.ts +12 -0
- package/dist/prompts/time.js +202 -0
- package/dist/prompts/tree-select.d.ts +0 -1
- package/dist/prompts/tree-select.js +1 -5
- package/dist/symbols.d.ts +12 -0
- package/dist/symbols.js +14 -2
- package/dist/theme.js +10 -1
- package/dist/types.d.ts +264 -1
- package/dist/utils.d.ts +53 -0
- package/dist/utils.js +252 -0
- package/package.json +51 -47
- package/example.ts +0 -390
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ConnectionStringOptions {
|
|
2
|
+
message: string;
|
|
3
|
+
protocols?: string[];
|
|
4
|
+
defaults?: Record<string, number>;
|
|
5
|
+
}
|
|
6
|
+
export interface ConnectionStringResult {
|
|
7
|
+
raw: string;
|
|
8
|
+
parts: {
|
|
9
|
+
protocol: string;
|
|
10
|
+
host?: string;
|
|
11
|
+
port?: number;
|
|
12
|
+
user?: string;
|
|
13
|
+
password?: string;
|
|
14
|
+
database?: string;
|
|
15
|
+
filePath?: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare function connectionString(options: ConnectionStringOptions): Promise<ConnectionStringResult>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectionString = connectionString;
|
|
4
|
+
const select_1 = require("./select");
|
|
5
|
+
const text_1 = require("./text");
|
|
6
|
+
const number_1 = require("./number");
|
|
7
|
+
const confirm_1 = require("./confirm");
|
|
8
|
+
const file_1 = require("./file");
|
|
9
|
+
const DEFAULT_PROTOCOLS = ['postgres', 'mysql', 'mongodb', 'redis', 'amqp', 'sqlite'];
|
|
10
|
+
const DEFAULT_PORTS = {
|
|
11
|
+
postgres: 5432,
|
|
12
|
+
mysql: 3306,
|
|
13
|
+
mongodb: 27017,
|
|
14
|
+
redis: 6379,
|
|
15
|
+
amqp: 5672,
|
|
16
|
+
};
|
|
17
|
+
async function connectionString(options) {
|
|
18
|
+
const protocols = options.protocols || DEFAULT_PROTOCOLS;
|
|
19
|
+
const defaults = { ...DEFAULT_PORTS, ...options.defaults };
|
|
20
|
+
// 1. Protocol Selection
|
|
21
|
+
const protocol = await new select_1.SelectPrompt({
|
|
22
|
+
message: options.message,
|
|
23
|
+
choices: protocols.map(p => ({ title: p, value: p })),
|
|
24
|
+
}).run();
|
|
25
|
+
const parts = { protocol };
|
|
26
|
+
let raw = '';
|
|
27
|
+
if (protocol === 'sqlite') {
|
|
28
|
+
// SQLite: File Path
|
|
29
|
+
const filePath = await new file_1.FilePrompt({
|
|
30
|
+
message: 'Database file path',
|
|
31
|
+
}).run();
|
|
32
|
+
parts.filePath = filePath;
|
|
33
|
+
// Construct SQLite URI
|
|
34
|
+
raw = `sqlite://${filePath}`;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Network Database
|
|
38
|
+
// 2. Host
|
|
39
|
+
const host = await new text_1.TextPrompt({
|
|
40
|
+
message: 'Host',
|
|
41
|
+
initial: 'localhost',
|
|
42
|
+
placeholder: 'localhost',
|
|
43
|
+
}).run();
|
|
44
|
+
parts.host = host;
|
|
45
|
+
// 3. Port
|
|
46
|
+
const defaultPort = defaults[protocol];
|
|
47
|
+
const port = await new number_1.NumberPrompt({
|
|
48
|
+
message: 'Port',
|
|
49
|
+
initial: defaultPort,
|
|
50
|
+
}).run();
|
|
51
|
+
parts.port = port;
|
|
52
|
+
// 4. Auth
|
|
53
|
+
const hasAuth = await new confirm_1.ConfirmPrompt({
|
|
54
|
+
message: 'Authentication required?',
|
|
55
|
+
initial: true,
|
|
56
|
+
}).run();
|
|
57
|
+
if (hasAuth) {
|
|
58
|
+
const user = await new text_1.TextPrompt({
|
|
59
|
+
message: 'Username',
|
|
60
|
+
initial: 'root', // Common default
|
|
61
|
+
}).run();
|
|
62
|
+
parts.user = user;
|
|
63
|
+
// Use TextPrompt with empty mask for secret handling
|
|
64
|
+
const password = await new text_1.TextPrompt({
|
|
65
|
+
message: 'Password',
|
|
66
|
+
mask: '*', // Mask with asterisks
|
|
67
|
+
}).run();
|
|
68
|
+
parts.password = password;
|
|
69
|
+
}
|
|
70
|
+
// 5. Database
|
|
71
|
+
const database = await new text_1.TextPrompt({
|
|
72
|
+
message: 'Database name',
|
|
73
|
+
}).run();
|
|
74
|
+
parts.database = database;
|
|
75
|
+
// Construct URL
|
|
76
|
+
try {
|
|
77
|
+
// Use URL object for safe construction and encoding
|
|
78
|
+
const u = new URL(`${protocol}://${host}:${port}/${database}`);
|
|
79
|
+
if (parts.user)
|
|
80
|
+
u.username = parts.user;
|
|
81
|
+
if (parts.password)
|
|
82
|
+
u.password = parts.password;
|
|
83
|
+
raw = u.toString();
|
|
84
|
+
}
|
|
85
|
+
catch (_e) {
|
|
86
|
+
// Fallback manual construction with encoding
|
|
87
|
+
const userEncoded = parts.user ? encodeURIComponent(parts.user) : '';
|
|
88
|
+
const passEncoded = parts.password ? encodeURIComponent(parts.password) : '';
|
|
89
|
+
let authPart = '';
|
|
90
|
+
if (userEncoded || passEncoded) {
|
|
91
|
+
authPart = `${userEncoded}:${passEncoded}@`;
|
|
92
|
+
}
|
|
93
|
+
raw = `${protocol}://${authPart}${host}:${port}/${parts.database}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { raw, parts };
|
|
97
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
export interface CurlOptions {
|
|
3
|
+
message: string;
|
|
4
|
+
defaultMethod?: string;
|
|
5
|
+
defaultUrl?: string;
|
|
6
|
+
defaultHeaders?: Record<string, string>;
|
|
7
|
+
defaultBody?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CurlResult {
|
|
10
|
+
method: string;
|
|
11
|
+
url: string;
|
|
12
|
+
headers: Record<string, string>;
|
|
13
|
+
body?: string;
|
|
14
|
+
command: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class CurlPrompt extends Prompt<CurlResult, CurlOptions> {
|
|
17
|
+
private section;
|
|
18
|
+
private methodIndex;
|
|
19
|
+
private url;
|
|
20
|
+
private headers;
|
|
21
|
+
private body;
|
|
22
|
+
private urlCursor;
|
|
23
|
+
private lastLinesUp;
|
|
24
|
+
constructor(options: CurlOptions);
|
|
25
|
+
private get currentMethod();
|
|
26
|
+
private get hasBody();
|
|
27
|
+
/**
|
|
28
|
+
* Escape a string for safe inclusion inside a double-quoted shell argument.
|
|
29
|
+
* This escapes backslashes first, then double quotes.
|
|
30
|
+
*/
|
|
31
|
+
private shellEscapeDoubleQuoted;
|
|
32
|
+
private generateCommand;
|
|
33
|
+
protected render(firstRender: boolean): void;
|
|
34
|
+
protected handleInput(char: string, _buffer: Buffer): void;
|
|
35
|
+
private cycleSection;
|
|
36
|
+
private editHeaders;
|
|
37
|
+
private editBody;
|
|
38
|
+
private submitResult;
|
|
39
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CurlPrompt = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
const ansi_1 = require("../ansi");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
8
|
+
const map_1 = require("./map");
|
|
9
|
+
const code_1 = require("./code");
|
|
10
|
+
var Section;
|
|
11
|
+
(function (Section) {
|
|
12
|
+
Section[Section["METHOD"] = 0] = "METHOD";
|
|
13
|
+
Section[Section["URL"] = 1] = "URL";
|
|
14
|
+
Section[Section["HEADERS"] = 2] = "HEADERS";
|
|
15
|
+
Section[Section["BODY"] = 3] = "BODY";
|
|
16
|
+
})(Section || (Section = {}));
|
|
17
|
+
const METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
|
18
|
+
class CurlPrompt extends base_1.Prompt {
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super(options);
|
|
21
|
+
this.section = Section.METHOD;
|
|
22
|
+
this.methodIndex = 0;
|
|
23
|
+
this.url = '';
|
|
24
|
+
this.headers = {};
|
|
25
|
+
this.body = '';
|
|
26
|
+
// For URL input
|
|
27
|
+
this.urlCursor = 0;
|
|
28
|
+
this.lastLinesUp = 0;
|
|
29
|
+
this.warnExperimental();
|
|
30
|
+
// Initialize state
|
|
31
|
+
if (options.defaultMethod) {
|
|
32
|
+
const idx = METHODS.indexOf(options.defaultMethod.toUpperCase());
|
|
33
|
+
if (idx >= 0)
|
|
34
|
+
this.methodIndex = idx;
|
|
35
|
+
}
|
|
36
|
+
this.url = options.defaultUrl || '';
|
|
37
|
+
this.urlCursor = this.url.length;
|
|
38
|
+
this.headers = { ...options.defaultHeaders };
|
|
39
|
+
this.body = options.defaultBody || '';
|
|
40
|
+
// Auto-select URL if method is GET (default)
|
|
41
|
+
if (this.methodIndex === 0) {
|
|
42
|
+
this.section = Section.URL;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
get currentMethod() {
|
|
46
|
+
return METHODS[this.methodIndex];
|
|
47
|
+
}
|
|
48
|
+
get hasBody() {
|
|
49
|
+
return this.currentMethod !== 'GET' && this.currentMethod !== 'HEAD';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Escape a string for safe inclusion inside a double-quoted shell argument.
|
|
53
|
+
* This escapes backslashes first, then double quotes.
|
|
54
|
+
*/
|
|
55
|
+
shellEscapeDoubleQuoted(value) {
|
|
56
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
57
|
+
}
|
|
58
|
+
generateCommand() {
|
|
59
|
+
let cmd = `curl -X ${this.currentMethod}`;
|
|
60
|
+
// Headers
|
|
61
|
+
Object.entries(this.headers).forEach(([k, v]) => {
|
|
62
|
+
cmd += ` -H "${k}: ${v}"`;
|
|
63
|
+
});
|
|
64
|
+
// Body
|
|
65
|
+
if (this.hasBody && this.body) {
|
|
66
|
+
// Escape body for shell
|
|
67
|
+
const escapedBody = this.shellEscapeDoubleQuoted(this.body);
|
|
68
|
+
cmd += ` -d "${escapedBody}"`;
|
|
69
|
+
}
|
|
70
|
+
// URL
|
|
71
|
+
if (this.url) {
|
|
72
|
+
cmd += ` "${this.url}"`;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
cmd += ` "http://localhost..."`;
|
|
76
|
+
}
|
|
77
|
+
return cmd;
|
|
78
|
+
}
|
|
79
|
+
render(firstRender) {
|
|
80
|
+
if (!firstRender && this.lastLinesUp > 0) {
|
|
81
|
+
this.print(`\x1b[${this.lastLinesUp}B`);
|
|
82
|
+
}
|
|
83
|
+
this.lastLinesUp = 0;
|
|
84
|
+
let output = '';
|
|
85
|
+
// Title
|
|
86
|
+
output += `${theme_1.theme.success}? ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
87
|
+
// 1. Method
|
|
88
|
+
const methodLabel = this.section === Section.METHOD
|
|
89
|
+
? `${theme_1.theme.main}${ansi_1.ANSI.REVERSE} ${this.currentMethod} ${ansi_1.ANSI.RESET}`
|
|
90
|
+
: `${ansi_1.ANSI.BOLD}[${this.currentMethod}]${ansi_1.ANSI.RESET}`;
|
|
91
|
+
output += `\n${methodLabel}`;
|
|
92
|
+
// 2. URL
|
|
93
|
+
const urlActive = this.section === Section.URL;
|
|
94
|
+
const urlPrefix = urlActive ? `${theme_1.theme.main}${ansi_1.ANSI.BOLD} URL: ${ansi_1.ANSI.RESET}` : ` URL: `;
|
|
95
|
+
let urlDisplay = this.url;
|
|
96
|
+
if (!urlDisplay && urlActive) {
|
|
97
|
+
urlDisplay = `${theme_1.theme.muted}http://localhost:3000${ansi_1.ANSI.RESET}`;
|
|
98
|
+
}
|
|
99
|
+
// Insert cursor for URL
|
|
100
|
+
if (urlActive) {
|
|
101
|
+
const beforeCursor = urlDisplay.slice(0, this.urlCursor);
|
|
102
|
+
const atCursor = urlDisplay.slice(this.urlCursor, this.urlCursor + 1) || ' ';
|
|
103
|
+
const afterCursor = urlDisplay.slice(this.urlCursor + 1);
|
|
104
|
+
urlDisplay = `${beforeCursor}${theme_1.theme.main}${ansi_1.ANSI.UNDERLINE}${atCursor}${ansi_1.ANSI.RESET}${afterCursor}`;
|
|
105
|
+
}
|
|
106
|
+
output += `${urlPrefix}${urlDisplay}\n`;
|
|
107
|
+
// 3. Headers
|
|
108
|
+
const headersCount = Object.keys(this.headers).length;
|
|
109
|
+
const headersActive = this.section === Section.HEADERS;
|
|
110
|
+
const headersPointer = headersActive ? `${theme_1.theme.main}${symbols_1.symbols.pointer} ` : ' ';
|
|
111
|
+
const headersStyle = headersActive ? `${theme_1.theme.main}${ansi_1.ANSI.UNDERLINE}` : '';
|
|
112
|
+
output += `${headersPointer}${headersStyle}HEADERS${ansi_1.ANSI.RESET} (${headersCount} defined)\n`;
|
|
113
|
+
// 4. Body
|
|
114
|
+
if (this.hasBody) {
|
|
115
|
+
const bodyActive = this.section === Section.BODY;
|
|
116
|
+
const bodyPointer = bodyActive ? `${theme_1.theme.main}${symbols_1.symbols.pointer} ` : ' ';
|
|
117
|
+
const bodyStyle = bodyActive ? `${theme_1.theme.main}${ansi_1.ANSI.UNDERLINE}` : '';
|
|
118
|
+
let bodyPreview = '';
|
|
119
|
+
if (this.body) {
|
|
120
|
+
const oneLiner = this.body.replace(/\n/g, ' ').substring(0, 40);
|
|
121
|
+
bodyPreview = `${theme_1.theme.muted} ${oneLiner}...${ansi_1.ANSI.RESET}`;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
bodyPreview = `${theme_1.theme.muted} (empty)${ansi_1.ANSI.RESET}`;
|
|
125
|
+
}
|
|
126
|
+
output += `${bodyPointer}${bodyStyle}BODY${ansi_1.ANSI.RESET}${bodyPreview}\n`;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
output += ` ${theme_1.theme.muted}BODY (Disabled for ${this.currentMethod})${ansi_1.ANSI.RESET}\n`;
|
|
130
|
+
}
|
|
131
|
+
// Preview
|
|
132
|
+
output += `\n${ansi_1.ANSI.BOLD}Preview:${ansi_1.ANSI.RESET}\n`;
|
|
133
|
+
const cmd = this.generateCommand();
|
|
134
|
+
// Syntax highlight command (basic)
|
|
135
|
+
output += `${ansi_1.ANSI.FG_CYAN}${cmd}${ansi_1.ANSI.RESET}\n`;
|
|
136
|
+
// Instructions
|
|
137
|
+
output += `\n${theme_1.theme.muted}(Tab: Nav, Space: Toggle Method, Enter: Edit/Submit)${ansi_1.ANSI.RESET}`;
|
|
138
|
+
this.renderFrame(output);
|
|
139
|
+
// Cursor Positioning
|
|
140
|
+
if (this.section === Section.URL) {
|
|
141
|
+
const prefixLen = 6; // " URL: "
|
|
142
|
+
// We need to move cursor to (row 3, prefixLen + this.urlCursor)
|
|
143
|
+
const lines = output.split('\n');
|
|
144
|
+
const urlLineIndex = lines.findIndex(l => l.includes(' URL: '));
|
|
145
|
+
const linesFromBottom = lines.length - 1 - urlLineIndex;
|
|
146
|
+
this.print(ansi_1.ANSI.SHOW_CURSOR);
|
|
147
|
+
if (linesFromBottom > 0) {
|
|
148
|
+
this.print(`\x1b[${linesFromBottom}A`);
|
|
149
|
+
this.lastLinesUp = linesFromBottom;
|
|
150
|
+
}
|
|
151
|
+
const targetCol = prefixLen + this.urlCursor;
|
|
152
|
+
this.print(`\r\x1b[${targetCol}C`);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
this.print(ansi_1.ANSI.HIDE_CURSOR);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
handleInput(char, _buffer) {
|
|
159
|
+
// Navigation
|
|
160
|
+
if (char === '\t') {
|
|
161
|
+
this.cycleSection(1);
|
|
162
|
+
this.render(false);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (char === '\u001b[Z') { // Shift+Tab
|
|
166
|
+
this.cycleSection(-1);
|
|
167
|
+
this.render(false);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Section Specifics
|
|
171
|
+
switch (this.section) {
|
|
172
|
+
case Section.METHOD:
|
|
173
|
+
if (char === ' ' || this.isRight(char) || this.isDown(char)) {
|
|
174
|
+
this.methodIndex = (this.methodIndex + 1) % METHODS.length;
|
|
175
|
+
this.render(false);
|
|
176
|
+
}
|
|
177
|
+
else if (this.isLeft(char) || this.isUp(char)) {
|
|
178
|
+
this.methodIndex = (this.methodIndex - 1 + METHODS.length) % METHODS.length;
|
|
179
|
+
this.render(false);
|
|
180
|
+
}
|
|
181
|
+
else if (char === '\r' || char === '\n') {
|
|
182
|
+
// Enter on Method -> Submit
|
|
183
|
+
this.submitResult();
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
case Section.URL:
|
|
187
|
+
if (char === '\r' || char === '\n') {
|
|
188
|
+
this.submitResult();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// Typing
|
|
192
|
+
if (char === '\u0008' || char === '\x7f') { // Backspace
|
|
193
|
+
if (this.urlCursor > 0) {
|
|
194
|
+
this.url = this.url.slice(0, this.urlCursor - 1) + this.url.slice(this.urlCursor);
|
|
195
|
+
this.urlCursor--;
|
|
196
|
+
this.render(false);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else if (this.isLeft(char)) {
|
|
200
|
+
if (this.urlCursor > 0) {
|
|
201
|
+
this.urlCursor--;
|
|
202
|
+
this.render(false);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (this.isRight(char)) {
|
|
206
|
+
if (this.urlCursor < this.url.length) {
|
|
207
|
+
this.urlCursor++;
|
|
208
|
+
this.render(false);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else if (!/^[\x00-\x1F]/.test(char)) {
|
|
212
|
+
this.url = this.url.slice(0, this.urlCursor) + char + this.url.slice(this.urlCursor);
|
|
213
|
+
this.urlCursor += char.length;
|
|
214
|
+
this.render(false);
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
case Section.HEADERS:
|
|
218
|
+
if (char === '\r' || char === '\n') {
|
|
219
|
+
this.editHeaders();
|
|
220
|
+
}
|
|
221
|
+
break;
|
|
222
|
+
case Section.BODY:
|
|
223
|
+
if (char === '\r' || char === '\n') {
|
|
224
|
+
this.editBody();
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
cycleSection(direction) {
|
|
230
|
+
// Logic to skip disabled Body
|
|
231
|
+
let next = this.section + direction;
|
|
232
|
+
// Loop
|
|
233
|
+
if (next > Section.BODY)
|
|
234
|
+
next = Section.METHOD;
|
|
235
|
+
if (next < Section.METHOD)
|
|
236
|
+
next = Section.BODY;
|
|
237
|
+
// If Body is disabled and we landed on it
|
|
238
|
+
if (next === Section.BODY && !this.hasBody) {
|
|
239
|
+
next = direction === 1 ? Section.METHOD : Section.HEADERS;
|
|
240
|
+
}
|
|
241
|
+
this.section = next;
|
|
242
|
+
}
|
|
243
|
+
async editHeaders() {
|
|
244
|
+
this.pauseInput();
|
|
245
|
+
try {
|
|
246
|
+
const result = await new map_1.MapPrompt({
|
|
247
|
+
message: 'Edit Headers',
|
|
248
|
+
initial: this.headers,
|
|
249
|
+
}).run();
|
|
250
|
+
this.headers = result;
|
|
251
|
+
}
|
|
252
|
+
catch (_e) {
|
|
253
|
+
// Cancelled or error
|
|
254
|
+
}
|
|
255
|
+
this.resumeInput();
|
|
256
|
+
this.render(false); // Re-render our UI
|
|
257
|
+
}
|
|
258
|
+
async editBody() {
|
|
259
|
+
this.pauseInput();
|
|
260
|
+
try {
|
|
261
|
+
const result = await new code_1.CodePrompt({
|
|
262
|
+
message: 'Edit Body (JSON)',
|
|
263
|
+
template: '${json}',
|
|
264
|
+
highlight: true,
|
|
265
|
+
values: this.body ? { json: this.body } : undefined
|
|
266
|
+
}).run();
|
|
267
|
+
this.body = result;
|
|
268
|
+
}
|
|
269
|
+
catch (_e) {
|
|
270
|
+
// Cancelled
|
|
271
|
+
}
|
|
272
|
+
this.resumeInput();
|
|
273
|
+
this.render(false);
|
|
274
|
+
}
|
|
275
|
+
submitResult() {
|
|
276
|
+
this.submit({
|
|
277
|
+
method: this.currentMethod,
|
|
278
|
+
url: this.url,
|
|
279
|
+
headers: this.headers,
|
|
280
|
+
body: this.hasBody ? this.body : undefined,
|
|
281
|
+
command: this.generateCommand()
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
exports.CurlPrompt = CurlPrompt;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { DataInspectorOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class DataInspectorPrompt extends Prompt<any, DataInspectorOptions> {
|
|
4
|
+
private cursor;
|
|
5
|
+
private flatList;
|
|
6
|
+
private expandedPaths;
|
|
7
|
+
private scrollTop;
|
|
8
|
+
private readonly pageSize;
|
|
9
|
+
private editMode;
|
|
10
|
+
private editBuffer;
|
|
11
|
+
private rootData;
|
|
12
|
+
constructor(options: DataInspectorOptions);
|
|
13
|
+
private getType;
|
|
14
|
+
private recalculateFlatList;
|
|
15
|
+
private traverse;
|
|
16
|
+
private getValueColor;
|
|
17
|
+
private formatValue;
|
|
18
|
+
protected render(_firstRender: boolean): void;
|
|
19
|
+
protected handleInput(char: string, key: Buffer): void;
|
|
20
|
+
private handleEditInput;
|
|
21
|
+
protected handleMouse(event: MouseEvent): void;
|
|
22
|
+
}
|