From b5593ef5b2eaa470b71c38f1b6c6b8e3f03239bb Mon Sep 17 00:00:00 2001 From: Alexis Svinartchouk Date: Wed, 8 Jan 2020 18:31:37 +0100 Subject: [PATCH] Convert utils.js to typescript Change-type: patch --- lib/gui/app/models/store.js | 1 + lib/gui/etcher.js | 1 + lib/shared/errors.ts | 6 +- lib/shared/permissions.js | 1 + lib/shared/utils.js | 161 ------------------------------------ lib/shared/utils.ts | 97 ++++++++++++++++++++++ npm-shrinkwrap.json | 43 ++++++++++ package.json | 2 + tests/shared/utils.spec.js | 1 + 9 files changed, 149 insertions(+), 164 deletions(-) delete mode 100755 lib/shared/utils.js create mode 100755 lib/shared/utils.ts diff --git a/lib/gui/app/models/store.js b/lib/gui/app/models/store.js index 616cc13c..7078a34b 100644 --- a/lib/gui/app/models/store.js +++ b/lib/gui/app/models/store.js @@ -27,6 +27,7 @@ const supportedFormats = require('../../../shared/supported-formats') const errors = require('../../../shared/errors') // eslint-disable-next-line node/no-missing-require const fileExtensions = require('../../../shared/file-extensions') +// eslint-disable-next-line node/no-missing-require const utils = require('../../../shared/utils') const settings = require('./settings') diff --git a/lib/gui/etcher.js b/lib/gui/etcher.js index ad92a5d4..3540f610 100644 --- a/lib/gui/etcher.js +++ b/lib/gui/etcher.js @@ -29,6 +29,7 @@ const { buildWindowMenu } = require('./menu') const settings = require('./app/models/settings') // eslint-disable-next-line node/no-missing-require const analytics = require('./app/modules/analytics') +// eslint-disable-next-line node/no-missing-require const { getConfig } = require('../shared/utils') const { version, packageType } = require('../../package.json') /* eslint-disable lodash/prefer-lodash-method */ diff --git a/lib/shared/errors.ts b/lib/shared/errors.ts index a932cd9c..fa0233bf 100644 --- a/lib/shared/errors.ts +++ b/lib/shared/errors.ts @@ -160,9 +160,9 @@ export function getDescription( */ export function createError(options: { title: string; - description: string; - report: boolean; - code: string; + description?: string; + report?: boolean; + code?: string; }): Error & { description?: string; report?: boolean; code?: string } { if (isBlank(options.title)) { throw new Error(`Invalid error title: ${options.title}`); diff --git a/lib/shared/permissions.js b/lib/shared/permissions.js index eb4f18b9..66f7c0f8 100755 --- a/lib/shared/permissions.js +++ b/lib/shared/permissions.js @@ -31,6 +31,7 @@ const { promisify } = require('util') // eslint-disable-next-line node/no-missing-require const errors = require('./errors') +// eslint-disable-next-line node/no-missing-require const { tmpFileDisposer } = require('./utils') // eslint-disable-next-line node/no-missing-require const { sudo: catalinaSudo } = require('./catalina-sudo/sudo') diff --git a/lib/shared/utils.js b/lib/shared/utils.js deleted file mode 100755 index 03ea594e..00000000 --- a/lib/shared/utils.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2017 balena.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict' - -const _ = require('lodash') -const Bluebird = require('bluebird') -const request = Bluebird.promisifyAll(require('request')) -const tmp = require('tmp') - -// eslint-disable-next-line node/no-missing-require -const errors = require('./errors') - -/** - * @summary Minimum percentage value - * @constant - * @public - * @type {Number} - */ -exports.PERCENTAGE_MINIMUM = 0 - -/** - * @summary Maximum percentage value - * @constant - * @public - * @type {Number} - */ -exports.PERCENTAGE_MAXIMUM = 100 - -/** - * @summary Check if a percentage is valid - * @function - * @public - * - * @param {Number} percentage - percentage - * @returns {Boolean} whether the percentage is valid - * - * @example - * if (utils.isValidPercentage(85)) { - * console.log('The percentage is valid'); - * } - */ -exports.isValidPercentage = (percentage) => { - return _.every([ - _.isNumber(percentage), - percentage >= exports.PERCENTAGE_MINIMUM, - percentage <= exports.PERCENTAGE_MAXIMUM - ]) -} - -/** - * @summary Convert a percentage to a float - * @function - * @public - * - * @param {Number} percentage - percentage - * @returns {Number} float percentage - * - * @example - * const value = utils.percentageToFloat(50); - * console.log(value); - * > 0.5 - */ -exports.percentageToFloat = (percentage) => { - if (!exports.isValidPercentage(percentage)) { - throw errors.createError({ - title: `Invalid percentage: ${percentage}` - }) - } - - return percentage / exports.PERCENTAGE_MAXIMUM -} - -/** - * @summary Check if obj has one or many specific props - * @function - * @public - * - * @param {Object} obj - object - * @param {Array} props - properties - * - * @returns {Boolean} - * - * @example - * const doesIt = hasProps({ foo: 'bar' }, [ 'foo' ]); - */ -exports.hasProps = (obj, props) => { - return _.every(props, (prop) => { - return _.has(obj, prop) - }) -} - -/** -* @summary Get etcher configs stored online -* @param {String} - url where config.json is stored -*/ -// eslint-disable-next-line -exports.getConfig = (configUrl) => { - return request.getAsync(configUrl, { json: true }) - .get('body') -} - -/** - * @summary returns { path: String, cleanup: Function } - * @function - * - * @param {Object} options - options - * - * @returns {Promise<{ path: String, cleanup: Function }>} - * - * @example - * tmpFileAsync() - * .then({ path, cleanup } => { - * console.log(path) - * cleanup() - * }); - */ -const tmpFileAsync = (options) => { - return new Promise((resolve, reject) => { - tmp.file(options, (error, path, _fd, cleanup) => { - if (error) { - reject(error) - } else { - resolve({ path, cleanup }) - } - }) - }) -} - -/** - * @summary Disposer for tmpFileAsync, calls cleanup() - * @function - * - * @param {Object} options - options - * - * @returns {Disposer<{ path: String, cleanup: Function }>} - * - * @example - * await Bluebird.using(tmpFileDisposer(), ({ path }) => { - * console.log(path); - * }) - */ -exports.tmpFileDisposer = (options) => { - return Bluebird.resolve(tmpFileAsync(options)) - .disposer(({ cleanup }) => { - cleanup() - }) -} diff --git a/lib/shared/utils.ts b/lib/shared/utils.ts new file mode 100755 index 00000000..899d596f --- /dev/null +++ b/lib/shared/utils.ts @@ -0,0 +1,97 @@ +/* + * Copyright 2017 balena.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as Bluebird from 'bluebird'; +import * as _ from 'lodash'; +import * as request from 'request'; +import * as tmp from 'tmp'; +import { promisify } from 'util'; + +import * as errors from './errors'; + +const getAsync = promisify(request.get); + +export function isValidPercentage(percentage: any): boolean { + return _.every([_.isNumber(percentage), percentage >= 0, percentage <= 100]); +} + +export function percentageToFloat(percentage: any) { + if (!isValidPercentage(percentage)) { + throw errors.createError({ + title: `Invalid percentage: ${percentage}`, + }); + } + return percentage / 100; +} + +/** + * @summary Check if obj has one or many specific props + */ +export function hasProps(obj: any, props: string[]): boolean { + return _.every(props, prop => { + return _.has(obj, prop); + }); +} + +/** + * @summary Get etcher configs stored online + * @param {String} - url where config.json is stored + */ +export async function getConfig(configUrl: string): Promise { + return (await getAsync({ url: configUrl, json: true })).body; +} + +/** + * @summary returns { path: String, cleanup: Function } + * + * @example + * tmpFileAsync() + * .then({ path, cleanup } => { + * console.log(path) + * cleanup() + * }); + */ +function tmpFileAsync( + options: tmp.FileOptions, +): Promise<{ path: string; cleanup: () => void }> { + return new Promise((resolve, reject) => { + tmp.file(options, (error, path, _fd, cleanup) => { + if (error) { + reject(error); + } else { + resolve({ path, cleanup }); + } + }); + }); +} + +/** + * @summary Disposer for tmpFileAsync, calls cleanup() + * + * @returns {Disposer<{ path: String, cleanup: Function }>} + * + * @example + * await Bluebird.using(tmpFileDisposer(), ({ path }) => { + * console.log(path); + * }) + */ +export function tmpFileDisposer( + options: tmp.FileOptions, +): Bluebird.Disposer<{ path: string; cleanup: () => void }> { + return Bluebird.resolve(tmpFileAsync(options)).disposer(({ cleanup }) => { + cleanup(); + }); +} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index ad197e9c..ae8c3517 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1098,6 +1098,12 @@ "integrity": "sha512-0Vk/kqkukxPKSzP9c8WJgisgGDx5oZDbsLLWIP5t70yThO/YleE+GEm2S1GlRALTaack3O7U5OS5qEm7q2kciA==", "dev": true }, + "@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, "@types/color": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.0.tgz", @@ -1278,6 +1284,31 @@ "@types/react": "*" } }, + "@types/request": { + "version": "2.48.4", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.4.tgz", + "integrity": "sha512-W1t1MTKYR8PxICH+A4HgEIPuAC3sbljoEVfyZbeFJJDbr30guDspJri2XOaM2E+Un7ZjrihaDi7cf6fPa2tbgw==", + "dev": true, + "requires": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + }, + "dependencies": { + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + } + } + }, "@types/sanitize-html": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-1.20.2.tgz", @@ -1304,6 +1335,18 @@ "csstype": "^2.6.4" } }, + "@types/tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA==", + "dev": true + }, + "@types/tough-cookie": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.6.tgz", + "integrity": "sha512-wHNBMnkoEBiRAd3s8KTKwIuO9biFtTf0LehITzBhSco+HQI0xkXZbLOD55SW3Aqw3oUkHstkm5SPv58yaAdFPQ==", + "dev": true + }, "@types/usb": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/usb/-/usb-1.5.1.tgz", diff --git a/package.json b/package.json index 8fca077a..3a6dcfe4 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,8 @@ "@types/mime-types": "^2.1.0", "@types/node": "^12.12.24", "@types/react-dom": "^16.8.4", + "@types/request": "^2.48.4", + "@types/tmp": "^0.1.0", "babel-loader": "^8.0.4", "chalk": "^1.1.3", "electron": "6.1.4", diff --git a/tests/shared/utils.spec.js b/tests/shared/utils.spec.js index 103e6b5d..dd27c915 100644 --- a/tests/shared/utils.spec.js +++ b/tests/shared/utils.spec.js @@ -17,6 +17,7 @@ 'use strict' const m = require('mochainon') +// eslint-disable-next-line node/no-missing-require const utils = require('../../lib/shared/utils') describe('Shared: Utils', function () {