Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = getESLintConfig('react-ts', {
'react-hooks/exhaustive-deps': 0,
'@iceworks/best-practices/recommend-polyfill': 0,
'import/order': 1,
'no-param-reassign': 0
'no-param-reassign': 0,
'@typescript-eslint/no-require-imports': 0
},
});
28 changes: 28 additions & 0 deletions main/autoDownloader/AutoDownloader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as path from 'path';
import * as fse from 'fs-extra';
import { TOOLKIT_PACKAGES_DIR } from '../constants';
import downloadFile from '../utils/downloadFile';
import log from '../utils/log';

class AutoDownloader {
async checkForDownloadAvailable(sourceFileName: string) {
const sourceFilePath = path.join(TOOLKIT_PACKAGES_DIR, sourceFileName);
const sourceFileExists = await fse.pathExists(sourceFilePath);
log.info(sourceFileExists ? `${sourceFileName} has already existed in ${sourceFilePath}` : `${sourceFileName} is available to download.`);
return !sourceFileExists;
}

async downloadPackage({ downloadUrl, sourceFileName }) {
await downloadFile(downloadUrl, TOOLKIT_PACKAGES_DIR, sourceFileName);
}

async start(data) {
const { sourceFileName } = data;
const downloadAvailable = await this.checkForDownloadAvailable(sourceFileName);
if (downloadAvailable) {
await this.downloadPackage(data);
}
}
}

export default AutoDownloader;
31 changes: 31 additions & 0 deletions main/autoDownloader/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { IBasePackageInfo, Platform } from '../types';
import store, { packagesDataKey } from '../store';
import getPackageFileName from '../utils/getPackageFileName';
import AutoDownloader from './AutoDownloader';

const packageTypes = ['bases'];

export async function autoDownloadPackages() {
const data = store.get(packagesDataKey);
// the packages which should be checked for available downloading
const packageDatas = [];

packageTypes.forEach((packageType: string) => {
const packagesInfo: IBasePackageInfo[] = data[packageType] || [];

for (const packageInfo of packagesInfo) {
const { downloadUrl, platforms } = packageInfo;
const currentPlatform = process.platform as Platform;
if (!downloadUrl || !platforms.includes(currentPlatform)) {
continue;
}
const packageFileName = getPackageFileName(packageInfo);
packageDatas.push({ sourceFileName: packageFileName, downloadUrl });
}
});

await Promise.all(packageDatas.map((packageData) => {
const autoDownloader = new AutoDownloader();
return autoDownloader.start(packageData);
}));
}
14 changes: 10 additions & 4 deletions main/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ export const APPLICATIONS_DIR_PATH = '/Applications';

export const PACKAGE_JSON_FILE_NAME = 'package.json';

export const TOOLKIT_TMP_DIR = path.join(process.env.HOME, '.toolkit');
export const TOOLKIT_DIR = path.join(process.env.HOME, '.toolkit');
export const TOOLKIT_TMP_DIR = path.join(TOOLKIT_DIR, 'tmp');
export const TOOLKIT_PACKAGES_DIR = path.join(TOOLKIT_DIR, 'packages');

export const DEFAULT_LOCAL_PACKAGE_INFO: ILocalPackageInfo = {
localVersion: null,
localPath: null,
versionStatus: 'uninstalled',
};

export const VSCODE_CLI_COMAMND_NAME = 'code';
export const VSCODE_COMMAND_NAME = 'code';
export const VSCODE_NAME = 'Visual Studio Code';

export const INSTALL_COMMAND_PACKAGES = [
{
name: 'Visual Studio Code',
command: 'code',
name: VSCODE_NAME,
command: VSCODE_COMMAND_NAME,
commandRelativePath: './Contents/Resources/app/bin/code',
},
];
Expand All @@ -28,3 +31,6 @@ export const NOT_REINSTALL_PACKAGES = ['npm'];
export const TAOBAO_NPM_REGISTRY = 'https://registry.npm.taobao.org';
export const ALI_NPM_REGISTRY = 'https://registry.npm.alibaba-inc.com/';
export const TAOBAO_NODE_MIRROR = 'https://npm.taobao.org/mirrors/node';

