🎨 Optimize the use of CLI.
This commit is contained in:
3
bin/builders/BaseBuilder.ts
vendored
3
bin/builders/BaseBuilder.ts
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
import ora from "ora";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fsExtra from "fs-extra";
|
import fsExtra from "fs-extra";
|
||||||
import prompts from 'prompts';
|
import prompts from 'prompts';
|
||||||
@@ -39,6 +40,8 @@ export default abstract class BaseBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async runBuildCommand(directory: string, command: string) {
|
protected async runBuildCommand(directory: string, command: string) {
|
||||||
|
const spinner = ora('Building...').start();
|
||||||
|
setTimeout(() => spinner.succeed(), 5000);
|
||||||
const isChina = await isChinaDomain("www.npmjs.com");
|
const isChina = await isChinaDomain("www.npmjs.com");
|
||||||
if (isChina) {
|
if (isChina) {
|
||||||
logger.info("Located in China, using npm/Rust CN mirror.");
|
logger.info("Located in China, using npm/Rust CN mirror.");
|
||||||
|
|||||||
21
bin/builders/BuilderProvider.ts
vendored
21
bin/builders/BuilderProvider.ts
vendored
@@ -3,19 +3,20 @@ import MacBuilder from './MacBuilder';
|
|||||||
import WinBuilder from './WinBuilder';
|
import WinBuilder from './WinBuilder';
|
||||||
import LinuxBuilder from './LinuxBuilder';
|
import LinuxBuilder from './LinuxBuilder';
|
||||||
|
|
||||||
import { IS_MAC, IS_WIN, IS_LINUX } from '@/utils/platform';
|
const { platform } = process;
|
||||||
|
|
||||||
|
const buildersMap: Record<string, new () => BaseBuilder> = {
|
||||||
|
darwin: MacBuilder,
|
||||||
|
win32: WinBuilder,
|
||||||
|
linux: LinuxBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
export default class BuilderProvider {
|
export default class BuilderProvider {
|
||||||
static create(): BaseBuilder {
|
static create(): BaseBuilder {
|
||||||
if (IS_MAC) {
|
const Builder = buildersMap[platform];
|
||||||
return new MacBuilder();
|
if (!Builder) {
|
||||||
|
throw new Error('The current system is not supported!');
|
||||||
}
|
}
|
||||||
if (IS_WIN) {
|
return new Builder();
|
||||||
return new WinBuilder();
|
|
||||||
}
|
|
||||||
if (IS_LINUX) {
|
|
||||||
return new LinuxBuilder();
|
|
||||||
}
|
|
||||||
throw new Error('The current system is not supported!');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
bin/cli.ts
vendored
4
bin/cli.ts
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
import ora from "ora";
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
|
|
||||||
@@ -46,10 +47,11 @@ program
|
|||||||
log.setLevel('debug');
|
log.setLevel('debug');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const spinner = ora('Preparing...').start();
|
||||||
const builder = BuilderProvider.create();
|
const builder = BuilderProvider.create();
|
||||||
await builder.prepare();
|
await builder.prepare();
|
||||||
|
|
||||||
const appOptions = await handleInputOptions(options, url);
|
const appOptions = await handleInputOptions(options, url);
|
||||||
|
spinner.succeed();
|
||||||
|
|
||||||
log.debug('PakeAppOptions', appOptions);
|
log.debug('PakeAppOptions', appOptions);
|
||||||
|
|
||||||
|
|||||||
6
bin/helpers/merge.ts
vendored
6
bin/helpers/merge.ts
vendored
@@ -127,19 +127,19 @@ export async function mergeConfig(
|
|||||||
const platformIconMap: PlatformMap = {
|
const platformIconMap: PlatformMap = {
|
||||||
win32: {
|
win32: {
|
||||||
fileExt: '.ico',
|
fileExt: '.ico',
|
||||||
path: `png/${name.toLowerCase()}_32.ico`,
|
path: `png/${name.toLowerCase()}_256.ico`,
|
||||||
defaultIcon: 'png/icon_256.ico',
|
defaultIcon: 'png/icon_256.ico',
|
||||||
message: 'Windows icon must be .ico and 256x256px.',
|
message: 'Windows icon must be .ico and 256x256px.',
|
||||||
},
|
},
|
||||||
linux: {
|
linux: {
|
||||||
fileExt: '.png',
|
fileExt: '.png',
|
||||||
path: `png/${name.toLowerCase()}_32.png`,
|
path: `png/${name.toLowerCase()}_512.png`,
|
||||||
defaultIcon: 'png/icon_512.png',
|
defaultIcon: 'png/icon_512.png',
|
||||||
message: 'Linux icon must be .png and 512x512px.',
|
message: 'Linux icon must be .png and 512x512px.',
|
||||||
},
|
},
|
||||||
darwin: {
|
darwin: {
|
||||||
fileExt: '.icns',
|
fileExt: '.icns',
|
||||||
path: `icons/${name.toLowerCase()}_32.icns`,
|
path: `icons/${name.toLowerCase()}.icns`,
|
||||||
defaultIcon: 'icons/icon.icns',
|
defaultIcon: 'icons/icon.icns',
|
||||||
message: 'MacOS icon must be .icns type.',
|
message: 'MacOS icon must be .icns type.',
|
||||||
},
|
},
|
||||||
|
|||||||
6
bin/options/icon.ts
vendored
6
bin/options/icon.ts
vendored
@@ -25,11 +25,10 @@ export async function handleIcon(options: PakeAppOptions) {
|
|||||||
|
|
||||||
export async function downloadIcon(iconUrl: string) {
|
export async function downloadIcon(iconUrl: string) {
|
||||||
try {
|
try {
|
||||||
const iconResponse = await axios.get(iconUrl, {
|
const iconResponse = await axios.get(iconUrl, { responseType: 'arraybuffer' });
|
||||||
responseType: 'arraybuffer',
|
|
||||||
});
|
|
||||||
|
|
||||||
const iconData = await iconResponse.data;
|
const iconData = await iconResponse.data;
|
||||||
|
|
||||||
if (!iconData) {
|
if (!iconData) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -42,6 +41,7 @@ export async function downloadIcon(iconUrl: string) {
|
|||||||
const { path: tempPath } = await dir();
|
const { path: tempPath } = await dir();
|
||||||
const iconPath = `${tempPath}/icon.${fileDetails.ext}`;
|
const iconPath = `${tempPath}/icon.${fileDetails.ext}`;
|
||||||
await fsExtra.outputFile(iconPath, iconData);
|
await fsExtra.outputFile(iconPath, iconData);
|
||||||
|
|
||||||
return iconPath;
|
return iconPath;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response && error.response.status === 404) {
|
if (error.response && error.response.status === 404) {
|
||||||
|
|||||||
18
bin/utils/ip.ts
vendored
18
bin/utils/ip.ts
vendored
@@ -10,7 +10,8 @@ const ping = async (host: string) => {
|
|||||||
const ip = await lookup(host);
|
const ip = await lookup(host);
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
|
|
||||||
return new Promise<number>((resolve, reject) => {
|
// Prevent timeouts from affecting user experience.
|
||||||
|
const requestPromise = new Promise<number>((resolve, reject) => {
|
||||||
const req = http.get(`http://${ip.address}`, (res) => {
|
const req = http.get(`http://${ip.address}`, (res) => {
|
||||||
const delay = new Date().getTime() - start.getTime();
|
const delay = new Date().getTime() - start.getTime();
|
||||||
res.resume();
|
res.resume();
|
||||||
@@ -21,14 +22,23 @@ const ping = async (host: string) => {
|
|||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const timeoutPromise = new Promise<number>((_, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('Request timed out after 3 seconds'));
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.race([requestPromise, timeoutPromise]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
async function isChinaDomain(domain: string): Promise<boolean> {
|
async function isChinaDomain(domain: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const [ip] = await resolve(domain);
|
const [ip] = await resolve(domain);
|
||||||
return await isChinaIP(ip, domain);
|
return await isChinaIP(ip, domain);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.info(`${domain} can't be parse!`);
|
logger.debug(`${domain} can't be parse!`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,10 +46,10 @@ async function isChinaDomain(domain: string): Promise<boolean> {
|
|||||||
async function isChinaIP(ip: string, domain: string): Promise<boolean> {
|
async function isChinaIP(ip: string, domain: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const delay = await ping(ip);
|
const delay = await ping(ip);
|
||||||
logger.info(`${domain} latency is ${delay} ms`);
|
logger.debug(`${domain} latency is ${delay} ms`);
|
||||||
return delay > 500;
|
return delay > 500;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.info(`ping ${domain} failed!`);
|
logger.debug(`ping ${domain} failed!`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
dist/cli.js
vendored
64
dist/cli.js
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
import ora from 'ora';
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import { InvalidArgumentError, program } from 'commander';
|
import { InvalidArgumentError, program } from 'commander';
|
||||||
import fsExtra from 'fs-extra';
|
import fsExtra from 'fs-extra';
|
||||||
@@ -15,7 +16,6 @@ import shelljs from 'shelljs';
|
|||||||
import dns from 'dns';
|
import dns from 'dns';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import ora from 'ora';
|
|
||||||
import updateNotifier from 'update-notifier';
|
import updateNotifier from 'update-notifier';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
@@ -42,10 +42,10 @@ const currentModulePath = fileURLToPath(import.meta.url);
|
|||||||
// Resolve the parent directory of the current module
|
// Resolve the parent directory of the current module
|
||||||
const npmDirectory = path.join(path.dirname(currentModulePath), '..');
|
const npmDirectory = path.join(path.dirname(currentModulePath), '..');
|
||||||
|
|
||||||
const { platform: platform$1 } = process;
|
const { platform: platform$2 } = process;
|
||||||
const IS_MAC = platform$1 === 'darwin';
|
const IS_MAC = platform$2 === 'darwin';
|
||||||
const IS_WIN = platform$1 === 'win32';
|
const IS_WIN = platform$2 === 'win32';
|
||||||
const IS_LINUX = platform$1 === 'linux';
|
const IS_LINUX = platform$2 === 'linux';
|
||||||
|
|
||||||
async function handleIcon(options) {
|
async function handleIcon(options) {
|
||||||
if (options.icon) {
|
if (options.icon) {
|
||||||
@@ -64,9 +64,7 @@ async function handleIcon(options) {
|
|||||||
}
|
}
|
||||||
async function downloadIcon(iconUrl) {
|
async function downloadIcon(iconUrl) {
|
||||||
try {
|
try {
|
||||||
const iconResponse = await axios.get(iconUrl, {
|
const iconResponse = await axios.get(iconUrl, { responseType: 'arraybuffer' });
|
||||||
responseType: 'arraybuffer',
|
|
||||||
});
|
|
||||||
const iconData = await iconResponse.data;
|
const iconData = await iconResponse.data;
|
||||||
if (!iconData) {
|
if (!iconData) {
|
||||||
return null;
|
return null;
|
||||||
@@ -347,9 +345,9 @@ const platformConfigs = {
|
|||||||
darwin: MacConf,
|
darwin: MacConf,
|
||||||
linux: LinuxConf
|
linux: LinuxConf
|
||||||
};
|
};
|
||||||
const { platform } = process;
|
const { platform: platform$1 } = process;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const platformConfig = platformConfigs[platform];
|
const platformConfig = platformConfigs[platform$1];
|
||||||
let tauriConfig = {
|
let tauriConfig = {
|
||||||
tauri: {
|
tauri: {
|
||||||
...CommonConf.tauri,
|
...CommonConf.tauri,
|
||||||
@@ -378,7 +376,8 @@ const ping = async (host) => {
|
|||||||
const lookup = promisify(dns.lookup);
|
const lookup = promisify(dns.lookup);
|
||||||
const ip = await lookup(host);
|
const ip = await lookup(host);
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
return new Promise((resolve, reject) => {
|
// Prevent timeouts from affecting user experience.
|
||||||
|
const requestPromise = new Promise((resolve, reject) => {
|
||||||
const req = http.get(`http://${ip.address}`, (res) => {
|
const req = http.get(`http://${ip.address}`, (res) => {
|
||||||
const delay = new Date().getTime() - start.getTime();
|
const delay = new Date().getTime() - start.getTime();
|
||||||
res.resume();
|
res.resume();
|
||||||
@@ -388,6 +387,12 @@ const ping = async (host) => {
|
|||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
const timeoutPromise = new Promise((_, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('Request timed out after 3 seconds'));
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
return Promise.race([requestPromise, timeoutPromise]);
|
||||||
};
|
};
|
||||||
async function isChinaDomain(domain) {
|
async function isChinaDomain(domain) {
|
||||||
try {
|
try {
|
||||||
@@ -395,18 +400,18 @@ async function isChinaDomain(domain) {
|
|||||||
return await isChinaIP(ip, domain);
|
return await isChinaIP(ip, domain);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
logger.info(`${domain} can't be parse!`);
|
logger.debug(`${domain} can't be parse!`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function isChinaIP(ip, domain) {
|
async function isChinaIP(ip, domain) {
|
||||||
try {
|
try {
|
||||||
const delay = await ping(ip);
|
const delay = await ping(ip);
|
||||||
logger.info(`${domain} latency is ${delay} ms`);
|
logger.debug(`${domain} latency is ${delay} ms`);
|
||||||
return delay > 500;
|
return delay > 500;
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
logger.info(`ping ${domain} failed!`);
|
logger.debug(`ping ${domain} failed!`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,6 +462,8 @@ class BaseBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async runBuildCommand(directory, command) {
|
async runBuildCommand(directory, command) {
|
||||||
|
const spinner = ora('Building...').start();
|
||||||
|
setTimeout(() => spinner.succeed(), 5000);
|
||||||
const isChina = await isChinaDomain("www.npmjs.com");
|
const isChina = await isChinaDomain("www.npmjs.com");
|
||||||
if (isChina) {
|
if (isChina) {
|
||||||
logger.info("Located in China, using npm/Rust CN mirror.");
|
logger.info("Located in China, using npm/Rust CN mirror.");
|
||||||
@@ -557,19 +564,19 @@ async function mergeConfig(url, options, tauriConf) {
|
|||||||
const platformIconMap = {
|
const platformIconMap = {
|
||||||
win32: {
|
win32: {
|
||||||
fileExt: '.ico',
|
fileExt: '.ico',
|
||||||
path: `png/${name.toLowerCase()}_32.ico`,
|
path: `png/${name.toLowerCase()}_256.ico`,
|
||||||
defaultIcon: 'png/icon_256.ico',
|
defaultIcon: 'png/icon_256.ico',
|
||||||
message: 'Windows icon must be .ico and 256x256px.',
|
message: 'Windows icon must be .ico and 256x256px.',
|
||||||
},
|
},
|
||||||
linux: {
|
linux: {
|
||||||
fileExt: '.png',
|
fileExt: '.png',
|
||||||
path: `png/${name.toLowerCase()}_32.png`,
|
path: `png/${name.toLowerCase()}_512.png`,
|
||||||
defaultIcon: 'png/icon_512.png',
|
defaultIcon: 'png/icon_512.png',
|
||||||
message: 'Linux icon must be .png and 512x512px.',
|
message: 'Linux icon must be .png and 512x512px.',
|
||||||
},
|
},
|
||||||
darwin: {
|
darwin: {
|
||||||
fileExt: '.icns',
|
fileExt: '.icns',
|
||||||
path: `icons/${name.toLowerCase()}_32.icns`,
|
path: `icons/${name.toLowerCase()}.icns`,
|
||||||
defaultIcon: 'icons/icon.icns',
|
defaultIcon: 'icons/icon.icns',
|
||||||
message: 'MacOS icon must be .icns type.',
|
message: 'MacOS icon must be .icns type.',
|
||||||
},
|
},
|
||||||
@@ -718,23 +725,24 @@ class LinuxBuilder extends BaseBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { platform } = process;
|
||||||
|
const buildersMap = {
|
||||||
|
darwin: MacBuilder,
|
||||||
|
win32: WinBuilder,
|
||||||
|
linux: LinuxBuilder,
|
||||||
|
};
|
||||||
class BuilderProvider {
|
class BuilderProvider {
|
||||||
static create() {
|
static create() {
|
||||||
if (IS_MAC) {
|
const Builder = buildersMap[platform];
|
||||||
return new MacBuilder();
|
if (!Builder) {
|
||||||
|
throw new Error('The current system is not supported!');
|
||||||
}
|
}
|
||||||
if (IS_WIN) {
|
return new Builder();
|
||||||
return new WinBuilder();
|
|
||||||
}
|
|
||||||
if (IS_LINUX) {
|
|
||||||
return new LinuxBuilder();
|
|
||||||
}
|
|
||||||
throw new Error('The current system is not supported!');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = "pake-cli";
|
var name = "pake-cli";
|
||||||
var version = "2.1.0";
|
var version = "2.1.1";
|
||||||
var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。";
|
var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。";
|
||||||
var engines = {
|
var engines = {
|
||||||
node: ">=16.0.0"
|
node: ">=16.0.0"
|
||||||
@@ -907,9 +915,11 @@ program
|
|||||||
if (options.debug) {
|
if (options.debug) {
|
||||||
log.setLevel('debug');
|
log.setLevel('debug');
|
||||||
}
|
}
|
||||||
|
const spinner = ora('Preparing...').start();
|
||||||
const builder = BuilderProvider.create();
|
const builder = BuilderProvider.create();
|
||||||
await builder.prepare();
|
await builder.prepare();
|
||||||
const appOptions = await handleOptions(options, url);
|
const appOptions = await handleOptions(options, url);
|
||||||
|
spinner.succeed();
|
||||||
log.debug('PakeAppOptions', appOptions);
|
log.debug('PakeAppOptions', appOptions);
|
||||||
await builder.build(url, appOptions);
|
await builder.build(url, appOptions);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pake-cli",
|
"name": "pake-cli",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"description": "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。",
|
"description": "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App。",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
"types": [
|
"types": [
|
||||||
"node"
|
"node"
|
||||||
],
|
],
|
||||||
|
"lib": [
|
||||||
|
"es2020",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user