Set module: es2015 in tsconfig.json

Changelog-entry: Set module: es2015 in tsconfig.json
Change-type: patch
This commit is contained in:
Alexis Svinartchouk 2020-08-04 16:17:20 +02:00
parent 281f119456
commit a3322e9fd7
21 changed files with 177 additions and 143 deletions

View File

@ -16,7 +16,7 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex } from 'rendition';
import { v4 as uuidV4 } from 'uuid'; import { v4 as uuidV4 } from 'uuid';
import * as flashState from '../../models/flash-state'; import * as flashState from '../../models/flash-state';

View File

@ -19,8 +19,7 @@ import CheckCircleSvg from '@fortawesome/fontawesome-free/svgs/solid/check-circl
import * as _ from 'lodash'; import * as _ from 'lodash';
import outdent from 'outdent'; import outdent from 'outdent';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex, Txt } from 'rendition';
import Txt from 'rendition/dist_esm5/components/Txt';
import { progress } from '../../../../shared/messages'; import { progress } from '../../../../shared/messages';
import { bytesToMegabytes } from '../../../../shared/units'; import { bytesToMegabytes } from '../../../../shared/units';

View File

@ -15,10 +15,7 @@
*/ */
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex, Button, ProgressBar, Txt } from 'rendition';
import Button from 'rendition/dist_esm5/components/Button';
import ProgressBar from 'rendition/dist_esm5/components/ProgressBar';
import Txt from 'rendition/dist_esm5/components/Txt';
import { default as styled } from 'styled-components'; import { default as styled } from 'styled-components';
import { fromFlashState } from '../../modules/progress-status'; import { fromFlashState } from '../../modules/progress-status';

View File

@ -15,8 +15,7 @@
*/ */
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex, Txt } from 'rendition';
import Txt from 'rendition/dist_esm5/components/Txt';
import DriveSvg from '../../../assets/drive.svg'; import DriveSvg from '../../../assets/drive.svg';
import ImageSvg from '../../../assets/image.svg'; import ImageSvg from '../../../assets/image.svg';

View File

@ -18,9 +18,7 @@ import GithubSvg from '@fortawesome/fontawesome-free/svgs/brands/github.svg';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as os from 'os'; import * as os from 'os';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex, Checkbox, Txt } from 'rendition';
import Checkbox from 'rendition/dist_esm5/components/Checkbox';
import Txt from 'rendition/dist_esm5/components/Txt';
import { version, packageType } from '../../../../../package.json'; import { version, packageType } from '../../../../../package.json';
import * as settings from '../../models/settings'; import * as settings from '../../models/settings';

View File

@ -23,12 +23,14 @@ import * as _ from 'lodash';
import { GPTPartition, MBRPartition } from 'partitioninfo'; import { GPTPartition, MBRPartition } from 'partitioninfo';
import * as path from 'path'; import * as path from 'path';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import {
import { ButtonProps } from 'rendition/dist_esm5/components/Button'; Flex,
import SmallModal from 'rendition/dist_esm5/components/Modal'; ButtonProps,
import Txt from 'rendition/dist_esm5/components/Txt'; Modal as SmallModal,
import BaseCard from 'rendition/dist_esm5/components/Card'; Txt,
import Input from 'rendition/dist_esm5/components/Input'; Card as BaseCard,
Input,
} from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import * as errors from '../../../../shared/errors'; import * as errors from '../../../../shared/errors';

View File

