pake-cli 0.0.2 → 0.0.4
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/dist/cli.js +1 -0
- package/package.json +10 -4
- 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 -4
- 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 -91
- 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/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
package/bin/README.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
## 安装
|
|
2
|
-
|
|
3
|
-
```bash
|
|
4
|
-
npm install -g pake-cli
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
如果安装失败提示没有权限,请使用 `sudo` 运行。
|
|
8
|
-
|
|
9
|
-
## 用法
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
pake [options] url
|
|
13
|
-
```
|
|
14
|
-
打包完成后的应用程序默认为当前工作目录。
|
|
15
|
-
|
|
16
|
-
Note: 打包需要用 `Rust` 环境,如果没有 `Rust`,会提示确认安装。如遇安装失败或超时,可[自行安装](https://www.rust-lang.org/tools/install)。
|
|
17
|
-
|
|
18
|
-
Note: 目前仅支持 MacOs,后续会支持其他平台。
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
### url
|
|
22
|
-
url 为你需要打包的网页链接🔗,必须提供。
|
|
23
|
-
|
|
24
|
-
### [options]
|
|
25
|
-
|
|
26
|
-
提供了一些特定的选项,打包时可以传递对应参数达到定制化的效果。
|
|
27
|
-
|
|
28
|
-
#### [name]
|
|
29
|
-
应用名称,如输入时未指定,会提示你输入。
|
|
30
|
-
```shell
|
|
31
|
-
--name <value>
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
#### [icon]
|
|
35
|
-
应用icon,支持本地/远程文件,默认为 Pake 自带图标。
|
|
36
|
-
- MacOS下必须为 `.icns`
|
|
37
|
-
```shell
|
|
38
|
-
--icon <path>
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
#### [height]
|
|
42
|
-
打包后的应用窗口高度,默认 `800px`。
|
|
43
|
-
```
|
|
44
|
-
--height <number>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
#### [width]
|
|
49
|
-
打包后的应用窗口宽度,默认 `1280px`。
|
|
50
|
-
```
|
|
51
|
-
--width <number>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
#### [transparent]
|
|
56
|
-
是否开启沉浸式头部,默认为 `false` 不开启。
|
|
57
|
-
```
|
|
58
|
-
--transparent
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
#### [resize]
|
|
63
|
-
是否可以拖动大小,默认为 `true` 可拖动。
|
|
64
|
-
```
|
|
65
|
-
--no-resizable
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
#### [fullscreen]
|
|
69
|
-
打开应用后是否开启全屏,默认为 `false`。
|
|
70
|
-
```
|
|
71
|
-
--fullscreen <value>
|
|
72
|
-
```
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { IS_MAC } from '@/utils/platform.js';
|
|
2
|
-
import { IBuilder } from './base.js';
|
|
3
|
-
import MacBuilder from './MacBuilder.js';
|
|
4
|
-
|
|
5
|
-
export default class BuilderFactory {
|
|
6
|
-
static create(): IBuilder {
|
|
7
|
-
if (IS_MAC) {
|
|
8
|
-
return new MacBuilder();
|
|
9
|
-
}
|
|
10
|
-
throw new Error('The current system does not support');
|
|
11
|
-
}
|
|
12
|
-
}
|
|
File without changes
|
|
@@ -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: 'We detected that 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,91 +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
|
-
return downloadIcon(options.icon);
|
|
14
|
-
} else {
|
|
15
|
-
return path.resolve(options.icon);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
if (!options.icon) {
|
|
19
|
-
return inferIcon(options.name, url);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function inferIcon(name: string, url: string) {
|
|
24
|
-
log.info('You have not provided an app icon, use the default icon(can use --icon option to assign an icon)')
|
|
25
|
-
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
26
|
-
return path.join(npmDirectory, 'pake-default.icns');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// export async function getIconFromPageUrl(url: string) {
|
|
30
|
-
// const icon = await pageIcon(url);
|
|
31
|
-
// console.log(icon);
|
|
32
|
-
// if (icon.ext === '.ico') {
|
|
33
|
-
// const a = await ICO.parse(icon.data);
|
|
34
|
-
// icon.data = Buffer.from(a[0].buffer);
|
|
35
|
-
// }
|
|
36
|
-
|
|
37
|
-
// const iconDir = (await dir()).path;
|
|
38
|
-
// const iconPath = path.join(iconDir, `/icon.icns`);
|
|
39
|
-
|
|
40
|
-
// const out = png2icons.createICNS(icon.data, png2icons.BILINEAR, 0);
|
|
41
|
-
|
|
42
|
-
// await fs.writeFile(iconPath, out);
|
|
43
|
-
// return iconPath;
|
|
44
|
-
// }
|
|
45
|
-
|
|
46
|
-
// export async function getIconFromMacosIcons(name: string) {
|
|
47
|
-
// const data = {
|
|
48
|
-
// query: name,
|
|
49
|
-
// filters: 'approved:true',
|
|
50
|
-
// hitsPerPage: 10,
|
|
51
|
-
// page: 1,
|
|
52
|
-
// };
|
|
53
|
-
// 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, {
|
|
54
|
-
// headers: {
|
|
55
|
-
// 'x-algolia-api-key': '0ba04276e457028f3e11e38696eab32c',
|
|
56
|
-
// 'x-algolia-application-id': 'P1TXH7ZFB3',
|
|
57
|
-
// },
|
|
58
|
-
// });
|
|
59
|
-
// if (!res.data.hits.length) {
|
|
60
|
-
// return '';
|
|
61
|
-
// } else {
|
|
62
|
-
// return downloadIcon(res.data.hits[0].icnsUrl);
|
|
63
|
-
// }
|
|
64
|
-
// }
|
|
65
|
-
|
|
66
|
-
export async function downloadIcon(iconUrl: string) {
|
|
67
|
-
let iconResponse;
|
|
68
|
-
try {
|
|
69
|
-
iconResponse = await axios.get(iconUrl, {
|
|
70
|
-
responseType: 'arraybuffer',
|
|
71
|
-
});
|
|
72
|
-
} catch (error) {
|
|
73
|
-
if (error.response && error.response.status === 404) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const iconData = await iconResponse.data;
|
|
80
|
-
if (!iconData) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
const fileDetails = await fileTypeFromBuffer(iconData);
|
|
84
|
-
if (!fileDetails) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
const { path } = await dir();
|
|
88
|
-
const iconPath = `${path}/icon.${fileDetails.ext}`;
|
|
89
|
-
await fs.writeFile(iconPath, iconData);
|
|
90
|
-
return iconPath;
|
|
91
|
-
}
|
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
|
-
}
|