pake-cli 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -2
- package/dist/cli.js +1 -1918
- package/package.json +10 -4
- package/src-tauri/src/main.rs +1 -3
- package/src-tauri/tauri.conf.json +1 -1
- package/.ecrc.json +0 -3
- package/.editorconfig +0 -24
- package/.github/FUNDING.yml +0 -2
- package/.github/ISSUE_TEMPLATE/bug.md +0 -13
- package/.github/workflows/editorconfig-check.yml +0 -23
- package/.github/workflows/main.yml +0 -17
- package/.github/workflows/rust-code-quality-check.yml +0 -89
- package/.prettierignore +0 -4
- package/.vscode/settings.json +0 -8
- package/CODE_OF_CONDUCT.md +0 -128
- package/CONTRIBUTING.md +0 -26
- package/README_EN.md +0 -148
- package/app.csv +0 -9
- package/bin/README.md +0 -72
- package/bin/builders/BuilderFactory.ts +0 -12
- package/bin/builders/LinuxBuilder.ts +0 -0
- package/bin/builders/MacBuilder.ts +0 -65
- package/bin/builders/WinBulider.ts +0 -0
- package/bin/builders/base.ts +0 -16
- package/bin/builders/common.ts +0 -11
- package/bin/cli.ts +0 -36
- package/bin/defaults.ts +0 -13
- package/bin/helpers/rust.ts +0 -21
- package/bin/helpers/tauriConfig.ts +0 -8
- package/bin/options/icon.ts +0 -97
- package/bin/options/index.ts +0 -22
- package/bin/types.ts +0 -29
- package/bin/utils/platform.ts +0 -5
- package/bin/utils/shell.ts +0 -13
- package/bin/utils/tlds.ts +0 -1489
- package/bin/utils/url.ts +0 -47
- package/bin/utils/validate.ts +0 -18
- package/icns2png.py +0 -38
- package/pake-default.icns +0 -0
- package/rollup.config.js +0 -24
- package/script/build.bat +0 -80
- package/script/build.sh +0 -122
- package/script/sd-apple-x64 +0 -0
- package/script/sd-linux-x64 +0 -0
- package/script/sd.exe +0 -0
- package/tsconfig.json +0 -17
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import prompts from 'prompts';
|
|
4
|
-
import { checkRustInstalled, installRust } from '@/helpers/rust.js';
|
|
5
|
-
import { PakeAppOptions } from '@/types.js';
|
|
6
|
-
import { IBuilder } from './base.js';
|
|
7
|
-
import { shellExec } from '@/utils/shell.js';
|
|
8
|
-
import tauriConf from '../../src-tauri/tauri.conf.json';
|
|
9
|
-
import { fileURLToPath } from 'url';
|
|
10
|
-
import log from 'loglevel';
|
|
11
|
-
|
|
12
|
-
export default class MacBuilder implements IBuilder {
|
|
13
|
-
async prepare() {
|
|
14
|
-
if (checkRustInstalled()) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const res = await prompts({
|
|
19
|
-
type: 'confirm',
|
|
20
|
-
message: 'Detect you have not installed Rust, install it now?',
|
|
21
|
-
name: 'value',
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
if (res.value) {
|
|
25
|
-
// TODO 国内有可能会超时
|
|
26
|
-
await installRust();
|
|
27
|
-
} else {
|
|
28
|
-
log.error('Error: Pake need Rust to package your webapp!!!');
|
|
29
|
-
process.exit(2);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async build(url: string, options: PakeAppOptions) {
|
|
34
|
-
log.debug('PakeAppOptions', options);
|
|
35
|
-
|
|
36
|
-
const { width, height, fullscreen, transparent, resizable, identifier, name } = options;
|
|
37
|
-
|
|
38
|
-
const tauriConfWindowOptions = {
|
|
39
|
-
width,
|
|
40
|
-
height,
|
|
41
|
-
fullscreen,
|
|
42
|
-
transparent,
|
|
43
|
-
resizable,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// TODO 下面这块逻辑还可以再拆 目前比较简单
|
|
47
|
-
Object.assign(tauriConf.tauri.windows[0], { url, ...tauriConfWindowOptions });
|
|
48
|
-
tauriConf.package.productName = name;
|
|
49
|
-
tauriConf.tauri.bundle.identifier = identifier;
|
|
50
|
-
tauriConf.tauri.bundle.icon = [options.icon];
|
|
51
|
-
|
|
52
|
-
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
53
|
-
const configJsonPath = path.join(npmDirectory, 'src-tauri/tauri.conf.json');
|
|
54
|
-
await fs.writeFile(configJsonPath, Buffer.from(JSON.stringify(tauriConf), 'utf-8'));
|
|
55
|
-
|
|
56
|
-
const code = await shellExec(`cd ${npmDirectory} && npm run build`);
|
|
57
|
-
const dmgName = `${name}_${'0.2.0'}_universal.dmg`;
|
|
58
|
-
const appPath = this.getBuildedAppPath(npmDirectory, dmgName);
|
|
59
|
-
await fs.copyFile(appPath, path.resolve(`${name}_universal.dmg`));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
getBuildedAppPath(npmDirectory: string, dmgName: string) {
|
|
63
|
-
return path.join(npmDirectory, 'src-tauri/target/universal-apple-darwin/release/bundle/dmg', dmgName);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
File without changes
|
package/bin/builders/base.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { PakeAppOptions } from '@/types.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Builder接口
|
|
5
|
-
* 不同平台打包过程需要实现 prepare 和 build 方法
|
|
6
|
-
*/
|
|
7
|
-
export interface IBuilder {
|
|
8
|
-
/** 前置检查 */
|
|
9
|
-
prepare(): Promise<void>;
|
|
10
|
-
/**
|
|
11
|
-
* 开始打包
|
|
12
|
-
* @param url 打包url
|
|
13
|
-
* @param options 配置参数
|
|
14
|
-
*/
|
|
15
|
-
build(url: string, options: PakeAppOptions): Promise<void>;
|
|
16
|
-
}
|
package/bin/builders/common.ts
DELETED
package/bin/cli.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { program } from 'commander';
|
|
2
|
-
import { DEFAULT_PAKE_OPTIONS } from './defaults.js';
|
|
3
|
-
import { PakeCliOptions } from './types.js';
|
|
4
|
-
import { validateNumberInput, validateUrlInput } from './utils/validate.js';
|
|
5
|
-
import handleInputOptions from './options/index.js';
|
|
6
|
-
import BuilderFactory from './builders/BuilderFactory.js';
|
|
7
|
-
import log from 'loglevel';
|
|
8
|
-
|
|
9
|
-
program.version('0.0.1').description('A cli application can package a web page to desktop application');
|
|
10
|
-
|
|
11
|
-
program
|
|
12
|
-
.showHelpAfterError()
|
|
13
|
-
.argument('<url>', 'the web url you want to package', validateUrlInput)
|
|
14
|
-
.option('--name <string>', 'application name')
|
|
15
|
-
.option('--icon <string>', 'application icon', DEFAULT_PAKE_OPTIONS.icon)
|
|
16
|
-
.option('--height <number>', 'window height', validateNumberInput, DEFAULT_PAKE_OPTIONS.height)
|
|
17
|
-
.option('--width <number>', 'window width', validateNumberInput, DEFAULT_PAKE_OPTIONS.width)
|
|
18
|
-
.option('--no-resizable', 'whether the window can be resizable', DEFAULT_PAKE_OPTIONS.resizable)
|
|
19
|
-
.option('--fullscreen', 'makes the packaged app start in full screen', DEFAULT_PAKE_OPTIONS.fullscreen)
|
|
20
|
-
.option('--transparent', 'transparent title bar', DEFAULT_PAKE_OPTIONS.transparent)
|
|
21
|
-
.option('--debug', 'debug', DEFAULT_PAKE_OPTIONS.transparent)
|
|
22
|
-
.action(async (url: string, options: PakeCliOptions) => {
|
|
23
|
-
log.setDefaultLevel('info')
|
|
24
|
-
if (options.debug) {
|
|
25
|
-
log.setLevel('debug');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const builder = BuilderFactory.create();
|
|
29
|
-
await builder.prepare();
|
|
30
|
-
|
|
31
|
-
const appOptions = await handleInputOptions(options, url);
|
|
32
|
-
|
|
33
|
-
builder.build(url, appOptions);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
program.parse();
|
package/bin/defaults.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { PakeCliOptions } from './types.js';
|
|
2
|
-
|
|
3
|
-
export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = {
|
|
4
|
-
icon: '',
|
|
5
|
-
height: 800,
|
|
6
|
-
width: 1280,
|
|
7
|
-
fullscreen: false,
|
|
8
|
-
resizable: true,
|
|
9
|
-
transparent: false,
|
|
10
|
-
debug: false,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const DEFAULT_APP_NAME = 'Pake';
|
package/bin/helpers/rust.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import ora from 'ora';
|
|
2
|
-
import shelljs from 'shelljs';
|
|
3
|
-
import { shellExec } from '../utils/shell.js';
|
|
4
|
-
|
|
5
|
-
const InstallRustScript = "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y";
|
|
6
|
-
export async function installRust() {
|
|
7
|
-
const spinner = ora('Downloading Rust').start();
|
|
8
|
-
try {
|
|
9
|
-
await shellExec(InstallRustScript);
|
|
10
|
-
spinner.succeed();
|
|
11
|
-
} catch (error) {
|
|
12
|
-
console.error('install rust return code', error.message);
|
|
13
|
-
spinner.fail();
|
|
14
|
-
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function checkRustInstalled() {
|
|
20
|
-
return shelljs.exec('rustc --version', { silent: true }).code === 0;
|
|
21
|
-
}
|
package/bin/options/icon.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import { fileTypeFromBuffer } from "file-type";
|
|
3
|
-
import { PakeAppOptions } from "../types.js";
|
|
4
|
-
import { dir } from "tmp-promise";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import fs from "fs/promises";
|
|
7
|
-
import { fileURLToPath } from "url";
|
|
8
|
-
import log from "loglevel";
|
|
9
|
-
|
|
10
|
-
export async function handleIcon(options: PakeAppOptions, url: string) {
|
|
11
|
-
if (options.icon) {
|
|
12
|
-
if (options.icon.startsWith("http")) {
|
|
13
|
-
log.info(options.icon);
|
|
14
|
-
return downloadIcon(options.icon);
|
|
15
|
-
} else {
|
|
16
|
-
return path.resolve(options.icon);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
if (!options.icon) {
|
|
20
|
-
return inferIcon(options.name, url);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function inferIcon(name: string, url: string) {
|
|
25
|
-
log.info(
|
|
26
|
-
"You have not provided an app icon, use the default icon(can use --icon option to assign an icon)"
|
|
27
|
-
);
|
|
28
|
-
const npmDirectory = path.join(
|
|
29
|
-
path.dirname(fileURLToPath(import.meta.url)),
|
|
30
|
-
".."
|
|
31
|
-
);
|
|
32
|
-
return path.join(npmDirectory, "pake-default.icns");
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// export async function getIconFromPageUrl(url: string) {
|
|
36
|
-
// const icon = await pageIcon(url);
|
|
37
|
-
// console.log(icon);
|
|
38
|
-
// if (icon.ext === '.ico') {
|
|
39
|
-
// const a = await ICO.parse(icon.data);
|
|
40
|
-
// icon.data = Buffer.from(a[0].buffer);
|
|
41
|
-
// }
|
|
42
|
-
|
|
43
|
-
// const iconDir = (await dir()).path;
|
|
44
|
-
// const iconPath = path.join(iconDir, `/icon.icns`);
|
|
45
|
-
|
|
46
|
-
// const out = png2icons.createICNS(icon.data, png2icons.BILINEAR, 0);
|
|
47
|
-
|
|
48
|
-
// await fs.writeFile(iconPath, out);
|
|
49
|
-
// return iconPath;
|
|
50
|
-
// }
|
|
51
|
-
|
|
52
|
-
// export async function getIconFromMacosIcons(name: string) {
|
|
53
|
-
// const data = {
|
|
54
|
-
// query: name,
|
|
55
|
-
// filters: 'approved:true',
|
|
56
|
-
// hitsPerPage: 10,
|
|
57
|
-
// page: 1,
|
|
58
|
-
// };
|
|
59
|
-
// const res = await axios.post('https://p1txh7zfb3-2.algolianet.com/1/indexes/macOSicons/query?x-algolia-agent=Algolia%20for%20JavaScript%20(4.13.1)%3B%20Browser', data, {
|
|
60
|
-
// headers: {
|
|
61
|
-
// 'x-algolia-api-key': '0ba04276e457028f3e11e38696eab32c',
|
|
62
|
-
// 'x-algolia-application-id': 'P1TXH7ZFB3',
|
|
63
|
-
// },
|
|
64
|
-
// });
|
|
65
|
-
// if (!res.data.hits.length) {
|
|
66
|
-
// return '';
|
|
67
|
-
// } else {
|
|
68
|
-
// return downloadIcon(res.data.hits[0].icnsUrl);
|
|
69
|
-
// }
|
|
70
|
-
// }
|
|
71
|
-
|
|
72
|
-
export async function downloadIcon(iconUrl: string) {
|
|
73
|
-
let iconResponse;
|
|
74
|
-
try {
|
|
75
|
-
iconResponse = await axios.get(iconUrl, {
|
|
76
|
-
responseType: "arraybuffer",
|
|
77
|
-
});
|
|
78
|
-
} catch (error) {
|
|
79
|
-
if (error.response && error.response.status === 404) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
throw error;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const iconData = await iconResponse.data;
|
|
86
|
-
if (!iconData) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
const fileDetails = await fileTypeFromBuffer(iconData);
|
|
90
|
-
if (!fileDetails) {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
const { path } = await dir();
|
|
94
|
-
const iconPath = `${path}/icon.${fileDetails.ext}`;
|
|
95
|
-
await fs.writeFile(iconPath, iconData);
|
|
96
|
-
return iconPath;
|
|
97
|
-
}
|
package/bin/options/index.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { promptText } from '@/builders/common.js';
|
|
2
|
-
import { getDomain } from '@/utils/url.js';
|
|
3
|
-
import { getIdentifier } from '../helpers/tauriConfig.js';
|
|
4
|
-
import { PakeAppOptions, PakeCliOptions } from '../types.js';
|
|
5
|
-
import { handleIcon } from './icon.js';
|
|
6
|
-
|
|
7
|
-
export default async function handleOptions(options: PakeCliOptions, url: string): Promise<PakeAppOptions> {
|
|
8
|
-
const appOptions: PakeAppOptions = {
|
|
9
|
-
...options,
|
|
10
|
-
identifier: '',
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
if (!appOptions.name) {
|
|
14
|
-
appOptions.name = await promptText('please input your application name', getDomain(url));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
appOptions.identifier = getIdentifier(appOptions.name, url);
|
|
18
|
-
|
|
19
|
-
appOptions.icon = await handleIcon(appOptions, url);
|
|
20
|
-
|
|
21
|
-
return appOptions;
|
|
22
|
-
}
|
package/bin/types.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export interface PakeCliOptions {
|
|
2
|
-
/** 应用名称 */
|
|
3
|
-
name?: string;
|
|
4
|
-
|
|
5
|
-
/** 应用icon */
|
|
6
|
-
icon: string;
|
|
7
|
-
|
|
8
|
-
/** 应用窗口宽度,默认 1280px */
|
|
9
|
-
width: number;
|
|
10
|
-
|
|
11
|
-
/** 应用窗口高度,默认 800px */
|
|
12
|
-
height: number;
|
|
13
|
-
|
|
14
|
-
/** 是否可以拖动,默认true */
|
|
15
|
-
resizable: boolean;
|
|
16
|
-
|
|
17
|
-
/** 是否可以全屏,默认 false */
|
|
18
|
-
fullscreen: boolean;
|
|
19
|
-
|
|
20
|
-
/** 是否开启沉浸式头部,默认为 false 不开启 ƒ*/
|
|
21
|
-
transparent: boolean;
|
|
22
|
-
|
|
23
|
-
/** 调试模式,会输出更多日志 */
|
|
24
|
-
debug: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface PakeAppOptions extends PakeCliOptions {
|
|
28
|
-
identifier: string;
|
|
29
|
-
}
|
package/bin/utils/platform.ts
DELETED
package/bin/utils/shell.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import shelljs from 'shelljs';
|
|
2
|
-
|
|
3
|
-
export function shellExec(command: string) {
|
|
4
|
-
return new Promise<number>((resolve, reject) => {
|
|
5
|
-
shelljs.exec(command, { async: true, silent: false}, (code) => {
|
|
6
|
-
if (code === 0) {
|
|
7
|
-
resolve(0);
|
|
8
|
-
} else {
|
|
9
|
-
reject(new Error(`${code}`));
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
});
|
|
13
|
-
}
|