@ -17,8 +17,7 @@
import ExclamationTriangleSvg from '@fortawesome/fontawesome-free/svgs/solid/exclamation-triangle.svg'; import ExclamationTriangleSvg from '@fortawesome/fontawesome-free/svgs/solid/exclamation-triangle.svg';
import { Drive as DrivelistDrive } from 'drivelist'; import { Drive as DrivelistDrive } from 'drivelist';
import * as React from 'react'; import * as React from 'react';
import { Flex, FlexProps } from 'rendition/dist_esm5/components/Flex'; import { Flex, FlexProps, Txt } from 'rendition';
import Txt from 'rendition/dist_esm5/components/Txt';
import { import {
getDriveImageCompatibilityStatuses, getDriveImageCompatibilityStatuses,

View File

@ -18,12 +18,15 @@ import ExclamationTriangleSvg from '@fortawesome/fontawesome-free/svgs/solid/exc
import ChevronDownSvg from '@fortawesome/fontawesome-free/svgs/solid/chevron-down.svg'; import ChevronDownSvg from '@fortawesome/fontawesome-free/svgs/solid/chevron-down.svg';
import { scanner, sourceDestination } from 'etcher-sdk'; import { scanner, sourceDestination } from 'etcher-sdk';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import {
import { ModalProps } from 'rendition/dist_esm5/components/Modal'; Flex,
import Txt from 'rendition/dist_esm5/components/Txt'; ModalProps,
import Badge from 'rendition/dist_esm5/components/Badge'; Txt,
import Link from 'rendition/dist_esm5/components/Link'; Badge,
import Table, { TableColumn } from 'rendition/dist_esm5/components/Table'; Link,
Table,
TableColumn,
} from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import { import {

View File

@ -86,8 +86,7 @@ const settings = _.cloneDeep(DEFAULT_SETTINGS);
async function load(): Promise<void> { async function load(): Promise<void> {
debug('load'); debug('load');
// Use exports.readAll() so it can be mocked in tests const loadedSettings = await readAll();
const loadedSettings = await exports.readAll();
_.assign(settings, loadedSettings); _.assign(settings, loadedSettings);
} }

View File

@ -136,16 +136,13 @@ interface FlashResults {
/** /**
* @summary Perform write operation * @summary Perform write operation
*
* @description
* This function is extracted for testing purposes.
*/ */
export async function performWrite( async function performWrite(
image: string, image: string,
drives: DrivelistDrive[], drives: DrivelistDrive[],
onProgress: sdk.multiWrite.OnProgressFunction, onProgress: sdk.multiWrite.OnProgressFunction,
source: SourceOptions, source: SourceOptions,
): Promise<{ cancelled?: boolean }> { ): Promise<FlashResults> {
let cancelled = false; let cancelled = false;
ipc.serve(); ipc.serve();
const { const {
@ -264,6 +261,8 @@ export async function flash(
image: string, image: string,
drives: DrivelistDrive[], drives: DrivelistDrive[],
source: SourceOptions, source: SourceOptions,
// This function is a parameter so it can be mocked in tests
write = performWrite,
): Promise<void> { ): Promise<void> {
if (flashState.isFlashing()) { if (flashState.isFlashing()) {
throw new Error('There is already a flash in progress'); throw new Error('There is already a flash in progress');
@ -288,8 +287,7 @@ export async function flash(
analytics.logEvent('Flash', analyticsData); analytics.logEvent('Flash', analyticsData);
try { try {
// Using it from exports so it can be mocked during tests const result = await write(
const result = await exports.performWrite(
image, image,
drives, drives,
flashState.setProgressState, flashState.setProgressState,

View File

@ -50,9 +50,9 @@ export const currentWindow = electron.remote.getCurrentWindow();
*/ */
export function set(state: FlashState) { export function set(state: FlashState) {
if (state.percentage != null) { if (state.percentage != null) {
exports.currentWindow.setProgressBar(percentageToFloat(state.percentage)); currentWindow.setProgressBar(percentageToFloat(state.percentage));
} }
exports.currentWindow.setTitle(getWindowTitle(state)); currentWindow.setTitle(getWindowTitle(state));
} }
/** /**
@ -60,6 +60,6 @@ export function set(state: FlashState) {
*/ */
export function clear() { export function clear() {
// Passing 0 or null/undefined doesn't work. // Passing 0 or null/undefined doesn't work.
exports.currentWindow.setProgressBar(-1); currentWindow.setProgressBar(-1);
exports.currentWindow.setTitle(getWindowTitle(undefined)); currentWindow.setTitle(getWindowTitle(undefined));
} }

View File

@ -31,8 +31,7 @@ const execAsync = promisify(exec);
/** /**
* @summary Returns wmic's output for network drives * @summary Returns wmic's output for network drives
*/ */
export async function getWmicNetworkDrivesOutput(): Promise<string> { async function getWmicNetworkDrivesOutput(): Promise<string> {
// Exported for tests.
// When trying to read wmic's stdout directly from node, it is encoded with the current // When trying to read wmic's stdout directly from node, it is encoded with the current
// console codepage (depending on the computer). // console codepage (depending on the computer).
// Decoding this would require getting this codepage somehow and using iconv as node // Decoding this would require getting this codepage somehow and using iconv as node
@ -66,9 +65,10 @@ export async function getWmicNetworkDrivesOutput(): Promise<string> {
/** /**
* @summary returns a Map of drive letter -> network locations on Windows: 'Z:' -> '\\\\192.168.0.1\\Public' * @summary returns a Map of drive letter -> network locations on Windows: 'Z:' -> '\\\\192.168.0.1\\Public'
*/ */
async function getWindowsNetworkDrives(): Promise<Map<string, string>> { async function getWindowsNetworkDrives(
// Use getWindowsNetworkDrives from "exports." so it can be mocked in tests getWmicOutput: () => Promise<string>,
const result = await exports.getWmicNetworkDrivesOutput(); ): Promise<Map<string, string>> {
const result = await getWmicOutput();
const couples: Array<[string, string]> = chain(result) const couples: Array<[string, string]> = chain(result)
.split('\n') .split('\n')
// Remove header line // Remove header line
@ -97,13 +97,15 @@ async function getWindowsNetworkDrives(): Promise<Map<string, string>> {
*/ */
export async function replaceWindowsNetworkDriveLetter( export async function replaceWindowsNetworkDriveLetter(
filePath: string, filePath: string,
// getWmicOutput is a parameter so it can be replaced in tests
getWmicOutput = getWmicNetworkDrivesOutput,
): Promise<string> { ): Promise<string> {
let result = filePath; let result = filePath;
if (platform() === 'win32') { if (platform() === 'win32') {
const matches = /^([A-Z]+:)\\(.*)$/.exec(filePath); const matches = /^([A-Z]+:)\\(.*)$/.exec(filePath);
if (matches !== null) { if (matches !== null) {
const [, drive, relativePath] = matches; const [, drive, relativePath] = matches;
const drives = await getWindowsNetworkDrives(); const drives = await getWindowsNetworkDrives(getWmicOutput);
const location = drives.get(drive); const location = drives.get(drive);
if (location !== undefined) { if (location !== undefined) {
result = `${location}\\${relativePath}`; result = `${location}\\${relativePath}`;

View File

@ -16,7 +16,7 @@
import { scanner } from 'etcher-sdk'; import { scanner } from 'etcher-sdk';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex } from 'rendition';
import { TargetSelector } from '../../components/target-selector/target-selector-button'; import { TargetSelector } from '../../components/target-selector/target-selector-button';
import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal'; import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal';
import { import {

View File

@ -18,9 +18,7 @@ import CircleSvg from '@fortawesome/fontawesome-free/svgs/solid/circle.svg';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as path from 'path'; import * as path from 'path';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex, Modal, Txt } from 'rendition';
import Modal from 'rendition/dist_esm5/components/Modal';
import Txt from 'rendition/dist_esm5/components/Txt';
import * as constraints from '../../../../shared/drive-constraints'; import * as constraints from '../../../../shared/drive-constraints';
import * as messages from '../../../../shared/messages'; import * as messages from '../../../../shared/messages';

View File

@ -21,7 +21,7 @@ import { sourceDestination } from 'etcher-sdk';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as path from 'path'; import * as path from 'path';
import * as React from 'react'; import * as React from 'react';
import { Flex } from 'rendition/dist_esm5/components/Flex'; import { Flex } from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import { FeaturedProject } from '../../components/featured-project/featured-project'; import { FeaturedProject } from '../../components/featured-project/featured-project';

View File

@ -15,12 +15,16 @@
*/ */
import * as React from 'react'; import * as React from 'react';
import { Flex, FlexProps } from 'rendition/dist_esm5/components/Flex'; import {
import Button, { ButtonProps } from 'rendition/dist_esm5/components/Button'; Flex,
import ModalBase from 'rendition/dist_esm5/components/Modal'; FlexProps,
import Provider from 'rendition/dist_esm5/components/Provider'; Button,
import Txt from 'rendition/dist_esm5/components/Txt'; ButtonProps,
import renditionTheme from 'rendition/dist_esm5/theme'; Modal as ModalBase,
Provider,
Txt,
Theme as renditionTheme,
} from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import { space } from 'styled-system'; import { space } from 'styled-system';

View File

@ -17,7 +17,6 @@
import { expect } from 'chai'; import { expect } from 'chai';
import { Drive as DrivelistDrive } from 'drivelist'; import { Drive as DrivelistDrive } from 'drivelist';
import { sourceDestination } from 'etcher-sdk'; import { sourceDestination } from 'etcher-sdk';
import * as _ from 'lodash';
import * as ipc from 'node-ipc'; import * as ipc from 'node-ipc';
import { assert, SinonStub, stub } from 'sinon'; import { assert, SinonStub, stub } from 'sinon';
@ -39,7 +38,7 @@ describe('Browser: imageWriter', () => {
let performWriteStub: SinonStub; let performWriteStub: SinonStub;
beforeEach(() => { beforeEach(() => {
performWriteStub = stub(imageWriter, 'performWrite'); performWriteStub = stub();
performWriteStub.returns( performWriteStub.returns(
Promise.resolve({ Promise.resolve({
cancelled: false, cancelled: false,
@ -49,52 +48,56 @@ describe('Browser: imageWriter', () => {
}); });
afterEach(() => { afterEach(() => {
performWriteStub.restore(); performWriteStub.reset();
}); });
it('should set flashing to false when done', () => { it('should set flashing to false when done', async () => {
flashState.unsetFlashingFlag({ flashState.unsetFlashingFlag({
cancelled: false, cancelled: false,
sourceChecksum: '1234', sourceChecksum: '1234',
}); });
imageWriter.flash(imagePath, [fakeDrive], sourceOptions).finally(() => { try {
expect(flashState.isFlashing()).to.be.false; await imageWriter.flash(
});
});
it('should prevent writing more than once', () => {
flashState.unsetFlashingFlag({
cancelled: false,
sourceChecksum: '1234',
});
const writing = imageWriter.flash(
imagePath, imagePath,
[fakeDrive], [fakeDrive],
sourceOptions, sourceOptions,
performWriteStub,
); );
imageWriter.flash(imagePath, [fakeDrive], sourceOptions).catch(_.noop); } catch {
writing.finally(() => { // noop
assert.calledOnce(performWriteStub); } finally {
}); expect(flashState.isFlashing()).to.be.false;
}
}); });
it('should reject the second flash attempt', () => { it('should prevent writing more than once', async () => {
imageWriter.flash(imagePath, [fakeDrive], sourceOptions); flashState.unsetFlashingFlag({
cancelled: false,
sourceChecksum: '1234',
});
let rejectError: Error; try {
imageWriter await Promise.all([
.flash(imagePath, [fakeDrive], sourceOptions) imageWriter.flash(
.catch((error) => { imagePath,
rejectError = error; [fakeDrive],
}) sourceOptions,
.finally(() => { performWriteStub,
expect(rejectError).to.be.an.instanceof(Error); ),
expect(rejectError!.message).to.equal( imageWriter.flash(
imagePath,
[fakeDrive],
sourceOptions,
performWriteStub,
),
]);
assert.fail('Writing twice should fail');
} catch (error) {
expect(error.message).to.equal(
'There is already a flash in progress', 'There is already a flash in progress',
); );
}); }
}); });
}); });
@ -102,51 +105,63 @@ describe('Browser: imageWriter', () => {
let performWriteStub: SinonStub; let performWriteStub: SinonStub;
beforeEach(() => { beforeEach(() => {
performWriteStub = stub(imageWriter, 'performWrite'); performWriteStub = stub();
const error: Error & { code?: string } = new Error('write error'); const error: Error & { code?: string } = new Error('write error');
error.code = 'FOO'; error.code = 'FOO';
performWriteStub.returns(Promise.reject(error)); performWriteStub.returns(Promise.reject(error));
}); });
afterEach(() => { afterEach(() => {
performWriteStub.restore(); performWriteStub.reset();
}); });
it('should set flashing to false when done', () => { it('should set flashing to false when done', async () => {
imageWriter try {
.flash(imagePath, [fakeDrive], sourceOptions) await imageWriter.flash(
.catch(_.noop) imagePath,
.finally(() => { [fakeDrive],
sourceOptions,
performWriteStub,
);
} catch {
// noop
} finally {
expect(flashState.isFlashing()).to.be.false; expect(flashState.isFlashing()).to.be.false;
}); }
}); });
it('should set the error code in the flash results', () => { it('should set the error code in the flash results', async () => {
imageWriter try {
.flash(imagePath, [fakeDrive], sourceOptions) await imageWriter.flash(
.catch(_.noop) imagePath,
.finally(() => { [fakeDrive],
sourceOptions,
performWriteStub,
);
} catch {
// noop
} finally {
const flashResults = flashState.getFlashResults(); const flashResults = flashState.getFlashResults();
expect(flashResults.errorCode).to.equal('FOO'); expect(flashResults.errorCode).to.equal('FOO');
}); }
}); });
it('should be rejected with the error', () => { it('should be rejected with the error', async () => {
flashState.unsetFlashingFlag({ flashState.unsetFlashingFlag({
cancelled: false, cancelled: false,
sourceChecksum: '1234', sourceChecksum: '1234',
}); });
try {
let rejection: Error; await imageWriter.flash(
imageWriter imagePath,
.flash(imagePath, [fakeDrive], sourceOptions) [fakeDrive],
.catch((error) => { sourceOptions,
rejection = error; performWriteStub,
}) );
.finally(() => { } catch (error) {
expect(rejection).to.be.an.instanceof(Error); expect(error).to.be.an.instanceof(Error);
expect(rejection!.message).to.equal('write error'); expect(error.message).to.equal('write error');
}); }
}); });
}); });
}); });

View File

@ -17,37 +17,34 @@
import { expect } from 'chai'; import { expect } from 'chai';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import * as os from 'os'; import * as os from 'os';
import { env } from 'process';
import { SinonStub, stub } from 'sinon'; import { SinonStub, stub } from 'sinon';
import * as wnd from '../../../lib/gui/app/os/windows-network-drives'; import * as wnd from '../../../lib/gui/app/os/windows-network-drives';
function mockGetWmicOutput() {
return fs.readFile('tests/data/wmic-output.txt', {
encoding: 'ucs2',
});
}
describe('Network drives on Windows', () => { describe('Network drives on Windows', () => {
let osPlatformStub: SinonStub; let osPlatformStub: SinonStub;
let outputStub: SinonStub;
let oldSystemRoot: string | undefined;
before(async () => { before(async () => {
osPlatformStub = stub(os, 'platform'); osPlatformStub = stub(os, 'platform');
osPlatformStub.returns('win32'); osPlatformStub.returns('win32');
const wmicOutput = await fs.readFile('tests/data/wmic-output.txt', {
encoding: 'ucs2',
});
outputStub = stub(wnd, 'getWmicNetworkDrivesOutput');
outputStub.resolves(wmicOutput);
oldSystemRoot = env.SystemRoot;
env.SystemRoot = 'C:\\Windows';
}); });
it('should parse network drive mapping on Windows', async () => { it('should parse network drive mapping on Windows', async () => {
expect( expect(
await wnd.replaceWindowsNetworkDriveLetter('Z:\\some-folder\\some-file'), await wnd.replaceWindowsNetworkDriveLetter(
'Z:\\some-folder\\some-file',
mockGetWmicOutput,
),
).to.equal('\\\\192.168.1.1\\Publicé\\some-folder\\some-file'); ).to.equal('\\\\192.168.1.1\\Publicé\\some-folder\\some-file');
}); });
after(() => { after(() => {
osPlatformStub.restore(); osPlatformStub.restore();
outputStub.restore();
env.SystemRoot = oldSystemRoot;
}); });
}); });

View File

@ -4,15 +4,7 @@
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"module": "commonjs",
"target": "es2019",
"jsx": "react", "jsx": "react",
"typeRoots": ["./node_modules/@types", "./typings"], "typeRoots": ["./node_modules/@types", "./typings"]
"importHelpers": true, }
"allowSyntheticDefaultImports": true
},
"include": [
"lib/**/*.ts",
"node_modules/electron/**/*.d.ts"
]
} }

19
tsconfig.webpack.json Normal file
View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"moduleResolution": "node",
"module": "es2015",
"target": "es2019",
"jsx": "react",
"typeRoots": ["./node_modules/@types", "./typings"],
"importHelpers": true,
"allowSyntheticDefaultImports": true
},
"include": [
"lib/**/*.ts",
"node_modules/electron/**/*.d.ts"
]
}

View File

@ -24,7 +24,11 @@ import * as path from 'path';
import { env } from 'process'; import { env } from 'process';
import * as SimpleProgressWebpackPlugin from 'simple-progress-webpack-plugin'; import * as SimpleProgressWebpackPlugin from 'simple-progress-webpack-plugin';
import * as TerserPlugin from 'terser-webpack-plugin'; import * as TerserPlugin from 'terser-webpack-plugin';
import { BannerPlugin, NormalModuleReplacementPlugin } from 'webpack'; import {
BannerPlugin,
IgnorePlugin,
NormalModuleReplacementPlugin,
} from 'webpack';
/** /**
* Don't webpack package.json as mixpanel & sentry tokens * Don't webpack package.json as mixpanel & sentry tokens
@ -135,7 +139,14 @@ const commonConfig = {
}, },
{ {
test: /\.tsx?$/, test: /\.tsx?$/,
use: 'ts-loader', use: [
{
loader: 'ts-loader',
options: {
configFile: 'tsconfig.webpack.json',
},
},
],
}, },
// don't import WeakMap polyfill in deep-map-keys (required in corvus) // don't import WeakMap polyfill in deep-map-keys (required in corvus)
replace(/node_modules\/deep-map-keys\/lib\/deep-map-keys\.js$/, { replace(/node_modules\/deep-map-keys\/lib\/deep-map-keys\.js$/, {
@ -237,6 +248,8 @@ const commonConfig = {
extensions: ['.node', '.js', '.json', '.ts', '.tsx'], extensions: ['.node', '.js', '.json', '.ts', '.tsx'],
}, },
plugins: [ plugins: [
// Rendition imports highlight.js default.css file, we don't need it
new IgnorePlugin({ resourceRegExp: /\.css$/ }),
new SimpleProgressWebpackPlugin({ new SimpleProgressWebpackPlugin({
format: process.env.WEBPACK_PROGRESS || 'verbose', format: process.env.WEBPACK_PROGRESS || 'verbose',
}), }),