genomic 0.0.1 → 4.0.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.
- package/LICENSE +1 -1
- package/README.md +1214 -1
- package/commander.d.ts +21 -0
- package/commander.js +57 -0
- package/esm/commander.js +50 -0
- package/esm/index.js +4 -0
- package/esm/keypress.js +95 -0
- package/esm/prompt.js +1024 -0
- package/esm/question/index.js +1 -0
- package/esm/question/types.js +1 -0
- package/esm/resolvers/date.js +11 -0
- package/esm/resolvers/git.js +26 -0
- package/esm/resolvers/index.js +103 -0
- package/esm/resolvers/npm.js +24 -0
- package/esm/resolvers/types.js +1 -0
- package/esm/resolvers/workspace.js +141 -0
- package/esm/utils.js +12 -0
- package/index.d.ts +4 -0
- package/index.js +20 -0
- package/keypress.d.ts +45 -0
- package/keypress.js +99 -0
- package/package.json +32 -64
- package/prompt.d.ts +116 -0
- package/prompt.js +1032 -0
- package/question/index.d.ts +1 -0
- package/question/index.js +17 -0
- package/question/types.d.ts +65 -0
- package/question/types.js +2 -0
- package/resolvers/date.d.ts +5 -0
- package/resolvers/date.js +14 -0
- package/resolvers/git.d.ts +11 -0
- package/resolvers/git.js +30 -0
- package/resolvers/index.d.ts +63 -0
- package/resolvers/index.js +111 -0
- package/resolvers/npm.d.ts +10 -0
- package/resolvers/npm.js +28 -0
- package/resolvers/types.d.ts +12 -0
- package/resolvers/types.js +2 -0
- package/resolvers/workspace.d.ts +6 -0
- package/resolvers/workspace.js +144 -0
- package/utils.d.ts +2 -0
- package/utils.js +16 -0
- package/main/index.js +0 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in date/time resolvers.
|
|
3
|
+
*/
|
|
4
|
+
export const dateResolvers = {
|
|
5
|
+
'date.year': () => new Date().getFullYear().toString(),
|
|
6
|
+
'date.month': () => (new Date().getMonth() + 1).toString().padStart(2, '0'),
|
|
7
|
+
'date.day': () => new Date().getDate().toString().padStart(2, '0'),
|
|
8
|
+
'date.now': () => new Date().toISOString(),
|
|
9
|
+
'date.iso': () => new Date().toISOString().split('T')[0], // YYYY-MM-DD
|
|
10
|
+
'date.timestamp': () => Date.now().toString(),
|
|
11
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves a git config value.
|
|
4
|
+
* @param key The git config key (e.g., 'user.name', 'user.email')
|
|
5
|
+
* @returns The config value as a string, or undefined if not found or error occurs
|
|
6
|
+
*/
|
|
7
|
+
export function getGitConfig(key) {
|
|
8
|
+
try {
|
|
9
|
+
const result = execSync(`git config --global ${key}`, {
|
|
10
|
+
encoding: 'utf8',
|
|
11
|
+
stdio: ['pipe', 'pipe', 'ignore'] // Suppress stderr
|
|
12
|
+
});
|
|
13
|
+
const trimmed = result.trim();
|
|
14
|
+
return trimmed || undefined; // Treat empty string as undefined
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Built-in git configuration resolvers.
|
|
22
|
+
*/
|
|
23
|
+
export const gitResolvers = {
|
|
24
|
+
'git.user.name': () => getGitConfig('user.name'),
|
|
25
|
+
'git.user.email': () => getGitConfig('user.email'),
|
|
26
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { gitResolvers } from './git';
|
|
2
|
+
import { dateResolvers } from './date';
|
|
3
|
+
import { npmResolvers } from './npm';
|
|
4
|
+
import { workspaceResolvers } from './workspace';
|
|
5
|
+
/**
|
|
6
|
+
* A registry for managing default value resolvers.
|
|
7
|
+
* Allows registration of custom resolvers and provides resolution logic.
|
|
8
|
+
*/
|
|
9
|
+
export class DefaultResolverRegistry {
|
|
10
|
+
resolvers;
|
|
11
|
+
constructor(initialResolvers = {}) {
|
|
12
|
+
this.resolvers = { ...initialResolvers };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Register a custom resolver.
|
|
16
|
+
* @param key The resolver key (e.g., 'git.user.name')
|
|
17
|
+
* @param resolver The resolver function
|
|
18
|
+
*/
|
|
19
|
+
register(key, resolver) {
|
|
20
|
+
this.resolvers[key] = resolver;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Unregister a resolver.
|
|
24
|
+
* @param key The resolver key to remove
|
|
25
|
+
*/
|
|
26
|
+
unregister(key) {
|
|
27
|
+
delete this.resolvers[key];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a key to its value.
|
|
31
|
+
* Returns undefined if the resolver doesn't exist or if it throws an error.
|
|
32
|
+
* @param key The resolver key
|
|
33
|
+
* @returns The resolved value or undefined
|
|
34
|
+
*/
|
|
35
|
+
async resolve(key) {
|
|
36
|
+
const resolver = this.resolvers[key];
|
|
37
|
+
if (!resolver) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const result = await Promise.resolve(resolver());
|
|
42
|
+
// Treat empty strings as undefined
|
|
43
|
+
return result === '' ? undefined : result;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
// Silent failure - log only in debug mode
|
|
47
|
+
if (process.env.DEBUG === 'genomic') {
|
|
48
|
+
console.error(`[genomic] Resolver '${key}' failed:`, error);
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a resolver exists for the given key.
|
|
55
|
+
* @param key The resolver key
|
|
56
|
+
* @returns True if the resolver exists
|
|
57
|
+
*/
|
|
58
|
+
has(key) {
|
|
59
|
+
return key in this.resolvers;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get all registered resolver keys.
|
|
63
|
+
* @returns Array of resolver keys
|
|
64
|
+
*/
|
|
65
|
+
keys() {
|
|
66
|
+
return Object.keys(this.resolvers);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Create a copy of this registry with all current resolvers.
|
|
70
|
+
* @returns A new DefaultResolverRegistry instance
|
|
71
|
+
*/
|
|
72
|
+
clone() {
|
|
73
|
+
return new DefaultResolverRegistry({ ...this.resolvers });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Global resolver registry instance with built-in resolvers.
|
|
78
|
+
* This is the default registry used by Prompter unless a custom one is provided.
|
|
79
|
+
*/
|
|
80
|
+
export const globalResolverRegistry = new DefaultResolverRegistry({
|
|
81
|
+
...gitResolvers,
|
|
82
|
+
...dateResolvers,
|
|
83
|
+
...npmResolvers,
|
|
84
|
+
...workspaceResolvers,
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* Convenience function to register a resolver on the global registry.
|
|
88
|
+
* @param key The resolver key
|
|
89
|
+
* @param resolver The resolver function
|
|
90
|
+
*/
|
|
91
|
+
export function registerDefaultResolver(key, resolver) {
|
|
92
|
+
globalResolverRegistry.register(key, resolver);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Convenience function to resolve a key using the global registry.
|
|
96
|
+
* @param key The resolver key
|
|
97
|
+
* @returns The resolved value or undefined
|
|
98
|
+
*/
|
|
99
|
+
export function resolveDefault(key) {
|
|
100
|
+
return globalResolverRegistry.resolve(key);
|
|
101
|
+
}
|
|
102
|
+
export { getGitConfig } from './git';
|
|
103
|
+
export { getNpmWhoami } from './npm';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves the currently logged in npm user.
|
|
4
|
+
* @returns The npm username, or undefined if not logged in or error occurs
|
|
5
|
+
*/
|
|
6
|
+
export function getNpmWhoami() {
|
|
7
|
+
try {
|
|
8
|
+
const result = execSync('npm whoami', {
|
|
9
|
+
encoding: 'utf8',
|
|
10
|
+
stdio: ['pipe', 'pipe', 'ignore'] // Suppress stderr
|
|
11
|
+
});
|
|
12
|
+
const trimmed = result.trim();
|
|
13
|
+
return trimmed || undefined; // Treat empty string as undefined
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Built-in npm resolvers.
|
|
21
|
+
*/
|
|
22
|
+
export const npmResolvers = {
|
|
23
|
+
'npm.whoami': () => getNpmWhoami(),
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { findAndRequirePackageJson } from 'find-and-require-package-json';
|
|
2
|
+
/**
|
|
3
|
+
* Find and read the nearest package.json starting from cwd.
|
|
4
|
+
* Returns undefined if not found (instead of throwing).
|
|
5
|
+
*/
|
|
6
|
+
function findPackageJsonFromCwd() {
|
|
7
|
+
try {
|
|
8
|
+
return findAndRequirePackageJson(process.cwd());
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse a GitHub URL and extract organization and repo name.
|
|
16
|
+
* Handles various formats:
|
|
17
|
+
* - https://github.com/org/repo
|
|
18
|
+
* - https://github.com/org/repo.git
|
|
19
|
+
* - git@github.com:org/repo.git
|
|
20
|
+
* - git://github.com/org/repo.git
|
|
21
|
+
*/
|
|
22
|
+
function parseGitHubUrl(url) {
|
|
23
|
+
if (!url) {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
// Handle git@github.com:org/repo.git format
|
|
27
|
+
const sshMatch = url.match(/git@github\.com:([^/]+)\/([^/.]+)(?:\.git)?/);
|
|
28
|
+
if (sshMatch) {
|
|
29
|
+
return { organization: sshMatch[1], name: sshMatch[2] };
|
|
30
|
+
}
|
|
31
|
+
// Handle https://github.com/org/repo or git://github.com/org/repo formats
|
|
32
|
+
const httpsMatch = url.match(/(?:https?|git):\/\/github\.com\/([^/]+)\/([^/.]+)(?:\.git)?/);
|
|
33
|
+
if (httpsMatch) {
|
|
34
|
+
return { organization: httpsMatch[1], name: httpsMatch[2] };
|
|
35
|
+
}
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the repository URL from package.json.
|
|
40
|
+
* Handles both string and object formats.
|
|
41
|
+
*/
|
|
42
|
+
function getRepositoryUrl(pkg) {
|
|
43
|
+
if (!pkg.repository) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
if (typeof pkg.repository === 'string') {
|
|
47
|
+
return pkg.repository;
|
|
48
|
+
}
|
|
49
|
+
return pkg.repository.url;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Parse author field which can be a string or object.
|
|
53
|
+
* String format: "Name <email> (url)" where email and url are optional
|
|
54
|
+
*/
|
|
55
|
+
function parseAuthor(author) {
|
|
56
|
+
if (!author) {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
if (typeof author === 'object') {
|
|
60
|
+
return { name: author.name, email: author.email };
|
|
61
|
+
}
|
|
62
|
+
// Parse string format: "Name <email> (url)"
|
|
63
|
+
const nameMatch = author.match(/^([^<(]+)/);
|
|
64
|
+
const emailMatch = author.match(/<([^>]+)>/);
|
|
65
|
+
return {
|
|
66
|
+
name: nameMatch ? nameMatch[1].trim() : undefined,
|
|
67
|
+
email: emailMatch ? emailMatch[1] : undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Built-in workspace resolvers.
|
|
72
|
+
* These resolve values from the nearest package.json in the current working directory.
|
|
73
|
+
*/
|
|
74
|
+
export const workspaceResolvers = {
|
|
75
|
+
'workspace.name': () => {
|
|
76
|
+
const pkg = findPackageJsonFromCwd();
|
|
77
|
+
if (!pkg)
|
|
78
|
+
return undefined;
|
|
79
|
+
const url = getRepositoryUrl(pkg);
|
|
80
|
+
// Prefer repo slug when repository is set; fall back to package name
|
|
81
|
+
if (url) {
|
|
82
|
+
const parsed = parseGitHubUrl(url);
|
|
83
|
+
if (parsed.name)
|
|
84
|
+
return parsed.name;
|
|
85
|
+
}
|
|
86
|
+
return pkg.name;
|
|
87
|
+
},
|
|
88
|
+
'workspace.repo.name': () => {
|
|
89
|
+
const pkg = findPackageJsonFromCwd();
|
|
90
|
+
if (!pkg)
|
|
91
|
+
return undefined;
|
|
92
|
+
const url = getRepositoryUrl(pkg);
|
|
93
|
+
if (!url)
|
|
94
|
+
return undefined;
|
|
95
|
+
return parseGitHubUrl(url).name;
|
|
96
|
+
},
|
|
97
|
+
'workspace.repo.organization': () => {
|
|
98
|
+
const pkg = findPackageJsonFromCwd();
|
|
99
|
+
if (!pkg)
|
|
100
|
+
return undefined;
|
|
101
|
+
const url = getRepositoryUrl(pkg);
|
|
102
|
+
if (!url)
|
|
103
|
+
return undefined;
|
|
104
|
+
return parseGitHubUrl(url).organization;
|
|
105
|
+
},
|
|
106
|
+
// Alias for repo.organization for template readability
|
|
107
|
+
'workspace.organization.name': () => {
|
|
108
|
+
const pkg = findPackageJsonFromCwd();
|
|
109
|
+
if (!pkg)
|
|
110
|
+
return undefined;
|
|
111
|
+
const url = getRepositoryUrl(pkg);
|
|
112
|
+
if (!url)
|
|
113
|
+
return undefined;
|
|
114
|
+
return parseGitHubUrl(url).organization;
|
|
115
|
+
},
|
|
116
|
+
'workspace.license': () => {
|
|
117
|
+
const pkg = findPackageJsonFromCwd();
|
|
118
|
+
return pkg?.license;
|
|
119
|
+
},
|
|
120
|
+
'workspace.author': () => {
|
|
121
|
+
const pkg = findPackageJsonFromCwd();
|
|
122
|
+
if (!pkg)
|
|
123
|
+
return undefined;
|
|
124
|
+
const parsed = parseAuthor(pkg.author);
|
|
125
|
+
return parsed.name;
|
|
126
|
+
},
|
|
127
|
+
'workspace.author.name': () => {
|
|
128
|
+
const pkg = findPackageJsonFromCwd();
|
|
129
|
+
if (!pkg)
|
|
130
|
+
return undefined;
|
|
131
|
+
const parsed = parseAuthor(pkg.author);
|
|
132
|
+
return parsed.name;
|
|
133
|
+
},
|
|
134
|
+
'workspace.author.email': () => {
|
|
135
|
+
const pkg = findPackageJsonFromCwd();
|
|
136
|
+
if (!pkg)
|
|
137
|
+
return undefined;
|
|
138
|
+
const parsed = parseAuthor(pkg.author);
|
|
139
|
+
return parsed.email;
|
|
140
|
+
},
|
|
141
|
+
};
|
package/esm/utils.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { green, blue } from 'yanse';
|
|
2
|
+
import { findAndRequirePackageJson } from 'find-and-require-package-json';
|
|
3
|
+
// Function to display the version information
|
|
4
|
+
export function displayVersion() {
|
|
5
|
+
const pkg = findAndRequirePackageJson(__dirname);
|
|
6
|
+
console.log(green(`Name: ${pkg.name}`));
|
|
7
|
+
console.log(blue(`Version: ${pkg.version}`));
|
|
8
|
+
}
|
|
9
|
+
export function getVersion() {
|
|
10
|
+
const pkg = findAndRequirePackageJson(__dirname);
|
|
11
|
+
return pkg.version;
|
|
12
|
+
}
|
package/index.d.ts
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./commander"), exports);
|
|
18
|
+
__exportStar(require("./prompt"), exports);
|
|
19
|
+
__exportStar(require("./question"), exports);
|
|
20
|
+
__exportStar(require("./resolvers"), exports);
|
package/keypress.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
type KeyHandler = () => void;
|
|
3
|
+
interface ProcessWrapper {
|
|
4
|
+
exit: (code?: number) => never;
|
|
5
|
+
}
|
|
6
|
+
export declare const KEY_CODES: {
|
|
7
|
+
UP_ARROW: string;
|
|
8
|
+
DOWN_ARROW: string;
|
|
9
|
+
RIGHT_ARROW: string;
|
|
10
|
+
LEFT_ARROW: string;
|
|
11
|
+
ENTER: string;
|
|
12
|
+
SPACE: string;
|
|
13
|
+
CTRL_C: string;
|
|
14
|
+
BACKSPACE: string;
|
|
15
|
+
BACKSPACE_LEGACY: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Handles keyboard input for interactive prompts.
|
|
19
|
+
*
|
|
20
|
+
* **Important**: Only one TerminalKeypress instance should be actively listening
|
|
21
|
+
* on a given input stream at a time. If you need multiple Prompter instances,
|
|
22
|
+
* call `close()` on the first instance before using the second, or reuse a single
|
|
23
|
+
* instance for all prompts.
|
|
24
|
+
*
|
|
25
|
+
* Multiple instances sharing the same input stream (e.g., process.stdin) will
|
|
26
|
+
* each receive all keypresses, which can cause duplicate or unexpected behavior.
|
|
27
|
+
*/
|
|
28
|
+
export declare class TerminalKeypress {
|
|
29
|
+
private listeners;
|
|
30
|
+
private active;
|
|
31
|
+
private noTty;
|
|
32
|
+
private input;
|
|
33
|
+
private proc;
|
|
34
|
+
private dataHandler;
|
|
35
|
+
constructor(noTty?: boolean, input?: Readable, proc?: ProcessWrapper);
|
|
36
|
+
isTTY(): boolean;
|
|
37
|
+
private setupListeners;
|
|
38
|
+
on(key: string, callback: KeyHandler): void;
|
|
39
|
+
off(key: string, callback: KeyHandler): void;
|
|
40
|
+
clearHandlers(): void;
|
|
41
|
+
pause(): void;
|
|
42
|
+
resume(): void;
|
|
43
|
+
destroy(): void;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
package/keypress.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TerminalKeypress = exports.KEY_CODES = void 0;
|
|
4
|
+
const defaultProcessWrapper = {
|
|
5
|
+
exit: (code) => process.exit(code)
|
|
6
|
+
};
|
|
7
|
+
exports.KEY_CODES = {
|
|
8
|
+
UP_ARROW: '\u001b[A',
|
|
9
|
+
DOWN_ARROW: '\u001b[B',
|
|
10
|
+
RIGHT_ARROW: '\u001b[C',
|
|
11
|
+
LEFT_ARROW: '\u001b[D',
|
|
12
|
+
ENTER: '\r',
|
|
13
|
+
SPACE: ' ',
|
|
14
|
+
CTRL_C: '\u0003',
|
|
15
|
+
BACKSPACE: '\x7f', // Commonly used BACKSPACE key in Unix-like systems
|
|
16
|
+
BACKSPACE_LEGACY: '\x08' // For compatibility with some systems
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Handles keyboard input for interactive prompts.
|
|
20
|
+
*
|
|
21
|
+
* **Important**: Only one TerminalKeypress instance should be actively listening
|
|
22
|
+
* on a given input stream at a time. If you need multiple Prompter instances,
|
|
23
|
+
* call `close()` on the first instance before using the second, or reuse a single
|
|
24
|
+
* instance for all prompts.
|
|
25
|
+
*
|
|
26
|
+
* Multiple instances sharing the same input stream (e.g., process.stdin) will
|
|
27
|
+
* each receive all keypresses, which can cause duplicate or unexpected behavior.
|
|
28
|
+
*/
|
|
29
|
+
class TerminalKeypress {
|
|
30
|
+
listeners = {};
|
|
31
|
+
active = true;
|
|
32
|
+
noTty;
|
|
33
|
+
input;
|
|
34
|
+
proc;
|
|
35
|
+
dataHandler = null;
|
|
36
|
+
constructor(noTty = false, input = process.stdin, proc = defaultProcessWrapper) {
|
|
37
|
+
this.noTty = noTty;
|
|
38
|
+
this.input = input;
|
|
39
|
+
this.proc = proc;
|
|
40
|
+
if (this.isTTY()) {
|
|
41
|
+
this.input.resume();
|
|
42
|
+
this.input.setEncoding('utf8');
|
|
43
|
+
}
|
|
44
|
+
this.setupListeners();
|
|
45
|
+
}
|
|
46
|
+
isTTY() {
|
|
47
|
+
return !this.noTty;
|
|
48
|
+
}
|
|
49
|
+
setupListeners() {
|
|
50
|
+
this.dataHandler = (key) => {
|
|
51
|
+
if (!this.active)
|
|
52
|
+
return;
|
|
53
|
+
const handlers = this.listeners[key];
|
|
54
|
+
handlers?.forEach(handler => handler());
|
|
55
|
+
if (key === exports.KEY_CODES.CTRL_C) {
|
|
56
|
+
this.proc.exit(0);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
this.input.on('data', this.dataHandler);
|
|
60
|
+
}
|
|
61
|
+
on(key, callback) {
|
|
62
|
+
if (!this.listeners[key]) {
|
|
63
|
+
this.listeners[key] = [];
|
|
64
|
+
}
|
|
65
|
+
this.listeners[key].push(callback);
|
|
66
|
+
}
|
|
67
|
+
off(key, callback) {
|
|
68
|
+
if (this.listeners[key]) {
|
|
69
|
+
const index = this.listeners[key].indexOf(callback);
|
|
70
|
+
if (index !== -1) {
|
|
71
|
+
this.listeners[key].splice(index, 1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
clearHandlers() {
|
|
76
|
+
this.listeners = {};
|
|
77
|
+
}
|
|
78
|
+
pause() {
|
|
79
|
+
this.active = false;
|
|
80
|
+
this.clearHandlers();
|
|
81
|
+
}
|
|
82
|
+
resume() {
|
|
83
|
+
this.active = true;
|
|
84
|
+
if (this.isTTY() && typeof this.input.setRawMode === 'function') {
|
|
85
|
+
this.input.setRawMode(true);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
destroy() {
|
|
89
|
+
if (typeof this.input.setRawMode === 'function') {
|
|
90
|
+
this.input.setRawMode(false);
|
|
91
|
+
}
|
|
92
|
+
this.input.pause();
|
|
93
|
+
if (this.dataHandler) {
|
|
94
|
+
this.input.removeListener('data', this.dataHandler);
|
|
95
|
+
this.dataHandler = null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.TerminalKeypress = TerminalKeypress;
|
package/package.json
CHANGED
|
@@ -1,77 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genomic",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"lib": "src",
|
|
12
|
-
"test": "__tests__"
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"types",
|
|
16
|
-
"main"
|
|
17
|
-
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "cross-env BABEL_ENV=production babel src --out-dir main --delete-dir-on-start --extensions \".tsx,.ts,.js\"",
|
|
20
|
-
"build:ts": "tsc --project ./tsconfig.json",
|
|
21
|
-
"prepare": "npm run build",
|
|
22
|
-
"dev": "cross-env NODE_ENV=development babel-node src/index --extensions \".tsx,.ts,.js\"",
|
|
23
|
-
"watch": "cross-env NODE_ENV=development babel-watch src/index --extensions \".tsx,.ts,.js\"",
|
|
24
|
-
"lint": "eslint .",
|
|
25
|
-
"format": "eslint --fix .",
|
|
26
|
-
"test": "jest",
|
|
27
|
-
"test:watch": "jest --watch",
|
|
28
|
-
"test:debug": "node --inspect node_modules/.bin/jest --runInBand"
|
|
29
|
-
},
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"author": "Constructive <developers@constructive.io>",
|
|
5
|
+
"description": "TypeScript-first library for building beautiful CLI interfaces with interactive prompts",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"module": "esm/index.js",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"homepage": "https://github.com/constructive-io/dev-utils",
|
|
10
|
+
"license": "MIT",
|
|
30
11
|
"publishConfig": {
|
|
31
|
-
"access": "public"
|
|
12
|
+
"access": "public",
|
|
13
|
+
"directory": "dist"
|
|
32
14
|
},
|
|
33
15
|
"repository": {
|
|
34
16
|
"type": "git",
|
|
35
|
-
"url": "https://github.com/
|
|
17
|
+
"url": "https://github.com/constructive-io/dev-utils"
|
|
36
18
|
},
|
|
37
|
-
"keywords": [],
|
|
38
19
|
"bugs": {
|
|
39
|
-
"url": "https://github.com/
|
|
20
|
+
"url": "https://github.com/constructive-io/dev-utils/issues"
|
|
40
21
|
},
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
22
|
+
"scripts": {
|
|
23
|
+
"copy": "makage assets",
|
|
24
|
+
"clean": "makage clean",
|
|
25
|
+
"prepublishOnly": "npm run build",
|
|
26
|
+
"build": "makage build",
|
|
27
|
+
"dev": "ts-node dev/index",
|
|
28
|
+
"test": "jest",
|
|
29
|
+
"test:watch": "jest --watch"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"deepmerge": "^4.3.1",
|
|
33
|
+
"find-and-require-package-json": "0.8.2",
|
|
34
|
+
"js-yaml": "^4.1.0",
|
|
35
|
+
"minimist": "^1.2.8",
|
|
36
|
+
"yanse": "0.1.8"
|
|
47
37
|
},
|
|
38
|
+
"keywords": [],
|
|
48
39
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"@babel/node": "^7.19.1",
|
|
53
|
-
"@babel/plugin-proposal-class-properties": "7.18.6",
|
|
54
|
-
"@babel/plugin-proposal-export-default-from": "7.18.10",
|
|
55
|
-
"@babel/plugin-proposal-object-rest-spread": "7.18.9",
|
|
56
|
-
"@babel/plugin-transform-runtime": "7.19.1",
|
|
57
|
-
"@babel/preset-env": "7.19.1",
|
|
58
|
-
"@babel/preset-typescript": "^7.18.6",
|
|
59
|
-
"@types/jest": "^29.0.2",
|
|
60
|
-
"babel-core": "7.0.0-bridge.0",
|
|
61
|
-
"babel-jest": "29.0.3",
|
|
62
|
-
"babel-watch": "^7.0.0",
|
|
63
|
-
"cross-env": "^7.0.2",
|
|
64
|
-
"eslint": "8.23.1",
|
|
65
|
-
"eslint-config-prettier": "^8.5.0",
|
|
66
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
67
|
-
"jest": "^29.0.3",
|
|
68
|
-
"jest-in-case": "^1.0.2",
|
|
69
|
-
"prettier": "^2.7.1",
|
|
70
|
-
"regenerator-runtime": "^0.13.7",
|
|
71
|
-
"ts-jest": "^29.0.1",
|
|
72
|
-
"typescript": "^4.8.3"
|
|
40
|
+
"@types/minimist": "^1.2.5",
|
|
41
|
+
"clean-ansi": "0.1.5",
|
|
42
|
+
"makage": "0.1.8"
|
|
73
43
|
},
|
|
74
|
-
"
|
|
75
|
-
"@babel/runtime": "^7.19.0"
|
|
76
|
-
}
|
|
44
|
+
"gitHead": "59317e6ae9ba291aebdee3098e456d4ef4e1a5dc"
|
|
77
45
|
}
|