export const PROFILE_FILES = ['.bash_profile', '.bashrc', '.zshrc'];
export const DEFAULT_PROFILE_FILE = '.bash_profile';
40 changes: 29 additions & 11 deletions main/data/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
"link": "https://git-scm.com/",
"icon": "https://img.alicdn.com/imgextra/i2/O1CN012cOEYH1QgKmtKX8Ju_!!6000000002005-2-tps-200-200.png",
"downloadUrl": "https://iceworks.oss-cn-hangzhou.aliyuncs.com/toolkit/packages/dmg/git-2.31.0-intel-universal-mavericks.dmg",
"version": "2.29.2",
"version": "2.31.0",
"recommended": true,
"isInternal": false,
"type": "cli",
"platform": "darwin"
"platforms": ["darwin"]
},
{
"title": "Node.js (NVM)",
Expand All @@ -24,7 +24,7 @@
"recommended": true,
"isInternal": false,
"type": "cli",
"platform": "darwin",
"platforms": ["darwin"],
"options": {
"managerName": "nvm"
}
Expand All @@ -40,7 +40,7 @@
"recommended": true,
"isInternal": false,
"type": "dmg",
"platform": "darwin"
"platforms": ["darwin"]
},
{
"title": "Visual Studio Code",
Expand All @@ -53,7 +53,7 @@
"recommended": true,
"isInternal": false,
"type": "dmg",
"platform": "darwin"
"platforms": ["darwin"]
},
{
"title": "AppWorks Pack",
Expand All @@ -67,18 +67,36 @@
"type": "IDEExtension",
"options": {
"IDEType": "VSCode"
}
},
"platforms": ["darwin", "win32"]
}
],
"apps": [
{
"title": "Google Chrome",
"name": "Google Chrome",
"description": "强大、快速的网页浏览器",
"icon": "https://img.alicdn.com/imgextra/i3/O1CN01cspie61ZOm8vgQfKl_!!6000000003185-55-tps-32-32.svg",
"downloadUrl": "",
"version": "89.0.4389.114",
"link": "https://www.google.com/chrome/",
"icon": "https://img.alicdn.com/imgextra/i2/O1CN01jRdeW91kg8w2eH4YR_!!6000000004712-0-tps-225-225.jpg",
"downloadUrl": "https://iceworks.oss-cn-hangzhou.aliyuncs.com/toolkit/packages/dmg/googlechrome.dmg",
"version": null,
"recommended": true,
"isInternal": false
"isInternal": false,
"type": "dmg",
"platforms": ["darwin"]
},
{
"title": "Visual Studio Code",
"name": "Visual Studio Code",
"description": "跨平台、轻量的代码编辑器",
"link": "https://code.visualstudio.com/",
"icon": "https://img.alicdn.com/imgextra/i4/O1CN01Jujm911lApTQ1ghkF_!!6000000004779-0-tps-225-225.jpg",
"downloadUrl": "https://iceworks.oss-cn-hangzhou.aliyuncs.com/toolkit/packages/dmg/VSCode-darwin-universal.zip",
"version": null,
"recommended": true,
"isInternal": false,
"type": "dmg",
"platforms": ["darwin"]
}
],
"npmPackages": [
Expand Down Expand Up @@ -133,4 +151,4 @@
}
}
]
}
}
8 changes: 4 additions & 4 deletions main/data/shells/install-nvm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,12 @@ nvm_detect_profile() {

local DETECTED_PROFILE
DETECTED_PROFILE=''

if [ -n "${BASH_VERSION-}" ]; then
if [ -f "$HOME/.bashrc" ]; then
DETECTED_PROFILE="$HOME/.bashrc"
elif [ -f "$HOME/.bash_profile" ]; then
# execute order is: .bash_profile > .bashrc
if [ -f "$HOME/.bash_profile" ]; then
DETECTED_PROFILE="$HOME/.bash_profile"
elif [ -f "$HOME/.bashrc" ]; then
DETECTED_PROFILE="$HOME/.bashrc"
fi
elif [ -n "${ZSH_VERSION-}" ]; then
DETECTED_PROFILE="$HOME/.zshrc"
Expand Down
5 changes: 5 additions & 0 deletions main/data/shells/is-nvm-installed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

\. "$NVM_DIR/nvm.sh"

echo "$(command -v nvm 2>/dev/null)"
29 changes: 21 additions & 8 deletions main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,35 @@ import modifyProcessEnv from './utils/modifyProcessEnv';
import { createWindow } from './window';
import handleIPC from './ipc';
import { checkForUpdates } from './utils/autoUpdater';
import getPackagesData from './utils/getPackagesData';
import { autoDownloadPackages } from './autoDownloader';
import store, { packagesDataKey } from './store';
import { recordDAU } from './recorder';

process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';

app.whenReady().then(() => {
checkForUpdates();
app.whenReady()
.then(() => getPackagesData())
.then((packagesData) => {
store.set(packagesDataKey, packagesData);
})
.finally(() => {
modifyProcessEnv();

modifyProcessEnv();
createWindow();

createWindow();
handleIPC();

handleIPC();
checkForUpdates();

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
autoDownloadPackages();

recordDAU();

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
Expand Down
15 changes: 7 additions & 8 deletions main/ipc/getBasePackagesInfo.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import * as path from 'path';
import * as fse from 'fs-extra';
import { ipcMain } from 'electron';
import { IBasePackageInfo } from '../types';
import { IBasePackageInfo, Platform } from '../types';
import { getPackageInfo } from '../packageInfo';
import checkIsAliInternal from '../utils/checkIsAliInternal';
import store, { packagesDataKey } from '../store';

export default () => {
ipcMain.handle('get-base-packages-info', async () => {
// TODO: get data.json from OSS and save it in the storage when app starts first
const data = await fse.readJSON(path.join(__dirname, '../data', 'data.json'));
const data = store.get(packagesDataKey);
const { bases = [] }: { bases: IBasePackageInfo[] } = data;
const isAliInternal = await checkIsAliInternal();
const basePackages = bases.filter((item) => {
// remove internal package when not in the ali internal
return item.isInternal ? isAliInternal : true;
const basePackages = bases.filter(({ isInternal, platforms }) => {
// 1. only return the package info in current platform
// 2. remove internal package when not in the ali internal
return platforms.includes(process.platform as Platform) && (isInternal ? isAliInternal : true);
});
const packagesData = await Promise.all(basePackages.map((basePackageInfo: IBasePackageInfo) => {
return getPackageInfo(basePackageInfo);
Expand Down
11 changes: 4 additions & 7 deletions main/ipc/getNodeInfo.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import * as path from 'path';
import * as fse from 'fs-extra';
import { ipcMain } from 'electron';
import { IpcMainInvokeEvent } from 'electron/main';
import getNodeVersions from '../utils/getNodeVersions';
import { getPackageInfo } from '../packageInfo';
import { IBasePackageInfo } from '../types';
import store, { packagesDataKey } from '../store';

export default () => {
ipcMain.handle('get-node-info', async () => {
// TODO: get data.json from OSS and save it in the storage when app starts first
const data = await fse.readJSON(path.join(__dirname, '../data', 'data.json'));
ipcMain.handle('get-node-info', () => {
const data = store.get(packagesDataKey);
const { bases = [] }: { bases: IBasePackageInfo[] } = data;
const nodeBasicInfo = bases.find((base: IBasePackageInfo) => base.name === 'node');
const nodeInfo = getPackageInfo(nodeBasicInfo);

return nodeInfo;
});

ipcMain.handle('get-node-versions', async (event: IpcMainInvokeEvent) => {
ipcMain.handle('get-node-versions', async () => {
return await getNodeVersions();
});
};
7 changes: 5 additions & 2 deletions main/ipc/installBasePackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { send as sendMainWindow } from '../window';
import killChannelChildProcess from '../utils/killChannelChildProcess';
import log from '../utils/log';
import nodeCache from '../utils/nodeCache';
import store, { packagesDataKey } from '../store';

const childProcessMap = new Map();

Expand All @@ -23,8 +24,10 @@ export default () => {
// fork a child process to install package
childProcess = child_process.fork(path.join(__dirname, '..', 'packageInstaller/index'));
childProcessMap.set(installChannel, childProcess);

childProcess.send({ packagesList, installChannel, processChannel });
// After packing the Electron app, the electron module which the electron-store require, couldn't be found in childProcess.
// For more detail, see this PR: https://github.com/appworks-lab/toolkit/pull/41
const packagesData = store.get(packagesDataKey);
childProcess.send({ packagesList, packagesData, installChannel, processChannel });

childProcess.on('message', ({ channel, data }: any) => {
if (channel === processChannel) {
Expand Down
8 changes: 4 additions & 4 deletions main/packageInfo/IDEExtension/vscodeExtension.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import * as execa from 'execa';
import isCliInstalled from '../../utils/isCliInstalled';
import { VSCODE_CLI_COMAMND_NAME } from '../../constants';
import isCliInstalled from '../../utils/isCommandInstalled';
import { VSCODE_COMMAND_NAME } from '../../constants';
import { ILocalPackageInfo } from '../../types';

async function getVSCodeExtensionInfo(name: string) {
const extensionInfo: ILocalPackageInfo = {
versionStatus: 'uninstalled',
localVersion: null,
};
if (isCliInstalled(VSCODE_CLI_COMAMND_NAME)) {
if (isCliInstalled(VSCODE_COMMAND_NAME)) {
const { stdout } = await execa(
VSCODE_CLI_COMAMND_NAME,
VSCODE_COMMAND_NAME,
['--list-extensions', '--show-versions'],
);
if (stdout && typeof stdout === 'string') {
Expand Down
Loading