appium-xcuitest-driver 11.3.1 → 11.4.0
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/CHANGELOG.md +6 -0
- package/npm-shrinkwrap.json +5 -5
- package/package.json +2 -1
- package/scripts/sign-wda.mjs +412 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [11.4.0](https://github.com/appium/appium-xcuitest-driver/compare/v11.3.1...v11.4.0) (2026-05-13)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* add resign task ([#2836](https://github.com/appium/appium-xcuitest-driver/issues/2836)) ([7dfca62](https://github.com/appium/appium-xcuitest-driver/commit/7dfca6298a0dd17b016d71793e465425bb04e59a))
|
|
6
|
+
|
|
1
7
|
## [11.3.1](https://github.com/appium/appium-xcuitest-driver/compare/v11.3.0...v11.3.1) (2026-05-12)
|
|
2
8
|
|
|
3
9
|
### Miscellaneous Chores
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-xcuitest-driver",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "appium-xcuitest-driver",
|
|
9
|
-
"version": "11.
|
|
9
|
+
"version": "11.4.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@appium/strongbox": "^1.0.0-rc.1",
|
|
@@ -652,9 +652,9 @@
|
|
|
652
652
|
}
|
|
653
653
|
},
|
|
654
654
|
"node_modules/appium-ios-tuntap": {
|
|
655
|
-
"version": "0.2.
|
|
656
|
-
"resolved": "https://registry.npmjs.org/appium-ios-tuntap/-/appium-ios-tuntap-0.2.
|
|
657
|
-
"integrity": "sha512-
|
|
655
|
+
"version": "0.2.3",
|
|
656
|
+
"resolved": "https://registry.npmjs.org/appium-ios-tuntap/-/appium-ios-tuntap-0.2.3.tgz",
|
|
657
|
+
"integrity": "sha512-rt8sZi66IeOSXyEclMsC+uSA1sO11PMAldztHPC1ipLkSwrahasvILy9AZ9wnPOzcCZ84TOQF3bpz8S4luJ4yA==",
|
|
658
658
|
"hasInstallScript": true,
|
|
659
659
|
"license": "Apache-2.0",
|
|
660
660
|
"optional": true,
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"xcuitest",
|
|
9
9
|
"xctest"
|
|
10
10
|
],
|
|
11
|
-
"version": "11.
|
|
11
|
+
"version": "11.4.0",
|
|
12
12
|
"author": "Appium Contributors",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"repository": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"tunnel-creation": "./scripts/tunnel-creation.mjs",
|
|
37
37
|
"download-wda": "./scripts/download-wda.mjs",
|
|
38
38
|
"download-wda-sim": "./scripts/download-wda-sim.mjs",
|
|
39
|
+
"sign-wda": "./scripts/sign-wda.mjs",
|
|
39
40
|
"image-mounter": "./scripts/image-mounter.mjs",
|
|
40
41
|
"list-real-devices": "./scripts/list-real-devices.mjs",
|
|
41
42
|
"cleanup-videos": "./scripts/cleanup-videos.mjs",
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import {fs, logger} from 'appium/support.js';
|
|
2
|
+
import {exec} from 'teen_process';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {pathToFileURL} from 'node:url';
|
|
6
|
+
import {mkdtemp, rm} from 'node:fs/promises';
|
|
7
|
+
import {Command} from 'commander';
|
|
8
|
+
|
|
9
|
+
const SCRIPT_NAME = 'sign-wda';
|
|
10
|
+
const RESIGNER_BINARY_NAME = 'resigner';
|
|
11
|
+
const MOBILEPROVISION_EXTENSION = '.mobileprovision';
|
|
12
|
+
const DEFAULT_PROFILE_DIR_CANDIDATES = [
|
|
13
|
+
path.join(os.homedir(), 'Library', 'Developer', 'Xcode', 'UserData', 'Provisioning Profiles'),
|
|
14
|
+
path.join(os.homedir(), 'Library', 'MobileDevice', 'Provisioning Profiles'),
|
|
15
|
+
];
|
|
16
|
+
const DEFAULT_WDA_BUNDLE_IDS = [
|
|
17
|
+
'com.facebook.WebDriverAgentRunner',
|
|
18
|
+
'com.facebook.WebDriverAgentRunner.xctrunner',
|
|
19
|
+
'com.facebook.WebDriverAgentLib',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const log = logger.getLogger(SCRIPT_NAME);
|
|
23
|
+
|
|
24
|
+
class RunCmd {
|
|
25
|
+
/**
|
|
26
|
+
* Check if the resginer binary is available in the PATH.
|
|
27
|
+
* @returns {Promise<void>} Whether the resigner binary is available in the local environment
|
|
28
|
+
*/
|
|
29
|
+
async requireResignerBinary() {
|
|
30
|
+
try {
|
|
31
|
+
await fs.which(RESIGNER_BINARY_NAME);
|
|
32
|
+
} catch {
|
|
33
|
+
throw new Error('Resigner binary is not available in the PATH.');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RunInspectWDA extends RunCmd {
|
|
40
|
+
/**
|
|
41
|
+
* Run resigner inspect on the signed WDA and return the output.
|
|
42
|
+
* @param {InspectWDAOptions} options
|
|
43
|
+
* @returns {Promise<void>}
|
|
44
|
+
*/
|
|
45
|
+
async inspect(options) {
|
|
46
|
+
if (!(await fs.exists(options.wdaPath))) {
|
|
47
|
+
throw new Error(`WDA path does not exist: ${options.wdaPath}`);
|
|
48
|
+
}
|
|
49
|
+
await this.requireResignerBinary();
|
|
50
|
+
const inspectResult = await inspectWDAWithResigner(options.wdaPath);
|
|
51
|
+
if (inspectResult) {
|
|
52
|
+
log.info(`Resigner inspect result:\n---\n${inspectResult}`);
|
|
53
|
+
} else {
|
|
54
|
+
log.info('Resigner inspect finished, but no output was returned.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class RunSignWDA extends RunCmd {
|
|
60
|
+
/**
|
|
61
|
+
* Run resigner to sign the WDA.
|
|
62
|
+
* @param {SignWDAOptions} options
|
|
63
|
+
* @returns {Promise<void>}
|
|
64
|
+
*/
|
|
65
|
+
async sign(options) {
|
|
66
|
+
if (!(await fs.exists(options.wdaPath))) {
|
|
67
|
+
throw new Error(`WDA path does not exist: ${options.wdaPath}`);
|
|
68
|
+
}
|
|
69
|
+
await this.requireResignerBinary();
|
|
70
|
+
const resolvedProfileDir = await resolveProfileDir(options.profileDir);
|
|
71
|
+
|
|
72
|
+
let p12File = options.p12File;
|
|
73
|
+
let tempDir;
|
|
74
|
+
let p12Password = options.p12Password;
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
// If cert and key provided, convert to p12 with auto-generated password
|
|
78
|
+
if (options.p12Cert && options.p12Key) {
|
|
79
|
+
const generatedPassword = generateRandomPassword();
|
|
80
|
+
const result = await convertCertAndKeyToP12(options.p12Cert, options.p12Key, generatedPassword);
|
|
81
|
+
p12File = result.p12File;
|
|
82
|
+
tempDir = result.tempDir;
|
|
83
|
+
p12Password = generatedPassword;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!p12File) {
|
|
87
|
+
throw new Error('No p12 file available for signing');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
await signWDAWithResigner(options.wdaPath, {
|
|
91
|
+
p12File,
|
|
92
|
+
p12Password,
|
|
93
|
+
profileDir: resolvedProfileDir,
|
|
94
|
+
bundleId: options.bundleId,
|
|
95
|
+
});
|
|
96
|
+
} finally {
|
|
97
|
+
// Clean up temp directory if it was created
|
|
98
|
+
if (tempDir) {
|
|
99
|
+
try {
|
|
100
|
+
await rm(tempDir, {recursive: true, force: true});
|
|
101
|
+
log.info(`Cleaned up temporary directory: ${tempDir}`);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
log.warn(`Failed to clean up temporary directory ${tempDir}: ${err.message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Generate a random password for temporary .p12 files.
|
|
112
|
+
* @returns {string} A random 12-character alphanumeric password
|
|
113
|
+
*/
|
|
114
|
+
function generateRandomPassword() {
|
|
115
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
116
|
+
let password = '';
|
|
117
|
+
for (let i = 0; i < 12; i++) {
|
|
118
|
+
password += chars[Math.floor(Math.random() * chars.length)];
|
|
119
|
+
}
|
|
120
|
+
return password;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Convert .cer and .key files to a .p12 file.
|
|
125
|
+
* @param {string} certPath - Path to the .cer certificate file
|
|
126
|
+
* @param {string} keyPath - Path to the .key private key file
|
|
127
|
+
* @param {string} p12Password - Password to protect the .p12 file
|
|
128
|
+
* @returns {Promise<{p12File: string, tempDir: string}>} Path to the generated .p12 and temp directory
|
|
129
|
+
*/
|
|
130
|
+
async function convertCertAndKeyToP12(certPath, keyPath, p12Password) {
|
|
131
|
+
// Validate input files exist
|
|
132
|
+
if (!(await fs.exists(certPath))) {
|
|
133
|
+
throw new Error(`Certificate file does not exist: ${certPath}`);
|
|
134
|
+
}
|
|
135
|
+
if (!(await fs.exists(keyPath))) {
|
|
136
|
+
throw new Error(`Private key file does not exist: ${keyPath}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
await fs.which('openssl');
|
|
141
|
+
} catch {
|
|
142
|
+
throw new Error('OpenSSL binary is not available in the PATH. ' +
|
|
143
|
+
'It is required to convert .cer and .key files to .p12 format.');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Create temp directory
|
|
147
|
+
const tempDir = await mkdtemp(path.join(os.tmpdir(), 'wda-sign-'));
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const certPem = path.join(tempDir, 'certificate.pem');
|
|
151
|
+
const p12File = path.join(tempDir, 'certificate.p12');
|
|
152
|
+
|
|
153
|
+
// Convert .cer to .pem
|
|
154
|
+
log.info(`Converting certificate from ${certPath} to PEM format`);
|
|
155
|
+
await exec('openssl', [
|
|
156
|
+
'x509',
|
|
157
|
+
'-in', certPath,
|
|
158
|
+
'-inform', 'DER',
|
|
159
|
+
'-out', certPem,
|
|
160
|
+
]);
|
|
161
|
+
|
|
162
|
+
// Convert to .p12
|
|
163
|
+
log.info(`Creating .p12 file from certificate and key`);
|
|
164
|
+
await exec('openssl', [
|
|
165
|
+
'pkcs12',
|
|
166
|
+
'-export',
|
|
167
|
+
'-in', certPem,
|
|
168
|
+
'-inkey', keyPath,
|
|
169
|
+
'-out', p12File,
|
|
170
|
+
'-passout', `pass:${p12Password}`,
|
|
171
|
+
]);
|
|
172
|
+
|
|
173
|
+
log.info(`Successfully created temporary .p12 file: ${p12File}`);
|
|
174
|
+
return {p12File, tempDir};
|
|
175
|
+
} catch (err) {
|
|
176
|
+
// Clean up temp dir on error
|
|
177
|
+
try {
|
|
178
|
+
await rm(tempDir, {recursive: true, force: true});
|
|
179
|
+
} catch {}
|
|
180
|
+
throw err;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Validate a provisioning profile directory.
|
|
186
|
+
* @param {string} dir
|
|
187
|
+
* @param {string} source
|
|
188
|
+
* @returns {Promise<string>}
|
|
189
|
+
*/
|
|
190
|
+
async function validateProfileDir(dir, source) {
|
|
191
|
+
if (!(await fs.exists(dir))) {
|
|
192
|
+
throw new Error(`${source} provisioning profile directory does not exist: ${dir}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let entries;
|
|
196
|
+
try {
|
|
197
|
+
entries = await fs.readdir(dir);
|
|
198
|
+
} catch {
|
|
199
|
+
throw new Error(`${source} provisioning profile directory is not a readable directory: ${dir}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!entries.some((name) => name.toLowerCase().endsWith(MOBILEPROVISION_EXTENSION))) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`${source} provisioning profile directory does not contain any ${MOBILEPROVISION_EXTENSION} files: ${dir}`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return dir;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Resolve the provisioning profile directory.
|
|
213
|
+
* If user provided --profile-dir, validate and use it.
|
|
214
|
+
* Otherwise discover from known defaults in priority order.
|
|
215
|
+
* @param {string | undefined} profileDir
|
|
216
|
+
* @returns {Promise<string>}
|
|
217
|
+
*/
|
|
218
|
+
async function resolveProfileDir(profileDir) {
|
|
219
|
+
if (profileDir) {
|
|
220
|
+
return await validateProfileDir(profileDir, 'Provided');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for (const candidate of DEFAULT_PROFILE_DIR_CANDIDATES) {
|
|
224
|
+
if (!(await fs.exists(candidate))) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
await validateProfileDir(candidate, 'Discovered');
|
|
229
|
+
log.info(`Using discovered provisioning profile directory: ${candidate}`);
|
|
230
|
+
return candidate;
|
|
231
|
+
} catch {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
throw new Error(
|
|
237
|
+
`No provisioning profile directory could be discovered. ` +
|
|
238
|
+
`Please provide --profile-dir explicitly. Checked: ${DEFAULT_PROFILE_DIR_CANDIDATES.join(', ')}`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Run resigner to sign WDA
|
|
244
|
+
* @param {string} wdaPath
|
|
245
|
+
* @param {SignOptions} options
|
|
246
|
+
* @returns {Promise<void>}
|
|
247
|
+
*/
|
|
248
|
+
async function signWDAWithResigner(wdaPath, options) {
|
|
249
|
+
const args = [
|
|
250
|
+
'--p12-file', options.p12File,
|
|
251
|
+
'--profile', options.profileDir,
|
|
252
|
+
'--force',
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
if (options.bundleId) {
|
|
256
|
+
args.push(
|
|
257
|
+
...[
|
|
258
|
+
// To re-apply the same mapping again for past failure cases for safe.
|
|
259
|
+
options.bundleId,
|
|
260
|
+
...DEFAULT_WDA_BUNDLE_IDS,
|
|
261
|
+
].flatMap((bundleId) => [
|
|
262
|
+
'--bundle-id-remap',
|
|
263
|
+
`${bundleId}=${options.bundleId}`,
|
|
264
|
+
])
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
args.push(wdaPath);
|
|
269
|
+
|
|
270
|
+
log.info(`Running resigner to sign ${wdaPath}`);
|
|
271
|
+
await exec(RESIGNER_BINARY_NAME, args, {
|
|
272
|
+
env: {
|
|
273
|
+
...process.env,
|
|
274
|
+
P12_PASSWORD: options.p12Password,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
log.info('WDA signed successfully');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Run resigner inspect on the signed WDA and return the output.
|
|
282
|
+
* @param {string} wdaPath
|
|
283
|
+
* @returns {Promise<string>}
|
|
284
|
+
*/
|
|
285
|
+
async function inspectWDAWithResigner(wdaPath) {
|
|
286
|
+
log.info(`Inspecting signed WDA at ${wdaPath}`);
|
|
287
|
+
const {stdout} = await exec(RESIGNER_BINARY_NAME, ['--inspect', wdaPath]);
|
|
288
|
+
return String(stdout || '').trim();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function main() {
|
|
292
|
+
const program = new Command();
|
|
293
|
+
|
|
294
|
+
program
|
|
295
|
+
.name('appium driver run xcuitest sign-wda')
|
|
296
|
+
.description('Sign a WebDriverAgentRunner app bundle with code signing certificate')
|
|
297
|
+
.requiredOption('--wda-path <path>', 'Path to the WebDriverAgentRunner.app bundle to sign')
|
|
298
|
+
.option('--inspect', 'Run resigner inspect only (no signing)')
|
|
299
|
+
.option('--p12-file <path>', 'Path to the .p12 signing certificate file (requires P12_PASSWORD env var; mutually exclusive with --p12-cert/--p12-key)')
|
|
300
|
+
.option('--p12-cert <path>', 'Path to the .cer certificate file from Apple Developer portal (auto-converted to .p12 with generated password; mutually exclusive with --p12-file; must use with --p12-key)')
|
|
301
|
+
.option('--p12-key <path>', 'Path to the .key private key file from Apple Developer portal (auto-converted to .p12 with generated password; mutually exclusive with --p12-file; must use with --p12-cert)')
|
|
302
|
+
.option('--profile-dir <path>', 'Directory containing provisioning profiles (auto-discovered if omitted)')
|
|
303
|
+
.option('--bundle-id <id>', 'Target bundle ID for remapping (e.g., com.example.wda)')
|
|
304
|
+
.addHelpText(
|
|
305
|
+
'after',
|
|
306
|
+
`
|
|
307
|
+
EXAMPLES:
|
|
308
|
+
# Sign downloaded WDA with .p12 certificate (requires P12_PASSWORD)
|
|
309
|
+
P12_PASSWORD=mypassword appium driver run xcuitest sign-wda -- --wda-path ./wda-real/WebDriverAgentRunner-Runner.app \
|
|
310
|
+
--p12-file ~/sign.p12
|
|
311
|
+
|
|
312
|
+
# Sign WDA with .cer and .key files (auto-converted, no password needed!)
|
|
313
|
+
appium driver run xcuitest sign-wda -- --wda-path ./wda-real/WebDriverAgentRunner-Runner.app \
|
|
314
|
+
--p12-cert ~/certificate.cer \
|
|
315
|
+
--p12-key ~/private.key
|
|
316
|
+
|
|
317
|
+
# Sign WDA and remap bundle ID with .p12 certificate (requires P12_PASSWORD)
|
|
318
|
+
P12_PASSWORD=mypassword appium driver run xcuitest sign-wda -- --wda-path ./wda-real/WebDriverAgentRunner-Runner.app \
|
|
319
|
+
--p12-file ~/sign.p12 \
|
|
320
|
+
--bundle-id com.example.wda
|
|
321
|
+
|
|
322
|
+
# Sign WDA with specified provisioning profile directory (cert+key approach)
|
|
323
|
+
appium driver run xcuitest sign-wda -- --wda-path ./wda-real/WebDriverAgentRunner-Runner.app \
|
|
324
|
+
--p12-cert ~/certificate.cer \
|
|
325
|
+
--p12-key ~/private.key \
|
|
326
|
+
--profile-dir /path/to/your/provisioning/profiles
|
|
327
|
+
|
|
328
|
+
# Inspect a WDA app without signing
|
|
329
|
+
appium driver run xcuitest sign-wda -- --wda-path ./wda-real/WebDriverAgentRunner-Runner.app --inspect`,
|
|
330
|
+
)
|
|
331
|
+
.action(async (options) => {
|
|
332
|
+
if (options.inspect) {
|
|
333
|
+
new RunInspectWDA().inspect({
|
|
334
|
+
wdaPath: options.wdaPath,
|
|
335
|
+
});
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const p12Password = process.env.P12_PASSWORD;
|
|
340
|
+
|
|
341
|
+
// Validate that either --p12-file OR (--p12-cert AND --p12-key) is provided
|
|
342
|
+
const hasP12File = !!options.p12File;
|
|
343
|
+
const hasCertAndKey = !!(options.p12Cert && options.p12Key);
|
|
344
|
+
|
|
345
|
+
if (!hasP12File && !hasCertAndKey) {
|
|
346
|
+
throw new Error(
|
|
347
|
+
`Must provide either --p12-file or both --p12-cert and --p12-key for signing mode`
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (hasP12File && hasCertAndKey) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
`Cannot provide both --p12-file and --p12-cert/--p12-key; use one approach`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if ((options.p12Cert && !options.p12Key) || (!options.p12Cert && options.p12Key)) {
|
|
358
|
+
throw new Error(
|
|
359
|
+
`Both --p12-cert and --p12-key must be provided together`
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// P12_PASSWORD is only required when using --p12-file
|
|
364
|
+
if (hasP12File && !p12Password) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
`Missing required option for signing mode: P12_PASSWORD env var (required when using --p12-file)`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
await new RunSignWDA().sign({
|
|
371
|
+
wdaPath: options.wdaPath,
|
|
372
|
+
p12File: options.p12File,
|
|
373
|
+
p12Cert: options.p12Cert,
|
|
374
|
+
p12Key: options.p12Key,
|
|
375
|
+
p12Password: p12Password || '',
|
|
376
|
+
profileDir: options.profileDir,
|
|
377
|
+
bundleId: options.bundleId,
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
await program.parseAsync(process.argv);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const isMainModule =
|
|
385
|
+
Boolean(process.argv[1]) && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
386
|
+
if (isMainModule) {
|
|
387
|
+
await main();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* @typedef {Object} SignOptions
|
|
392
|
+
* @property {string} p12File
|
|
393
|
+
* @property {string} p12Password
|
|
394
|
+
* @property {string} profileDir
|
|
395
|
+
* @property {string | undefined} [bundleId]
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* @typedef {Object} SignWDAOptions
|
|
400
|
+
* @property {string} wdaPath
|
|
401
|
+
* @property {string | undefined} [p12File]
|
|
402
|
+
* @property {string | undefined} [p12Cert]
|
|
403
|
+
* @property {string | undefined} [p12Key]
|
|
404
|
+
* @property {string} p12Password
|
|
405
|
+
* @property {string | undefined} [profileDir]
|
|
406
|
+
* @property {string | undefined} [bundleId]
|
|
407
|
+
*/
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @typedef {Object} InspectWDAOptions
|
|
411
|
+
* @property {string} wdaPath
|
|
412
|
+
*/
|