@flun/node-mobile-app 4.0.7 → 4.0.9

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/src/config.js CHANGED
@@ -1,113 +1,113 @@
1
- import path from 'path';
2
- import fs from 'fs';
3
- import { pathToFileURL } from 'url';
4
- import chalk from 'chalk';
5
-
6
- const DEFAULT_CONFIG = {
7
- serverPath: './server.js',
8
- appName: null,
9
- outputDir: null,
10
- appId: 'com.example.app',
11
- versionCode: 1,
12
- versionName: '1.0.0',
13
- webview: {
14
- showLoading: true,
15
- loadingText: '正在启动服务...',
16
- enableJavaScript: true,
17
- enableDomStorage: true,
18
- allowFileAccess: true,
19
- mixedContentMode: 'always',
20
- backgroundColor: '#ffffff',
21
- allowSelfSignedCert: false,
22
- },
23
- android: {
24
- sdkPath: null,
25
- adbPath: null,
26
- minSdkVersion: 29,
27
- targetSdkVersion: 36,
28
- compileSdkVersion: 37,
29
- buildToolsVersion: '37.0.0',
30
- abiFilters: ['arm64-v8a'],
31
- icon: './build/icon.png',
32
- usesCleartextTraffic: true,
33
- permissions: [],
34
- signing: {},
35
- },
36
- ios: {
37
- deploymentTarget: '15.1',
38
- icon: './build/icon.png',
39
- signing: {},
40
- },
41
- advanced: {
42
- keepAlive: true,
43
- heartbeatInterval: 5000,
44
- },
45
- keepFiles: [],
46
- extraRnDependencies: [],
47
- excludeFiles: [
48
- '.git/', '.vscode/', '.idea/', '.vs/',
49
- 'node_modules/', 'sessions/', 'users.json', '.env',
50
- '*.log', '*.md', '*.tgz', '*.bak', '.backup*', 'dist/', 'out/', 'build/', 'tests/',
51
- 'node-mobile-app-build/', 'nodejs-assets/',
52
- ],
53
- optimize: {
54
- enabled: true,
55
- exclude: [],
56
- },
57
- allowScripts: {
58
- 'node': true,
59
- }
60
- },
61
- merge = (def, user) => {
62
- const out = { ...def };
63
- for (const k of Object.keys(user)) {
64
- if (user[k] && typeof user[k] === 'object' && !Array.isArray(user[k])) out[k] = merge(def[k] || {}, user[k]);
65
- else if (user[k] !== undefined && user[k] !== null) out[k] = user[k];
66
- }
67
- return out;
68
- },
69
- loadConfig = async userProjectDir => {
70
- for (const name of ['mobileAppConfig.js', 'mobileAppConfig.mjs', 'mobileAppConfig.cjs']) {
71
- const p = path.join(userProjectDir, name);
72
- if (fs.existsSync(p)) {
73
- console.log(chalk.gray(' 读取配置: ' + name));
74
- const mod = await import(pathToFileURL(p).href);
75
- return merge(DEFAULT_CONFIG, mod.default || mod);
76
- }
77
- }
78
- console.log(chalk.yellow('未找到 mobileAppConfig.js,使用默认配置'));
79
- return DEFAULT_CONFIG;
80
- },
81
- validateConfig = (config, userProjectDir) => {
82
- const errors = [], entry = path.join(userProjectDir, config.serverPath);
83
- if (!fs.existsSync(entry)) errors.push('serverPath 不存在: ' + config.serverPath);
84
-
85
- const pkg = path.join(userProjectDir, 'package.json');
86
- if (!fs.existsSync(pkg)) errors.push('用户项目缺少 package.json');
87
- // 极简防呆:至少 2 段、每段非空、只含 [a-zA-Z0-9_-],不允许首尾点或连续点
88
- // 具体平台是否合法交给 Gradle / Xcode 报错(Android 不允许 -,iOS 允许)
89
- if (typeof config.appId !== 'string' || !/^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(config.appId))
90
- errors.push('appId 格式不合法(需反向域名格式,如 com.example.app): ' + config.appId);
91
- if (!Number.isInteger(config.versionCode) || config.versionCode < 1) errors.push('versionCode 必须是正整数');
92
- if (!config.android.abiFilters?.length) errors.push('android.abiFilters 不能为空');
93
- if (errors.length) {
94
- errors.forEach(e => console.error(chalk.red(' - ' + e)));
95
- throw new Error('配置校验失败');
96
- }
97
- console.log(chalk.green(' ✓ 配置校验通过'));
98
- },
99
- resolveSdkPath = config => {
100
- if (config.android && config.android.sdkPath) return config.android.sdkPath;
101
- for (const env of ['ANDROID_HOME', 'ANDROID_SDK_ROOT']) {
102
- const base = process.env[env];
103
- if (base && fs.existsSync(base)) return base;
104
- }
105
- const localAppData = process.env.LOCALAPPDATA || '', home = process.env.USERPROFILE || process.env.HOME || '',
106
- candidates = [path.join(localAppData, 'Android', 'Sdk'), path.join(home, 'Library', 'Android', 'sdk'),
107
- path.join(home, 'Android', 'Sdk')];
108
-
109
- for (const c of candidates) if (c && fs.existsSync(path.join(c, 'platform-tools'))) return c;
110
- return null;
111
- };
112
-
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { pathToFileURL } from 'url';
4
+ import chalk from 'chalk';
5
+
6
+ const DEFAULT_CONFIG = {
7
+ serverPath: './server.js',
8
+ appName: null,
9
+ outputDir: null,
10
+ appId: 'com.example.app',
11
+ versionCode: 1,
12
+ versionName: '1.0.0',
13
+ webview: {
14
+ showLoading: true,
15
+ loadingText: '正在启动服务...',
16
+ enableJavaScript: true,
17
+ enableDomStorage: true,
18
+ allowFileAccess: true,
19
+ mixedContentMode: 'always',
20
+ backgroundColor: '#ffffff',
21
+ allowSelfSignedCert: false,
22
+ },
23
+ android: {
24
+ sdkPath: null,
25
+ adbPath: null,
26
+ minSdkVersion: 29,
27
+ targetSdkVersion: 36,
28
+ compileSdkVersion: 37,
29
+ buildToolsVersion: '37.0.0',
30
+ abiFilters: ['arm64-v8a'],
31
+ icon: './build/icon.png',
32
+ usesCleartextTraffic: true,
33
+ permissions: [],
34
+ signing: {},
35
+ },
36
+ ios: {
37
+ deploymentTarget: '15.1',
38
+ icon: './build/icon.png',
39
+ signing: {},
40
+ },
41
+ advanced: {
42
+ keepAlive: true,
43
+ heartbeatInterval: 5000,
44
+ },
45
+ keepFiles: [],
46
+ extraRnDependencies: [],
47
+ excludeFiles: [
48
+ '.git/', '.vscode/', '.idea/', '.vs/',
49
+ 'node_modules/', 'sessions/', 'users.json', '.env',
50
+ '*.log', '*.md', '*.tgz', '*.bak', '.backup*', 'dist/', 'out/', 'build/', 'tests/',
51
+ 'node-mobile-app-build/', 'nodejs-assets/',
52
+ ],
53
+ optimize: {
54
+ enabled: true,
55
+ exclude: [],
56
+ },
57
+ allowScripts: {
58
+ 'node': true,
59
+ }
60
+ },
61
+ merge = (def, user) => {
62
+ const out = { ...def };
63
+ for (const k of Object.keys(user)) {
64
+ if (user[k] && typeof user[k] === 'object' && !Array.isArray(user[k])) out[k] = merge(def[k] || {}, user[k]);
65
+ else if (user[k] !== undefined && user[k] !== null) out[k] = user[k];
66
+ }
67
+ return out;
68
+ },
69
+ loadConfig = async userProjectDir => {
70
+ for (const name of ['mobileAppConfig.js', 'mobileAppConfig.mjs', 'mobileAppConfig.cjs']) {
71
+ const p = path.join(userProjectDir, name);
72
+ if (fs.existsSync(p)) {
73
+ console.log(chalk.gray(' 读取配置: ' + name));
74
+ const mod = await import(pathToFileURL(p).href);
75
+ return merge(DEFAULT_CONFIG, mod.default || mod);
76
+ }
77
+ }
78
+ console.log(chalk.yellow('未找到 mobileAppConfig.js,使用默认配置'));
79
+ return DEFAULT_CONFIG;
80
+ },
81
+ validateConfig = (config, userProjectDir) => {
82
+ const errors = [], entry = path.join(userProjectDir, config.serverPath);
83
+ if (!fs.existsSync(entry)) errors.push('serverPath 不存在: ' + config.serverPath);
84
+
85
+ const pkg = path.join(userProjectDir, 'package.json');
86
+ if (!fs.existsSync(pkg)) errors.push('用户项目缺少 package.json');
87
+ // 极简防呆:至少 2 段、每段非空、只含 [a-zA-Z0-9_-],不允许首尾点或连续点
88
+ // 具体平台是否合法交给 Gradle / Xcode 报错(Android 不允许 -,iOS 允许)
89
+ if (typeof config.appId !== 'string' || !/^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(config.appId))
90
+ errors.push('appId 格式不合法(需反向域名格式,如 com.example.app): ' + config.appId);
91
+ if (!Number.isInteger(config.versionCode) || config.versionCode < 1) errors.push('versionCode 必须是正整数');
92
+ if (!config.android.abiFilters?.length) errors.push('android.abiFilters 不能为空');
93
+ if (errors.length) {
94
+ errors.forEach(e => console.error(chalk.red(' - ' + e)));
95
+ throw new Error('配置校验失败');
96
+ }
97
+ console.log(chalk.green(' ✓ 配置校验通过'));
98
+ },
99
+ resolveSdkPath = config => {
100
+ if (config.android && config.android.sdkPath) return config.android.sdkPath;
101
+ for (const env of ['ANDROID_HOME', 'ANDROID_SDK_ROOT']) {
102
+ const base = process.env[env];
103
+ if (base && fs.existsSync(base)) return base;
104
+ }
105
+ const localAppData = process.env.LOCALAPPDATA || '', home = process.env.USERPROFILE || process.env.HOME || '',
106
+ candidates = [path.join(localAppData, 'Android', 'Sdk'), path.join(home, 'Library', 'Android', 'sdk'),
107
+ path.join(home, 'Android', 'Sdk')];
108
+
109
+ for (const c of candidates) if (c && fs.existsSync(path.join(c, 'platform-tools'))) return c;
110
+ return null;
111
+ };
112
+
113
113
  export { DEFAULT_CONFIG, loadConfig, validateConfig, resolveSdkPath };