UNPKG

5.34 kBJavaScriptView Raw
1'use strict';
2
3// The adapter includes typings for the lowest supported NodeJS version.
4// This script updates them to the installed version
5
6const { spawn } = require('child_process');
7const semver = require('semver');
8const installedNodeVersion = semver.coerce(process.versions.node).major;
9
10function fail(reason) {
11 console.error('Could not install NodeJS typings. This is not critical.');
12 console.error('Reason: \n' + reason);
13 // This is not critical!
14 process.exit(0);
15}
16
17// Find latest version on npm
18console.log('Installing NodeJS typings...');
19npmCommand('view', ['@types/node', 'version'], {stdout: 'pipe', stderr: 'pipe'})
20 .then(cmdResult => {
21 if (cmdResult.exitCode !== 0) {
22 return fail(cmdResult.stderr);
23 }
24 const latestVersion = semver.coerce(cmdResult.stdout).major;
25 console.log(`latest @types: ${latestVersion}, installed node: ${installedNodeVersion}`);
26 return semver.gt(`${installedNodeVersion}.0.0`, `${latestVersion}.0.0`)
27 ? 'latest' // The installed version is too new, install latest
28 : installedNodeVersion.toString()
29 ;
30 })
31 .then(targetVersion => {
32 // Install the desired version
33 return npmCommand('i', [`@types/node@${targetVersion}`], {stdout: 'ignore', stderr: 'pipe'});
34 })
35 .then(cmdResult => {
36 if (cmdResult.exitCode !== 0) {
37 return fail(cmdResult.stderr);
38 } else {
39 process.exit(0);
40 }
41 });
42
43// TODO: the following code is copied from a js-controller fork
44// It should be moved to the core and referenced from there in a future version
45
46/**
47 * @typedef {object} NpmCommandOptions
48 * @property {string} cwd The directory to execute the command in
49 * @property {NodeJS.ReadStream} stdin Where to redirect the stdin. Default: process.stdin
50 * @property {NodeJS.WriteStream | "pipe" | "ignore"} stdout A write stream to redirect the stdout, "ignore" to ignore it or "pipe" to return it as a string. Default: process.stdout
51 * @property {NodeJS.WriteStream | "pipe" | "ignore"} stderr A write stream to redirect the stderr, "ignore" to ignore it or "pipe" to return it as a string. Default: process.stderr
52 */
53
54/**
55 * @typedef {object} NpmCommandResult
56 * @property {number} exitCode - The exit code of the spawned process
57 * @property {string?} signal - The signal the process received before termination
58 * @property {string?} stdout - If options.stdout was set to "buffer", this contains the stdout of the spawned process
59 * @property {string?} stderr - If options.stderr was set to "buffer", this contains the stderr of the spawned process
60 */
61
62/**
63 * Executes an npm command (e.g. install) and returns the exit code and (if requested) the stdout
64 * @param {string} command The npm command to execute
65 * @param {string[]} [npmArgs] The command line arguments for the npm command
66 * @param {Partial<NpmCommandOptions>} [options] (optional) Some options for the command execution
67 * @returns {Promise<NpmCommandResult>}
68 */
69function npmCommand(command, npmArgs, options) {
70 if (typeof npmArgs === 'object' && !Array.isArray(npmArgs)) {
71 // no args were given
72 options = npmArgs;
73 npmArgs = undefined;
74 }
75 if (options == null) options = {};
76 if (npmArgs == null) npmArgs = [];
77
78 const npmBinary = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
79 /** @type {import("child_process").SpawnOptions} */
80 const spawnOptions = {
81 stdio: [
82 options.stdin || process.stdin,
83 options.stdout || process.stdout,
84 options.stderr || process.stderr,
85 ],
86 // @ts-ignore This option exists starting with NodeJS 8
87 windowsHide: true,
88 };
89 if (options.cwd != null) spawnOptions.cwd = options.cwd;
90
91 // Now execute the npm process and avoid throwing errors
92 return new Promise((resolve) => {
93 try {
94 /** @type {string} */
95 let bufferedStdout;
96 /** @type {string} */
97 let bufferedStderr;
98 const cmd = spawn(npmBinary, [command].concat(npmArgs), spawnOptions)
99 .on('close', (code, signal) => {
100 resolve({
101 exitCode: code,
102 signal,
103 stdout: bufferedStdout,
104 stderr: bufferedStderr
105 });
106 });
107 // Capture stdout/stderr if requested
108 if (options.stdout === 'pipe') {
109 bufferedStdout = '';
110 cmd.stdout.on('data', chunk => {
111 const buffer = Buffer.isBuffer(chunk)
112 ? chunk
113 : new Buffer(chunk, 'utf8')
114 ;
115 bufferedStdout += buffer;
116 });
117 }
118 if (options.stderr === 'pipe') {
119 bufferedStderr = '';
120 cmd.stderr.on('data', chunk => {
121 const buffer = Buffer.isBuffer(chunk)
122 ? chunk
123 : new Buffer(chunk, 'utf8')
124 ;
125 bufferedStderr += buffer;
126 });
127 }
128 } catch (e) {
129 // doesn't matter, we return the exit code in the "close" handler
130 }
131 });
132}