forked from victorb/trymodule
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.ts
More file actions
executable file
·114 lines (99 loc) · 3.77 KB
/
cli.ts
File metadata and controls
executable file
·114 lines (99 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#! /usr/bin/env node
import repl from 'node:repl';
import path from 'node:path';
import os from 'node:os';
import vm from 'node:vm';
import {exec} from 'node:child_process';
import process from 'node:process';
import chalk from 'chalk';
import logSymbol from 'log-symbols';
import isPromiseLike from 'is-promise';
import reserved from './reserved.js';
import {isPromise} from './utils.js';
import replHistory from './repl-history.js';
import loadPackages from './index.js';
import type {PackageInfo} from './index.js';
const TRYMODULE_PATH = process.env['TRYMODULE_PATH'] ?? path.resolve((os.homedir()), '.trymodule');
const TRYMODULE_HISTORY_PATH = process.env['TRYMODULE_HISTORY_PATH'] ?? path.resolve(TRYMODULE_PATH, 'repl_history');
const flags: string[] = [];
const packages: Record<string, string> = {}; // Data looks like [moduleName, as]
const makeVariableFriendly = (string_: string) => string_.replace(/-|\./g, '_');
for (const arg of process.argv.slice(2)) {
if (arg.startsWith('-')) {
// Matches '--clear', etc
flags.push(arg);
} else if (arg.includes('=')) {
// Matches 'lodash=_', etc
const i = arg.indexOf('=');
const module = arg.slice(0, i); // 'lodash'
const as = arg.slice(i + 1); // '_'
packages[module] = makeVariableFriendly(as); // ['lodash', '_']
} else {
// Assume it's just a regular module name: 'lodash', 'express', etc
packages[arg] = makeVariableFriendly(arg); // Call it the module's name
}
}
if (flags.length === 0 && Object.keys(packages).length === 0) {
throw new Error(`${logSymbol.error} You need to provide some arguments!`);
}
const logGreen = (message: string) => {
console.log(chalk.green(message));
};
const hasFlag = (flag: string) => flags.includes(flag);
const addPackageToObject = (object: Record<string, any>, pkg: PackageInfo) => {
const as = reserved.includes(pkg.as) ? `_${pkg.as}` : pkg.as;
logGreen(`${logSymbol.info} Package '${pkg.name}@${pkg.version}' was loaded and assigned to '${as}' in the current scope`);
object[as] = pkg.package;
return object;
};
if (hasFlag('--clear')) {
console.log(`${logSymbol.info} Removing folder ${TRYMODULE_PATH + '/node_modules'}`);
exec('rm -r ' + TRYMODULE_PATH + '/node_modules', (error, _stdout, _stderr) => {
if (!error) {
logGreen(`${logSymbol.info} Cache successfully cleared!`);
process.exit(0);
} else {
throw new Error(`${logSymbol.error} Could not remove cache! Error ${error.message}`);
}
});
} else {
logGreen(`${logSymbol.info} Gonna start a REPL with packages installed and loaded for you`);
// Extract
loadPackages(packages, TRYMODULE_PATH).then(packages => {
const contextPackages = packages.reduce((context, pkg) => addPackageToObject(context, pkg), {});
console.log(`${logSymbol.info} REPL started...`);
if (!process.env['TRYMODULE_NONINTERACTIVE']) {
const replServer = repl.start({
prompt: '> ',
replMode: repl.REPL_MODE_SLOPPY,
preview: true,
eval: (cmd: string, _context, _filename, callback) => {
const script = new vm.Script(cmd);
const result = script.runInContext(Object.assign(replServer.context, contextPackages), {
displayErrors: false,
breakOnSigint: true,
});
// Some libraries use non-native Promise implementations
// (ie lib$es6$promise$promise$$Promise)
if (isPromiseLike(result)) {
console.log(`${logSymbol.info} Returned a Promise. waiting for result...`);
if (isPromise(result)) {
result.then((value: any) => {
callback(null, value);
}).catch((error: any) => {
callback(error, undefined);
});
} else {
void result.then((value: any) => {
callback(null, value);
});
}
} else {
callback(null, result);
}
},
});
replHistory(replServer, TRYMODULE_HISTORY_PATH);
}
}).catch(console.error);
}