react-native-update-cli 1.46.2 → 2.0.1
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 +603 -1
- package/README.zh-CN.md +601 -0
- package/cli.json +39 -3
- package/lib/api.js +5 -5
- package/lib/app.js +1 -1
- package/lib/bundle.js +30 -28
- package/lib/exports.js +65 -0
- package/lib/index.js +100 -9
- package/lib/locales/en.js +2 -1
- package/lib/locales/zh.js +2 -1
- package/lib/module-manager.js +125 -0
- package/lib/modules/app-module.js +223 -0
- package/lib/modules/bundle-module.js +188 -0
- package/lib/modules/index.js +42 -0
- package/lib/modules/package-module.js +16 -0
- package/lib/modules/user-module.js +402 -0
- package/lib/modules/version-module.js +16 -0
- package/lib/package.js +40 -9
- package/lib/provider.js +341 -0
- package/lib/user.js +3 -3
- package/lib/utils/app-info-parser/apk.js +1 -1
- package/lib/utils/app-info-parser/ipa.js +2 -2
- package/lib/utils/app-info-parser/resource-finder.js +35 -35
- package/lib/utils/app-info-parser/xml-parser/manifest.js +2 -2
- package/lib/utils/app-info-parser/zip.js +3 -6
- package/lib/utils/check-plugin.js +1 -1
- package/lib/utils/git.js +1 -1
- package/lib/utils/i18n.js +3 -1
- package/lib/utils/index.js +4 -4
- package/lib/utils/latest-version/cli.js +3 -3
- package/lib/utils/latest-version/index.js +4 -4
- package/lib/versions.js +2 -2
- package/package.json +4 -4
- package/src/api.ts +7 -7
- package/src/app.ts +2 -2
- package/src/bundle.ts +44 -32
- package/src/exports.ts +30 -0
- package/src/index.ts +118 -16
- package/src/locales/en.ts +1 -0
- package/src/locales/zh.ts +1 -0
- package/src/module-manager.ts +149 -0
- package/src/modules/app-module.ts +205 -0
- package/src/modules/bundle-module.ts +202 -0
- package/src/modules/index.ts +19 -0
- package/src/modules/package-module.ts +11 -0
- package/src/modules/user-module.ts +406 -0
- package/src/modules/version-module.ts +8 -0
- package/src/package.ts +59 -25
- package/src/provider.ts +341 -0
- package/src/types.ts +126 -0
- package/src/user.ts +4 -3
- package/src/utils/app-info-parser/apk.js +62 -52
- package/src/utils/app-info-parser/app.js +5 -5
- package/src/utils/app-info-parser/ipa.js +69 -57
- package/src/utils/app-info-parser/resource-finder.js +50 -54
- package/src/utils/app-info-parser/utils.js +59 -54
- package/src/utils/app-info-parser/xml-parser/binary.js +366 -354
- package/src/utils/app-info-parser/xml-parser/manifest.js +145 -137
- package/src/utils/app-info-parser/zip.js +1 -1
- package/src/utils/check-plugin.ts +4 -2
- package/src/utils/dep-versions.ts +13 -6
- package/src/utils/git.ts +1 -1
- package/src/utils/i18n.ts +3 -1
- package/src/utils/index.ts +8 -10
- package/src/utils/latest-version/cli.ts +4 -4
- package/src/utils/latest-version/index.ts +17 -17
- package/src/utils/plugin-config.ts +3 -3
- package/src/versions.ts +3 -3
package/src/provider.ts
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { getSession, loadSession } from './api';
|
|
2
|
+
import { getPlatform, getSelectedApp } from './app';
|
|
3
|
+
import type {
|
|
4
|
+
BundleOptions,
|
|
5
|
+
CLIProvider,
|
|
6
|
+
CommandContext,
|
|
7
|
+
CommandResult,
|
|
8
|
+
CustomWorkflow,
|
|
9
|
+
Platform,
|
|
10
|
+
PublishOptions,
|
|
11
|
+
Session,
|
|
12
|
+
UploadOptions,
|
|
13
|
+
Version,
|
|
14
|
+
} from './types';
|
|
15
|
+
|
|
16
|
+
export class CLIProviderImpl implements CLIProvider {
|
|
17
|
+
private workflows: Map<string, CustomWorkflow> = new Map();
|
|
18
|
+
private session?: Session;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
this.init();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private async init() {
|
|
25
|
+
try {
|
|
26
|
+
await loadSession();
|
|
27
|
+
this.session = getSession();
|
|
28
|
+
} catch (error) {}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async bundle(options: BundleOptions): Promise<CommandResult> {
|
|
32
|
+
try {
|
|
33
|
+
const context: CommandContext = {
|
|
34
|
+
args: [],
|
|
35
|
+
options: {
|
|
36
|
+
dev: options.dev || false,
|
|
37
|
+
platform: options.platform,
|
|
38
|
+
bundleName: options.bundleName || 'index.bundlejs',
|
|
39
|
+
entryFile: options.entryFile || 'index.js',
|
|
40
|
+
output: options.output || '${tempDir}/output/${platform}.${time}.ppk',
|
|
41
|
+
sourcemap: options.sourcemap || false,
|
|
42
|
+
taro: options.taro || false,
|
|
43
|
+
expo: options.expo || false,
|
|
44
|
+
rncli: options.rncli || false,
|
|
45
|
+
disableHermes: options.disableHermes || false,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const { bundleCommands } = await import('./bundle');
|
|
50
|
+
await bundleCommands.bundle(context);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
success: true,
|
|
54
|
+
data: { message: 'Bundle created successfully' },
|
|
55
|
+
};
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error:
|
|
60
|
+
error instanceof Error
|
|
61
|
+
? error.message
|
|
62
|
+
: 'Unknown error during bundling',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async publish(options: PublishOptions): Promise<CommandResult> {
|
|
68
|
+
try {
|
|
69
|
+
const context: CommandContext = {
|
|
70
|
+
args: [],
|
|
71
|
+
options: {
|
|
72
|
+
name: options.name,
|
|
73
|
+
description: options.description,
|
|
74
|
+
metaInfo: options.metaInfo,
|
|
75
|
+
packageId: options.packageId,
|
|
76
|
+
packageVersion: options.packageVersion,
|
|
77
|
+
minPackageVersion: options.minPackageVersion,
|
|
78
|
+
maxPackageVersion: options.maxPackageVersion,
|
|
79
|
+
packageVersionRange: options.packageVersionRange,
|
|
80
|
+
rollout: options.rollout,
|
|
81
|
+
dryRun: options.dryRun || false,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const { versionCommands } = await import('./versions');
|
|
86
|
+
await versionCommands.publish(context);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
success: true,
|
|
90
|
+
data: { message: 'Version published successfully' },
|
|
91
|
+
};
|
|
92
|
+
} catch (error) {
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error:
|
|
96
|
+
error instanceof Error
|
|
97
|
+
? error.message
|
|
98
|
+
: 'Unknown error during publishing',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async upload(options: UploadOptions): Promise<CommandResult> {
|
|
104
|
+
try {
|
|
105
|
+
const platform = await this.getPlatform(options.platform);
|
|
106
|
+
const { appId } = await this.getSelectedApp(platform);
|
|
107
|
+
|
|
108
|
+
const filePath = options.filePath;
|
|
109
|
+
const fileType = filePath.split('.').pop()?.toLowerCase();
|
|
110
|
+
|
|
111
|
+
const context: CommandContext = {
|
|
112
|
+
args: [filePath],
|
|
113
|
+
options: { platform, appId, version: options.version },
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const { packageCommands } = await import('./package');
|
|
117
|
+
|
|
118
|
+
switch (fileType) {
|
|
119
|
+
case 'ipa':
|
|
120
|
+
await packageCommands.uploadIpa(context);
|
|
121
|
+
break;
|
|
122
|
+
case 'apk':
|
|
123
|
+
await packageCommands.uploadApk(context);
|
|
124
|
+
break;
|
|
125
|
+
case 'app':
|
|
126
|
+
await packageCommands.uploadApp(context);
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
throw new Error(`Unsupported file type: ${fileType}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
success: true,
|
|
134
|
+
data: { message: 'File uploaded successfully' },
|
|
135
|
+
};
|
|
136
|
+
} catch (error) {
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
error:
|
|
140
|
+
error instanceof Error
|
|
141
|
+
? error.message
|
|
142
|
+
: 'Unknown error during upload',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async getSelectedApp(
|
|
148
|
+
platform?: Platform,
|
|
149
|
+
): Promise<{ appId: string; platform: Platform }> {
|
|
150
|
+
const resolvedPlatform = await this.getPlatform(platform);
|
|
151
|
+
return getSelectedApp(resolvedPlatform);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async listApps(platform?: Platform): Promise<CommandResult> {
|
|
155
|
+
try {
|
|
156
|
+
const resolvedPlatform = await this.getPlatform(platform);
|
|
157
|
+
const { appCommands } = await import('./app');
|
|
158
|
+
await appCommands.apps({ options: { platform: resolvedPlatform } });
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
success: true,
|
|
162
|
+
data: { message: 'Apps listed successfully' },
|
|
163
|
+
};
|
|
164
|
+
} catch (error) {
|
|
165
|
+
return {
|
|
166
|
+
success: false,
|
|
167
|
+
error:
|
|
168
|
+
error instanceof Error ? error.message : 'Unknown error listing apps',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async createApp(name: string, platform: Platform): Promise<CommandResult> {
|
|
174
|
+
try {
|
|
175
|
+
const { appCommands } = await import('./app');
|
|
176
|
+
await appCommands.createApp({
|
|
177
|
+
options: {
|
|
178
|
+
name,
|
|
179
|
+
platform,
|
|
180
|
+
downloadUrl: '',
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
success: true,
|
|
186
|
+
data: { message: 'App created successfully' },
|
|
187
|
+
};
|
|
188
|
+
} catch (error) {
|
|
189
|
+
return {
|
|
190
|
+
success: false,
|
|
191
|
+
error:
|
|
192
|
+
error instanceof Error ? error.message : 'Unknown error creating app',
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async listVersions(appId: string): Promise<CommandResult> {
|
|
198
|
+
try {
|
|
199
|
+
const context: CommandContext = {
|
|
200
|
+
args: [],
|
|
201
|
+
options: { appId },
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const { versionCommands } = await import('./versions');
|
|
205
|
+
await versionCommands.versions(context);
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
success: true,
|
|
209
|
+
data: { message: 'Versions listed successfully' },
|
|
210
|
+
};
|
|
211
|
+
} catch (error) {
|
|
212
|
+
return {
|
|
213
|
+
success: false,
|
|
214
|
+
error:
|
|
215
|
+
error instanceof Error
|
|
216
|
+
? error.message
|
|
217
|
+
: 'Unknown error listing versions',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async updateVersion(
|
|
223
|
+
appId: string,
|
|
224
|
+
versionId: string,
|
|
225
|
+
updates: Partial<Version>,
|
|
226
|
+
): Promise<CommandResult> {
|
|
227
|
+
try {
|
|
228
|
+
const context: CommandContext = {
|
|
229
|
+
args: [versionId],
|
|
230
|
+
options: {
|
|
231
|
+
appId,
|
|
232
|
+
...updates,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const { versionCommands } = await import('./versions');
|
|
237
|
+
await versionCommands.update(context);
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
success: true,
|
|
241
|
+
data: { message: 'Version updated successfully' },
|
|
242
|
+
};
|
|
243
|
+
} catch (error) {
|
|
244
|
+
return {
|
|
245
|
+
success: false,
|
|
246
|
+
error:
|
|
247
|
+
error instanceof Error
|
|
248
|
+
? error.message
|
|
249
|
+
: 'Unknown error updating version',
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async getPlatform(platform?: Platform): Promise<Platform> {
|
|
255
|
+
return getPlatform(platform);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async loadSession(): Promise<Session> {
|
|
259
|
+
await loadSession();
|
|
260
|
+
this.session = getSession();
|
|
261
|
+
if (!this.session) {
|
|
262
|
+
throw new Error('Failed to load session');
|
|
263
|
+
}
|
|
264
|
+
return this.session;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
registerWorkflow(workflow: CustomWorkflow): void {
|
|
268
|
+
this.workflows.set(workflow.name, workflow);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async executeWorkflow(
|
|
272
|
+
workflowName: string,
|
|
273
|
+
context: CommandContext,
|
|
274
|
+
): Promise<CommandResult> {
|
|
275
|
+
const workflow = this.workflows.get(workflowName);
|
|
276
|
+
if (!workflow) {
|
|
277
|
+
return {
|
|
278
|
+
success: false,
|
|
279
|
+
error: `Workflow '${workflowName}' not found`,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
let previousResult: any = null;
|
|
285
|
+
for (const step of workflow.steps) {
|
|
286
|
+
if (step.condition && !step.condition(context)) {
|
|
287
|
+
console.log(`Skipping step '${step.name}' due to condition`);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
console.log(`Executing step '${step.name}'`);
|
|
292
|
+
previousResult = await step.execute(context, previousResult);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
success: true,
|
|
297
|
+
data: {
|
|
298
|
+
message: `Workflow '${workflowName}' completed successfully`,
|
|
299
|
+
result: previousResult,
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
} catch (error) {
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
error:
|
|
306
|
+
error instanceof Error
|
|
307
|
+
? error.message
|
|
308
|
+
: `Workflow '${workflowName}' failed`,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
getRegisteredWorkflows(): string[] {
|
|
314
|
+
return Array.from(this.workflows.keys());
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async listPackages(appId?: string): Promise<CommandResult> {
|
|
318
|
+
try {
|
|
319
|
+
const context: CommandContext = {
|
|
320
|
+
args: [],
|
|
321
|
+
options: appId ? { appId } : {},
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const { listPackage } = await import('./package');
|
|
325
|
+
const result = await listPackage(appId || '');
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
success: true,
|
|
329
|
+
data: result,
|
|
330
|
+
};
|
|
331
|
+
} catch (error) {
|
|
332
|
+
return {
|
|
333
|
+
success: false,
|
|
334
|
+
error:
|
|
335
|
+
error instanceof Error
|
|
336
|
+
? error.message
|
|
337
|
+
: 'Unknown error listing packages',
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -12,6 +12,12 @@ export type Platform = 'ios' | 'android' | 'harmony';
|
|
|
12
12
|
export interface Package {
|
|
13
13
|
id: string;
|
|
14
14
|
name: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
status?: string;
|
|
17
|
+
appId?: string;
|
|
18
|
+
appKey?: string;
|
|
19
|
+
versionName?: any;
|
|
20
|
+
buildTime?: any;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
export interface Version {
|
|
@@ -20,3 +26,123 @@ export interface Version {
|
|
|
20
26
|
name: string;
|
|
21
27
|
packages?: Package[];
|
|
22
28
|
}
|
|
29
|
+
|
|
30
|
+
export interface CommandContext {
|
|
31
|
+
args: string[];
|
|
32
|
+
options: Record<string, any>;
|
|
33
|
+
platform?: Platform;
|
|
34
|
+
appId?: string;
|
|
35
|
+
session?: Session;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface CommandResult {
|
|
39
|
+
success: boolean;
|
|
40
|
+
data?: any;
|
|
41
|
+
error?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CommandDefinition {
|
|
45
|
+
name: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
handler: (context: CommandContext) => Promise<CommandResult>;
|
|
48
|
+
options?: Record<
|
|
49
|
+
string,
|
|
50
|
+
{
|
|
51
|
+
hasValue?: boolean;
|
|
52
|
+
default?: any;
|
|
53
|
+
description?: string;
|
|
54
|
+
}
|
|
55
|
+
>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface BundleOptions {
|
|
59
|
+
dev?: boolean;
|
|
60
|
+
platform?: Platform;
|
|
61
|
+
bundleName?: string;
|
|
62
|
+
entryFile?: string;
|
|
63
|
+
output?: string;
|
|
64
|
+
sourcemap?: boolean;
|
|
65
|
+
taro?: boolean;
|
|
66
|
+
expo?: boolean;
|
|
67
|
+
rncli?: boolean;
|
|
68
|
+
disableHermes?: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface PublishOptions {
|
|
72
|
+
name?: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
metaInfo?: string;
|
|
75
|
+
packageId?: string;
|
|
76
|
+
packageVersion?: string;
|
|
77
|
+
minPackageVersion?: string;
|
|
78
|
+
maxPackageVersion?: string;
|
|
79
|
+
packageVersionRange?: string;
|
|
80
|
+
rollout?: number;
|
|
81
|
+
dryRun?: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface UploadOptions {
|
|
85
|
+
platform?: Platform;
|
|
86
|
+
filePath: string;
|
|
87
|
+
appId?: string;
|
|
88
|
+
version?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface WorkflowStep {
|
|
92
|
+
name: string;
|
|
93
|
+
description?: string;
|
|
94
|
+
execute: (context: CommandContext, previousResult?: any) => Promise<any>;
|
|
95
|
+
condition?: (context: CommandContext) => boolean;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface CustomWorkflow {
|
|
99
|
+
name: string;
|
|
100
|
+
description?: string;
|
|
101
|
+
steps: WorkflowStep[];
|
|
102
|
+
validate?: (context: CommandContext) => boolean;
|
|
103
|
+
options?: Record<
|
|
104
|
+
string,
|
|
105
|
+
{
|
|
106
|
+
hasValue?: boolean;
|
|
107
|
+
default?: any;
|
|
108
|
+
description?: string;
|
|
109
|
+
}
|
|
110
|
+
>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface CLIProvider {
|
|
114
|
+
bundle: (options: BundleOptions) => Promise<CommandResult>;
|
|
115
|
+
publish: (options: PublishOptions) => Promise<CommandResult>;
|
|
116
|
+
upload: (options: UploadOptions) => Promise<CommandResult>;
|
|
117
|
+
|
|
118
|
+
createApp: (name: string, platform: Platform) => Promise<CommandResult>;
|
|
119
|
+
listApps: (platform?: Platform) => Promise<CommandResult>;
|
|
120
|
+
getSelectedApp: (
|
|
121
|
+
platform?: Platform,
|
|
122
|
+
) => Promise<{ appId: string; platform: Platform }>;
|
|
123
|
+
|
|
124
|
+
listVersions: (appId: string) => Promise<CommandResult>;
|
|
125
|
+
updateVersion: (
|
|
126
|
+
appId: string,
|
|
127
|
+
versionId: string,
|
|
128
|
+
updates: Partial<Version>,
|
|
129
|
+
) => Promise<CommandResult>;
|
|
130
|
+
|
|
131
|
+
getPlatform: (platform?: Platform) => Promise<Platform>;
|
|
132
|
+
loadSession: () => Promise<Session>;
|
|
133
|
+
|
|
134
|
+
registerWorkflow: (workflow: CustomWorkflow) => void;
|
|
135
|
+
executeWorkflow: (
|
|
136
|
+
workflowName: string,
|
|
137
|
+
context: CommandContext,
|
|
138
|
+
) => Promise<CommandResult>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface CLIModule {
|
|
142
|
+
name: string;
|
|
143
|
+
version: string;
|
|
144
|
+
commands?: CommandDefinition[];
|
|
145
|
+
workflows?: CustomWorkflow[];
|
|
146
|
+
init?: (provider: CLIProvider) => void;
|
|
147
|
+
cleanup?: () => void;
|
|
148
|
+
}
|
package/src/user.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { question } from './utils';
|
|
2
|
-
import { post, get, replaceSession, saveSession, closeSession } from './api';
|
|
3
1
|
import crypto from 'crypto';
|
|
2
|
+
import type { CommandContext } from 'types';
|
|
3
|
+
import { closeSession, get, post, replaceSession, saveSession } from './api';
|
|
4
|
+
import { question } from './utils';
|
|
4
5
|
import { t } from './utils/i18n';
|
|
5
6
|
|
|
6
7
|
function md5(str: string) {
|
|
@@ -19,7 +20,7 @@ export const userCommands = {
|
|
|
19
20
|
await saveSession();
|
|
20
21
|
console.log(t('welcomeMessage', { name: info.name }));
|
|
21
22
|
},
|
|
22
|
-
logout: async () => {
|
|
23
|
+
logout: async (context: CommandContext) => {
|
|
23
24
|
await closeSession();
|
|
24
25
|
console.log(t('loggedOut'));
|
|
25
26
|
},
|
|
@@ -1,64 +1,74 @@
|
|
|
1
|
-
const Zip = require('./zip')
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const Zip = require('./zip');
|
|
2
|
+
const {
|
|
3
|
+
mapInfoResource,
|
|
4
|
+
findApkIconPath,
|
|
5
|
+
getBase64FromBuffer,
|
|
6
|
+
} = require('./utils');
|
|
7
|
+
const ManifestName = /^androidmanifest\.xml$/;
|
|
8
|
+
const ResourceName = /^resources\.arsc$/;
|
|
5
9
|
|
|
6
|
-
const ManifestXmlParser = require('./xml-parser/manifest')
|
|
7
|
-
const ResourceFinder = require('./resource-finder')
|
|
10
|
+
const ManifestXmlParser = require('./xml-parser/manifest');
|
|
11
|
+
const ResourceFinder = require('./resource-finder');
|
|
8
12
|
|
|
9
13
|
class ApkParser extends Zip {
|
|
10
14
|
/**
|
|
11
15
|
* parser for parsing .apk file
|
|
12
16
|
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
|
|
13
17
|
*/
|
|
14
|
-
constructor
|
|
15
|
-
super(file)
|
|
18
|
+
constructor(file) {
|
|
19
|
+
super(file);
|
|
16
20
|
if (!(this instanceof ApkParser)) {
|
|
17
|
-
return new ApkParser(file)
|
|
21
|
+
return new ApkParser(file);
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
|
-
parse
|
|
24
|
+
parse() {
|
|
21
25
|
return new Promise((resolve, reject) => {
|
|
22
|
-
this.getEntries([ManifestName, ResourceName])
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// parse resourceMap
|
|
32
|
-
resourceMap = this._parseResourceMap(buffers[ResourceName])
|
|
33
|
-
// update apkInfo with resourceMap
|
|
34
|
-
apkInfo = mapInfoResource(apkInfo, resourceMap)
|
|
35
|
-
|
|
36
|
-
// find icon path and parse icon
|
|
37
|
-
const iconPath = findApkIconPath(apkInfo)
|
|
38
|
-
if (iconPath) {
|
|
39
|
-
this.getEntry(iconPath).then(iconBuffer => {
|
|
40
|
-
apkInfo.icon = iconBuffer ? getBase64FromBuffer(iconBuffer) : null
|
|
41
|
-
resolve(apkInfo)
|
|
42
|
-
}).catch(e => {
|
|
43
|
-
apkInfo.icon = null
|
|
44
|
-
resolve(apkInfo)
|
|
45
|
-
console.warn('[Warning] failed to parse icon: ', e)
|
|
46
|
-
})
|
|
26
|
+
this.getEntries([ManifestName, ResourceName])
|
|
27
|
+
.then((buffers) => {
|
|
28
|
+
if (!buffers[ManifestName]) {
|
|
29
|
+
throw new Error("AndroidManifest.xml can't be found.");
|
|
30
|
+
}
|
|
31
|
+
let apkInfo = this._parseManifest(buffers[ManifestName]);
|
|
32
|
+
let resourceMap;
|
|
33
|
+
if (!buffers[ResourceName]) {
|
|
34
|
+
resolve(apkInfo);
|
|
47
35
|
} else {
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
// parse resourceMap
|
|
37
|
+
resourceMap = this._parseResourceMap(buffers[ResourceName]);
|
|
38
|
+
// update apkInfo with resourceMap
|
|
39
|
+
apkInfo = mapInfoResource(apkInfo, resourceMap);
|
|
40
|
+
|
|
41
|
+
// find icon path and parse icon
|
|
42
|
+
const iconPath = findApkIconPath(apkInfo);
|
|
43
|
+
if (iconPath) {
|
|
44
|
+
this.getEntry(iconPath)
|
|
45
|
+
.then((iconBuffer) => {
|
|
46
|
+
apkInfo.icon = iconBuffer
|
|
47
|
+
? getBase64FromBuffer(iconBuffer)
|
|
48
|
+
: null;
|
|
49
|
+
resolve(apkInfo);
|
|
50
|
+
})
|
|
51
|
+
.catch((e) => {
|
|
52
|
+
apkInfo.icon = null;
|
|
53
|
+
resolve(apkInfo);
|
|
54
|
+
console.warn('[Warning] failed to parse icon: ', e);
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
apkInfo.icon = null;
|
|
58
|
+
resolve(apkInfo);
|
|
59
|
+
}
|
|
50
60
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
})
|
|
61
|
+
})
|
|
62
|
+
.catch((e) => {
|
|
63
|
+
reject(e);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
56
66
|
}
|
|
57
67
|
/**
|
|
58
68
|
* Parse manifest
|
|
59
69
|
* @param {Buffer} buffer // manifest file's buffer
|
|
60
70
|
*/
|
|
61
|
-
_parseManifest
|
|
71
|
+
_parseManifest(buffer) {
|
|
62
72
|
try {
|
|
63
73
|
const parser = new ManifestXmlParser(buffer, {
|
|
64
74
|
ignore: [
|
|
@@ -66,25 +76,25 @@ class ApkParser extends Zip {
|
|
|
66
76
|
'application.service',
|
|
67
77
|
'application.receiver',
|
|
68
78
|
'application.provider',
|
|
69
|
-
'permission-group'
|
|
70
|
-
]
|
|
71
|
-
})
|
|
72
|
-
return parser.parse()
|
|
79
|
+
'permission-group',
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
return parser.parse();
|
|
73
83
|
} catch (e) {
|
|
74
|
-
throw new Error('Parse AndroidManifest.xml error: ', e)
|
|
84
|
+
throw new Error('Parse AndroidManifest.xml error: ', e);
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
87
|
/**
|
|
78
88
|
* Parse resourceMap
|
|
79
89
|
* @param {Buffer} buffer // resourceMap file's buffer
|
|
80
90
|
*/
|
|
81
|
-
_parseResourceMap
|
|
91
|
+
_parseResourceMap(buffer) {
|
|
82
92
|
try {
|
|
83
|
-
return new ResourceFinder().processResourceTable(buffer)
|
|
93
|
+
return new ResourceFinder().processResourceTable(buffer);
|
|
84
94
|
} catch (e) {
|
|
85
|
-
throw new Error('Parser resources.arsc error: ' + e)
|
|
95
|
+
throw new Error('Parser resources.arsc error: ' + e);
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
98
|
}
|
|
89
99
|
|
|
90
|
-
module.exports = ApkParser
|
|
100
|
+
module.exports = ApkParser;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
const Zip = require('./zip')
|
|
1
|
+
const Zip = require('./zip');
|
|
2
2
|
|
|
3
3
|
class AppParser extends Zip {
|
|
4
4
|
/**
|
|
5
5
|
* parser for parsing .apk file
|
|
6
6
|
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
|
|
7
7
|
*/
|
|
8
|
-
constructor
|
|
9
|
-
super(file)
|
|
8
|
+
constructor(file) {
|
|
9
|
+
super(file);
|
|
10
10
|
if (!(this instanceof AppParser)) {
|
|
11
|
-
return new AppParser(file)
|
|
11
|
+
return new AppParser(file);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
module.exports = AppParser
|
|
16
|
+
module.exports = AppParser;
|