web-ext 6.8.0 → 7.0.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/README.md +17 -8
- package/bin/web-ext.js +13 -0
- package/index.js +12 -0
- package/lib/cmd/build.js +226 -0
- package/lib/cmd/build.js.map +1 -0
- package/lib/cmd/docs.js +16 -0
- package/lib/cmd/docs.js.map +1 -0
- package/lib/cmd/index.js +47 -0
- package/lib/cmd/index.js.map +1 -0
- package/lib/cmd/lint.js +50 -0
- package/lib/cmd/lint.js.map +1 -0
- package/lib/cmd/run.js +191 -0
- package/lib/cmd/run.js.map +1 -0
- package/lib/cmd/sign.js +140 -0
- package/lib/cmd/sign.js.map +1 -0
- package/lib/config.js +144 -0
- package/lib/config.js.map +1 -0
- package/{src → lib}/errors.js +26 -35
- package/lib/errors.js.map +1 -0
- package/lib/extension-runners/base.js +2 -0
- package/lib/extension-runners/base.js.map +1 -0
- package/{src → lib}/extension-runners/chromium.js +121 -178
- package/lib/extension-runners/chromium.js.map +1 -0
- package/{src → lib}/extension-runners/firefox-android.js +168 -326
- package/lib/extension-runners/firefox-android.js.map +1 -0
- package/{src → lib}/extension-runners/firefox-desktop.js +73 -114
- package/lib/extension-runners/firefox-desktop.js.map +1 -0
- package/lib/extension-runners/index.js +311 -0
- package/lib/extension-runners/index.js.map +1 -0
- package/lib/firefox/index.js +362 -0
- package/lib/firefox/index.js.map +1 -0
- package/lib/firefox/package-identifiers.js +5 -0
- package/lib/firefox/package-identifiers.js.map +1 -0
- package/{src → lib}/firefox/preferences.js +27 -70
- package/lib/firefox/preferences.js.map +1 -0
- package/{src → lib}/firefox/rdp-client.js +98 -105
- package/lib/firefox/rdp-client.js.map +1 -0
- package/{src → lib}/firefox/remote.js +55 -129
- package/lib/firefox/remote.js.map +1 -0
- package/lib/main.js +9 -0
- package/lib/main.js.map +1 -0
- package/lib/program.js +657 -0
- package/lib/program.js.map +1 -0
- package/lib/util/adb.js +322 -0
- package/lib/util/adb.js.map +1 -0
- package/lib/util/artifacts.js +52 -0
- package/lib/util/artifacts.js.map +1 -0
- package/lib/util/desktop-notifier.js +27 -0
- package/lib/util/desktop-notifier.js.map +1 -0
- package/{src → lib}/util/file-exists.js +7 -14
- package/lib/util/file-exists.js.map +1 -0
- package/{src → lib}/util/file-filter.js +31 -59
- package/lib/util/file-filter.js.map +1 -0
- package/lib/util/is-directory.js +20 -0
- package/lib/util/is-directory.js.map +1 -0
- package/lib/util/logger.js +79 -0
- package/lib/util/logger.js.map +1 -0
- package/{src → lib}/util/manifest.js +18 -50
- package/lib/util/manifest.js.map +1 -0
- package/{src → lib}/util/promisify.js +6 -9
- package/lib/util/promisify.js.map +1 -0
- package/{src → lib}/util/stdin.js +3 -7
- package/lib/util/stdin.js.map +1 -0
- package/{src → lib}/util/temp-dir.js +47 -52
- package/lib/util/temp-dir.js.map +1 -0
- package/lib/util/updates.js +16 -0
- package/lib/util/updates.js.map +1 -0
- package/lib/watcher.js +78 -0
- package/lib/watcher.js.map +1 -0
- package/package.json +50 -52
- package/CODE_OF_CONDUCT.md +0 -10
- package/bin/web-ext +0 -7
- package/dist/web-ext.js +0 -2
- package/index.mjs +0 -13
- package/src/cmd/build.js +0 -319
- package/src/cmd/docs.js +0 -33
- package/src/cmd/index.js +0 -57
- package/src/cmd/lint.js +0 -102
- package/src/cmd/run.js +0 -266
- package/src/cmd/sign.js +0 -198
- package/src/config.js +0 -187
- package/src/extension-runners/base.js +0 -40
- package/src/extension-runners/index.js +0 -381
- package/src/firefox/index.js +0 -541
- package/src/firefox/package-identifiers.js +0 -14
- package/src/main.js +0 -19
- package/src/program.js +0 -765
- package/src/util/adb.js +0 -433
- package/src/util/artifacts.js +0 -69
- package/src/util/desktop-notifier.js +0 -41
- package/src/util/is-directory.js +0 -23
- package/src/util/logger.js +0 -131
- package/src/util/updates.js +0 -21
- package/src/watcher.js +0 -115
package/lib/cmd/run.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { fs } from 'mz';
|
|
2
|
+
import defaultBuildExtension from './build.js';
|
|
3
|
+
import { showDesktopNotification as defaultDesktopNotifications } from '../util/desktop-notifier.js';
|
|
4
|
+
import * as defaultFirefoxApp from '../firefox/index.js';
|
|
5
|
+
import { connectWithMaxRetries as defaultFirefoxClient } from '../firefox/remote.js';
|
|
6
|
+
import { createLogger } from '../util/logger.js';
|
|
7
|
+
import defaultGetValidatedManifest from '../util/manifest.js';
|
|
8
|
+
import { UsageError } from '../errors.js';
|
|
9
|
+
import { createExtensionRunner, defaultReloadStrategy, MultiExtensionRunner as DefaultMultiExtensionRunner } from '../extension-runners/index.js'; // Import objects that are only used as Flow types.
|
|
10
|
+
|
|
11
|
+
const log = createLogger(import.meta.url); // Run command types and implementation.
|
|
12
|
+
|
|
13
|
+
export default async function run({
|
|
14
|
+
artifactsDir,
|
|
15
|
+
browserConsole = false,
|
|
16
|
+
pref,
|
|
17
|
+
firefox,
|
|
18
|
+
firefoxProfile,
|
|
19
|
+
profileCreateIfMissing,
|
|
20
|
+
keepProfileChanges = false,
|
|
21
|
+
ignoreFiles,
|
|
22
|
+
noInput = false,
|
|
23
|
+
noReload = false,
|
|
24
|
+
preInstall = false,
|
|
25
|
+
sourceDir,
|
|
26
|
+
watchFile,
|
|
27
|
+
watchIgnored,
|
|
28
|
+
startUrl,
|
|
29
|
+
target,
|
|
30
|
+
args,
|
|
31
|
+
// Android CLI options.
|
|
32
|
+
adbBin,
|
|
33
|
+
adbHost,
|
|
34
|
+
adbPort,
|
|
35
|
+
adbDevice,
|
|
36
|
+
adbDiscoveryTimeout,
|
|
37
|
+
adbRemoveOldArtifacts,
|
|
38
|
+
firefoxApk,
|
|
39
|
+
firefoxApkComponent,
|
|
40
|
+
// Chromium CLI options.
|
|
41
|
+
chromiumBinary,
|
|
42
|
+
chromiumProfile
|
|
43
|
+
}, {
|
|
44
|
+
buildExtension = defaultBuildExtension,
|
|
45
|
+
desktopNotifications = defaultDesktopNotifications,
|
|
46
|
+
firefoxApp = defaultFirefoxApp,
|
|
47
|
+
firefoxClient = defaultFirefoxClient,
|
|
48
|
+
reloadStrategy = defaultReloadStrategy,
|
|
49
|
+
MultiExtensionRunner = DefaultMultiExtensionRunner,
|
|
50
|
+
getValidatedManifest = defaultGetValidatedManifest
|
|
51
|
+
} = {}) {
|
|
52
|
+
log.info(`Running web extension from ${sourceDir}`);
|
|
53
|
+
|
|
54
|
+
if (preInstall) {
|
|
55
|
+
log.info('Disabled auto-reloading because it\'s not possible with ' + '--pre-install');
|
|
56
|
+
noReload = true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (watchFile != null && (!Array.isArray(watchFile) || !watchFile.every(el => typeof el === 'string'))) {
|
|
60
|
+
throw new UsageError('Unexpected watchFile type');
|
|
61
|
+
} // Create an alias for --pref since it has been transformed into an
|
|
62
|
+
// object containing one or more preferences.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const customPrefs = pref;
|
|
66
|
+
const manifestData = await getValidatedManifest(sourceDir);
|
|
67
|
+
const profileDir = firefoxProfile || chromiumProfile;
|
|
68
|
+
|
|
69
|
+
if (profileCreateIfMissing) {
|
|
70
|
+
if (!profileDir) {
|
|
71
|
+
throw new UsageError('--profile-create-if-missing requires ' + '--firefox-profile or --chromium-profile');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const isDir = fs.existsSync(profileDir);
|
|
75
|
+
|
|
76
|
+
if (isDir) {
|
|
77
|
+
log.info(`Profile directory ${profileDir} already exists`);
|
|
78
|
+
} else {
|
|
79
|
+
log.info(`Profile directory not found. Creating directory ${profileDir}`);
|
|
80
|
+
await fs.mkdir(profileDir);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const runners = [];
|
|
85
|
+
const commonRunnerParams = {
|
|
86
|
+
// Common options.
|
|
87
|
+
extensions: [{
|
|
88
|
+
sourceDir,
|
|
89
|
+
manifestData
|
|
90
|
+
}],
|
|
91
|
+
keepProfileChanges,
|
|
92
|
+
startUrl,
|
|
93
|
+
args,
|
|
94
|
+
desktopNotifications
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
if (!target || target.length === 0 || target.includes('firefox-desktop')) {
|
|
98
|
+
const firefoxDesktopRunnerParams = { ...commonRunnerParams,
|
|
99
|
+
// Firefox specific CLI options.
|
|
100
|
+
firefoxBinary: firefox,
|
|
101
|
+
profilePath: firefoxProfile,
|
|
102
|
+
customPrefs,
|
|
103
|
+
browserConsole,
|
|
104
|
+
preInstall,
|
|
105
|
+
// Firefox runner injected dependencies.
|
|
106
|
+
firefoxApp,
|
|
107
|
+
firefoxClient
|
|
108
|
+
};
|
|
109
|
+
const firefoxDesktopRunner = await createExtensionRunner({
|
|
110
|
+
target: 'firefox-desktop',
|
|
111
|
+
params: firefoxDesktopRunnerParams
|
|
112
|
+
});
|
|
113
|
+
runners.push(firefoxDesktopRunner);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (target && target.includes('firefox-android')) {
|
|
117
|
+
const firefoxAndroidRunnerParams = { ...commonRunnerParams,
|
|
118
|
+
// Firefox specific CLI options.
|
|
119
|
+
profilePath: firefoxProfile,
|
|
120
|
+
customPrefs,
|
|
121
|
+
browserConsole,
|
|
122
|
+
preInstall,
|
|
123
|
+
firefoxApk,
|
|
124
|
+
firefoxApkComponent,
|
|
125
|
+
adbDevice,
|
|
126
|
+
adbHost,
|
|
127
|
+
adbPort,
|
|
128
|
+
adbBin,
|
|
129
|
+
adbDiscoveryTimeout,
|
|
130
|
+
adbRemoveOldArtifacts,
|
|
131
|
+
// Injected dependencies.
|
|
132
|
+
firefoxApp,
|
|
133
|
+
firefoxClient,
|
|
134
|
+
desktopNotifications: defaultDesktopNotifications,
|
|
135
|
+
buildSourceDir: (extensionSourceDir, tmpArtifactsDir) => {
|
|
136
|
+
return buildExtension({
|
|
137
|
+
sourceDir: extensionSourceDir,
|
|
138
|
+
ignoreFiles,
|
|
139
|
+
asNeeded: false,
|
|
140
|
+
// Use a separate temporary directory for building the extension zip file
|
|
141
|
+
// that we are going to upload on the android device.
|
|
142
|
+
artifactsDir: tmpArtifactsDir
|
|
143
|
+
}, {
|
|
144
|
+
// Suppress the message usually logged by web-ext build.
|
|
145
|
+
showReadyMessage: false
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const firefoxAndroidRunner = await createExtensionRunner({
|
|
150
|
+
target: 'firefox-android',
|
|
151
|
+
params: firefoxAndroidRunnerParams
|
|
152
|
+
});
|
|
153
|
+
runners.push(firefoxAndroidRunner);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (target && target.includes('chromium')) {
|
|
157
|
+
const chromiumRunnerParams = { ...commonRunnerParams,
|
|
158
|
+
chromiumBinary,
|
|
159
|
+
chromiumProfile
|
|
160
|
+
};
|
|
161
|
+
const chromiumRunner = await createExtensionRunner({
|
|
162
|
+
target: 'chromium',
|
|
163
|
+
params: chromiumRunnerParams
|
|
164
|
+
});
|
|
165
|
+
runners.push(chromiumRunner);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const extensionRunner = new MultiExtensionRunner({
|
|
169
|
+
desktopNotifications,
|
|
170
|
+
runners
|
|
171
|
+
});
|
|
172
|
+
await extensionRunner.run();
|
|
173
|
+
|
|
174
|
+
if (noReload) {
|
|
175
|
+
log.info('Automatic extension reloading has been disabled');
|
|
176
|
+
} else {
|
|
177
|
+
log.info('The extension will reload if any source file changes');
|
|
178
|
+
reloadStrategy({
|
|
179
|
+
extensionRunner,
|
|
180
|
+
sourceDir,
|
|
181
|
+
watchFile,
|
|
182
|
+
watchIgnored,
|
|
183
|
+
artifactsDir,
|
|
184
|
+
ignoreFiles,
|
|
185
|
+
noInput
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return extensionRunner;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","names":["fs","defaultBuildExtension","showDesktopNotification","defaultDesktopNotifications","defaultFirefoxApp","connectWithMaxRetries","defaultFirefoxClient","createLogger","defaultGetValidatedManifest","UsageError","createExtensionRunner","defaultReloadStrategy","MultiExtensionRunner","DefaultMultiExtensionRunner","log","import","meta","url","run","artifactsDir","browserConsole","pref","firefox","firefoxProfile","profileCreateIfMissing","keepProfileChanges","ignoreFiles","noInput","noReload","preInstall","sourceDir","watchFile","watchIgnored","startUrl","target","args","adbBin","adbHost","adbPort","adbDevice","adbDiscoveryTimeout","adbRemoveOldArtifacts","firefoxApk","firefoxApkComponent","chromiumBinary","chromiumProfile","buildExtension","desktopNotifications","firefoxApp","firefoxClient","reloadStrategy","getValidatedManifest","info","Array","isArray","every","el","customPrefs","manifestData","profileDir","isDir","existsSync","mkdir","runners","commonRunnerParams","extensions","length","includes","firefoxDesktopRunnerParams","firefoxBinary","profilePath","firefoxDesktopRunner","params","push","firefoxAndroidRunnerParams","buildSourceDir","extensionSourceDir","tmpArtifactsDir","asNeeded","showReadyMessage","firefoxAndroidRunner","chromiumRunnerParams","chromiumRunner","extensionRunner"],"sources":["../../src/cmd/run.js"],"sourcesContent":["/* @flow */\nimport { fs } from 'mz';\n\nimport defaultBuildExtension from './build.js';\nimport {\n showDesktopNotification as defaultDesktopNotifications,\n} from '../util/desktop-notifier.js';\nimport * as defaultFirefoxApp from '../firefox/index.js';\nimport {\n connectWithMaxRetries as defaultFirefoxClient,\n} from '../firefox/remote.js';\nimport {createLogger} from '../util/logger.js';\nimport defaultGetValidatedManifest from '../util/manifest.js';\nimport {UsageError} from '../errors.js';\nimport {\n createExtensionRunner,\n defaultReloadStrategy,\n MultiExtensionRunner as DefaultMultiExtensionRunner,\n} from '../extension-runners/index.js';\n// Import objects that are only used as Flow types.\nimport type {FirefoxPreferences} from '../firefox/preferences.js';\n\nconst log = createLogger(import.meta.url);\n\n\n// Run command types and implementation.\n\nexport type CmdRunParams = {|\n artifactsDir: string,\n browserConsole: boolean,\n pref?: FirefoxPreferences,\n firefox: string,\n firefoxProfile?: string,\n profileCreateIfMissing?: boolean,\n ignoreFiles?: Array<string>,\n keepProfileChanges: boolean,\n noInput?: boolean,\n noReload: boolean,\n preInstall: boolean,\n sourceDir: string,\n watchFile?: Array<string>,\n watchIgnored?: Array<string>,\n startUrl?: Array<string>,\n target?: Array<string>,\n args?: Array<string>,\n\n // Android CLI options.\n adbBin?: string,\n adbHost?: string,\n adbPort?: string,\n adbDevice?: string,\n adbDiscoveryTimeout?: number,\n adbRemoveOldArtifacts?: boolean,\n firefoxApk?: string,\n firefoxApkComponent?: string,\n\n // Chromium Desktop CLI options.\n chromiumBinary?: string,\n chromiumProfile?: string,\n|};\n\nexport type CmdRunOptions = {\n buildExtension: typeof defaultBuildExtension,\n desktopNotifications: typeof defaultDesktopNotifications,\n firefoxApp: typeof defaultFirefoxApp,\n firefoxClient: typeof defaultFirefoxClient,\n reloadStrategy: typeof defaultReloadStrategy,\n shouldExitProgram?: boolean,\n MultiExtensionRunner?: typeof DefaultMultiExtensionRunner,\n getValidatedManifest?: typeof defaultGetValidatedManifest,\n};\n\nexport default async function run(\n {\n artifactsDir,\n browserConsole = false,\n pref,\n firefox,\n firefoxProfile,\n profileCreateIfMissing,\n keepProfileChanges = false,\n ignoreFiles,\n noInput = false,\n noReload = false,\n preInstall = false,\n sourceDir,\n watchFile,\n watchIgnored,\n startUrl,\n target,\n args,\n // Android CLI options.\n adbBin,\n adbHost,\n adbPort,\n adbDevice,\n adbDiscoveryTimeout,\n adbRemoveOldArtifacts,\n firefoxApk,\n firefoxApkComponent,\n // Chromium CLI options.\n chromiumBinary,\n chromiumProfile,\n }: CmdRunParams,\n {\n buildExtension = defaultBuildExtension,\n desktopNotifications = defaultDesktopNotifications,\n firefoxApp = defaultFirefoxApp,\n firefoxClient = defaultFirefoxClient,\n reloadStrategy = defaultReloadStrategy,\n MultiExtensionRunner = DefaultMultiExtensionRunner,\n getValidatedManifest = defaultGetValidatedManifest,\n }: CmdRunOptions = {}): Promise<DefaultMultiExtensionRunner> {\n\n log.info(`Running web extension from ${sourceDir}`);\n if (preInstall) {\n log.info('Disabled auto-reloading because it\\'s not possible with ' +\n '--pre-install');\n noReload = true;\n }\n\n if (watchFile != null && (!Array.isArray(watchFile) ||\n !watchFile.every((el) => typeof el === 'string'))) {\n throw new UsageError('Unexpected watchFile type');\n }\n\n // Create an alias for --pref since it has been transformed into an\n // object containing one or more preferences.\n const customPrefs = pref;\n const manifestData = await getValidatedManifest(sourceDir);\n\n const profileDir = firefoxProfile || chromiumProfile;\n\n if (profileCreateIfMissing) {\n if (!profileDir) {\n throw new UsageError(\n '--profile-create-if-missing requires ' +\n '--firefox-profile or --chromium-profile'\n );\n }\n const isDir = fs.existsSync(profileDir);\n if (isDir) {\n log.info(`Profile directory ${profileDir} already exists`);\n } else {\n log.info(`Profile directory not found. Creating directory ${profileDir}`);\n await fs.mkdir(profileDir);\n }\n }\n\n const runners = [];\n\n const commonRunnerParams = {\n // Common options.\n extensions: [{sourceDir, manifestData}],\n keepProfileChanges,\n startUrl,\n args,\n desktopNotifications,\n };\n\n if (!target || target.length === 0 || target.includes('firefox-desktop')) {\n const firefoxDesktopRunnerParams = {\n ...commonRunnerParams,\n\n // Firefox specific CLI options.\n firefoxBinary: firefox,\n profilePath: firefoxProfile,\n customPrefs,\n browserConsole,\n preInstall,\n\n // Firefox runner injected dependencies.\n firefoxApp,\n firefoxClient,\n };\n\n const firefoxDesktopRunner = await createExtensionRunner({\n target: 'firefox-desktop',\n params: firefoxDesktopRunnerParams,\n });\n runners.push(firefoxDesktopRunner);\n }\n\n if (target && target.includes('firefox-android')) {\n const firefoxAndroidRunnerParams = {\n ...commonRunnerParams,\n\n // Firefox specific CLI options.\n profilePath: firefoxProfile,\n customPrefs,\n browserConsole,\n preInstall,\n firefoxApk,\n firefoxApkComponent,\n adbDevice,\n adbHost,\n adbPort,\n adbBin,\n adbDiscoveryTimeout,\n adbRemoveOldArtifacts,\n\n // Injected dependencies.\n firefoxApp,\n firefoxClient,\n desktopNotifications: defaultDesktopNotifications,\n buildSourceDir: (extensionSourceDir: string, tmpArtifactsDir: string) => {\n return buildExtension({\n sourceDir: extensionSourceDir,\n ignoreFiles,\n asNeeded: false,\n // Use a separate temporary directory for building the extension zip file\n // that we are going to upload on the android device.\n artifactsDir: tmpArtifactsDir,\n }, {\n // Suppress the message usually logged by web-ext build.\n showReadyMessage: false,\n });\n },\n };\n\n const firefoxAndroidRunner = await createExtensionRunner({\n target: 'firefox-android',\n params: firefoxAndroidRunnerParams,\n });\n runners.push(firefoxAndroidRunner);\n }\n\n if (target && target.includes('chromium')) {\n const chromiumRunnerParams = {\n ...commonRunnerParams,\n chromiumBinary,\n chromiumProfile,\n };\n\n const chromiumRunner = await createExtensionRunner({\n target: 'chromium',\n params: chromiumRunnerParams,\n });\n runners.push(chromiumRunner);\n }\n\n const extensionRunner = new MultiExtensionRunner({\n desktopNotifications,\n runners,\n });\n\n await extensionRunner.run();\n\n if (noReload) {\n log.info('Automatic extension reloading has been disabled');\n } else {\n log.info('The extension will reload if any source file changes');\n\n reloadStrategy({\n extensionRunner,\n sourceDir,\n watchFile,\n watchIgnored,\n artifactsDir,\n ignoreFiles,\n noInput,\n });\n }\n\n return extensionRunner;\n}\n"],"mappings":"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"}
|
package/lib/cmd/sign.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fs } from 'mz';
|
|
3
|
+
import { signAddon as defaultAddonSigner } from 'sign-addon';
|
|
4
|
+
import defaultBuilder from './build.js';
|
|
5
|
+
import getValidatedManifest, { getManifestId } from '../util/manifest.js';
|
|
6
|
+
import { withTempDir } from '../util/temp-dir.js';
|
|
7
|
+
import { isErrorWithCode, UsageError, WebExtError } from '../errors.js';
|
|
8
|
+
import { prepareArtifactsDir } from '../util/artifacts.js';
|
|
9
|
+
import { createLogger } from '../util/logger.js';
|
|
10
|
+
const log = createLogger(import.meta.url);
|
|
11
|
+
const defaultAsyncFsReadFile = fs.readFile.bind(fs);
|
|
12
|
+
export const extensionIdFile = '.web-extension-id'; // Sign command types and implementation.
|
|
13
|
+
|
|
14
|
+
export default function sign({
|
|
15
|
+
apiKey,
|
|
16
|
+
apiProxy,
|
|
17
|
+
apiSecret,
|
|
18
|
+
apiUrlPrefix,
|
|
19
|
+
artifactsDir,
|
|
20
|
+
id,
|
|
21
|
+
ignoreFiles = [],
|
|
22
|
+
sourceDir,
|
|
23
|
+
timeout,
|
|
24
|
+
verbose,
|
|
25
|
+
channel
|
|
26
|
+
}, {
|
|
27
|
+
build = defaultBuilder,
|
|
28
|
+
preValidatedManifest,
|
|
29
|
+
signAddon = defaultAddonSigner
|
|
30
|
+
} = {}) {
|
|
31
|
+
return withTempDir(async function (tmpDir) {
|
|
32
|
+
await prepareArtifactsDir(artifactsDir);
|
|
33
|
+
let manifestData;
|
|
34
|
+
|
|
35
|
+
if (preValidatedManifest) {
|
|
36
|
+
manifestData = preValidatedManifest;
|
|
37
|
+
} else {
|
|
38
|
+
manifestData = await getValidatedManifest(sourceDir);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const [buildResult, idFromSourceDir] = await Promise.all([build({
|
|
42
|
+
sourceDir,
|
|
43
|
+
ignoreFiles,
|
|
44
|
+
artifactsDir: tmpDir.path()
|
|
45
|
+
}, {
|
|
46
|
+
manifestData,
|
|
47
|
+
showReadyMessage: false
|
|
48
|
+
}), getIdFromSourceDir(sourceDir)]);
|
|
49
|
+
const manifestId = getManifestId(manifestData);
|
|
50
|
+
|
|
51
|
+
if (id && manifestId) {
|
|
52
|
+
throw new UsageError(`Cannot set custom ID ${id} because manifest.json ` + `declares ID ${manifestId}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (id) {
|
|
56
|
+
log.debug(`Using custom ID declared as --id=${id}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (manifestId) {
|
|
60
|
+
id = manifestId;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!id && idFromSourceDir) {
|
|
64
|
+
log.info(`Using previously auto-generated extension ID: ${idFromSourceDir}`);
|
|
65
|
+
id = idFromSourceDir;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!id) {
|
|
69
|
+
log.warn('No extension ID specified (it will be auto-generated)');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const signingResult = await signAddon({
|
|
73
|
+
apiKey,
|
|
74
|
+
apiSecret,
|
|
75
|
+
apiUrlPrefix,
|
|
76
|
+
apiProxy,
|
|
77
|
+
timeout,
|
|
78
|
+
verbose,
|
|
79
|
+
id,
|
|
80
|
+
xpiPath: buildResult.extensionPath,
|
|
81
|
+
version: manifestData.version,
|
|
82
|
+
downloadDir: artifactsDir,
|
|
83
|
+
channel
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (signingResult.id) {
|
|
87
|
+
await saveIdToSourceDir(sourceDir, signingResult.id);
|
|
88
|
+
} // All information about the downloaded files would have
|
|
89
|
+
// already been logged by signAddon().
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if (signingResult.success) {
|
|
93
|
+
log.info(`Extension ID: ${signingResult.id}`);
|
|
94
|
+
log.info('SUCCESS');
|
|
95
|
+
} else {
|
|
96
|
+
log.info('FAIL');
|
|
97
|
+
throw new WebExtError('The extension could not be signed');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return signingResult;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
export async function getIdFromSourceDir(sourceDir, asyncFsReadFile = defaultAsyncFsReadFile) {
|
|
104
|
+
const filePath = path.join(sourceDir, extensionIdFile);
|
|
105
|
+
let content;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
content = await asyncFsReadFile(filePath);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (isErrorWithCode('ENOENT', error)) {
|
|
111
|
+
log.debug(`No ID file found at: ${filePath}`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let lines = content.toString().split('\n');
|
|
119
|
+
lines = lines.filter(line => {
|
|
120
|
+
line = line.trim();
|
|
121
|
+
|
|
122
|
+
if (line && !line.startsWith('#')) {
|
|
123
|
+
return line;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
const id = lines[0];
|
|
127
|
+
log.debug(`Found extension ID ${id} in ${filePath}`);
|
|
128
|
+
|
|
129
|
+
if (!id) {
|
|
130
|
+
throw new UsageError(`No ID found in extension ID file ${filePath}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return id;
|
|
134
|
+
}
|
|
135
|
+
export async function saveIdToSourceDir(sourceDir, id) {
|
|
136
|
+
const filePath = path.join(sourceDir, extensionIdFile);
|
|
137
|
+
await fs.writeFile(filePath, ['# This file was created by https://github.com/mozilla/web-ext', '# Your auto-generated extension ID for addons.mozilla.org is:', id.toString()].join('\n'));
|
|
138
|
+
log.debug(`Saved auto-generated ID ${id} to ${filePath}`);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=sign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.js","names":["path","fs","signAddon","defaultAddonSigner","defaultBuilder","getValidatedManifest","getManifestId","withTempDir","isErrorWithCode","UsageError","WebExtError","prepareArtifactsDir","createLogger","log","import","meta","url","defaultAsyncFsReadFile","readFile","bind","extensionIdFile","sign","apiKey","apiProxy","apiSecret","apiUrlPrefix","artifactsDir","id","ignoreFiles","sourceDir","timeout","verbose","channel","build","preValidatedManifest","tmpDir","manifestData","buildResult","idFromSourceDir","Promise","all","showReadyMessage","getIdFromSourceDir","manifestId","debug","info","warn","signingResult","xpiPath","extensionPath","version","downloadDir","saveIdToSourceDir","success","asyncFsReadFile","filePath","join","content","error","lines","toString","split","filter","line","trim","startsWith","writeFile"],"sources":["../../src/cmd/sign.js"],"sourcesContent":["/* @flow */\nimport path from 'path';\n\nimport {fs} from 'mz';\nimport {signAddon as defaultAddonSigner} from 'sign-addon';\n\nimport defaultBuilder from './build.js';\nimport getValidatedManifest, {getManifestId} from '../util/manifest.js';\nimport {withTempDir} from '../util/temp-dir.js';\nimport {isErrorWithCode, UsageError, WebExtError} from '../errors.js';\nimport {prepareArtifactsDir} from '../util/artifacts.js';\nimport {createLogger} from '../util/logger.js';\nimport type {ExtensionManifest} from '../util/manifest.js';\n\nconst log = createLogger(import.meta.url);\n\nconst defaultAsyncFsReadFile: (string) => Promise<Buffer> =\n fs.readFile.bind(fs);\n\nexport const extensionIdFile = '.web-extension-id';\n\n// Sign command types and implementation.\n\nexport type SignParams = {|\n apiKey: string,\n apiProxy: string,\n apiSecret: string,\n apiUrlPrefix: string,\n artifactsDir: string,\n id?: string,\n ignoreFiles?: Array<string>,\n sourceDir: string,\n timeout: number,\n verbose?: boolean,\n channel?: string,\n|};\n\nexport type SignOptions = {\n build?: typeof defaultBuilder,\n signAddon?: typeof defaultAddonSigner,\n preValidatedManifest?: ExtensionManifest,\n shouldExitProgram?: boolean,\n};\n\nexport type SignResult = {|\n success: boolean,\n id: string,\n downloadedFiles: Array<string>,\n|};\n\nexport default function sign(\n {\n apiKey,\n apiProxy,\n apiSecret,\n apiUrlPrefix,\n artifactsDir,\n id,\n ignoreFiles = [],\n sourceDir,\n timeout,\n verbose,\n channel,\n }: SignParams,\n {\n build = defaultBuilder,\n preValidatedManifest,\n signAddon = defaultAddonSigner,\n }: SignOptions = {}\n): Promise<SignResult> {\n return withTempDir(\n async function(tmpDir) {\n await prepareArtifactsDir(artifactsDir);\n\n let manifestData;\n\n if (preValidatedManifest) {\n manifestData = preValidatedManifest;\n } else {\n manifestData = await getValidatedManifest(sourceDir);\n }\n\n const [buildResult, idFromSourceDir] = await Promise.all([\n build({sourceDir, ignoreFiles, artifactsDir: tmpDir.path()},\n {manifestData, showReadyMessage: false}),\n getIdFromSourceDir(sourceDir),\n ]);\n\n const manifestId = getManifestId(manifestData);\n\n if (id && manifestId) {\n throw new UsageError(\n `Cannot set custom ID ${id} because manifest.json ` +\n `declares ID ${manifestId}`);\n }\n if (id) {\n log.debug(`Using custom ID declared as --id=${id}`);\n }\n\n if (manifestId) {\n id = manifestId;\n }\n\n if (!id && idFromSourceDir) {\n log.info(\n `Using previously auto-generated extension ID: ${idFromSourceDir}`);\n id = idFromSourceDir;\n }\n\n if (!id) {\n log.warn('No extension ID specified (it will be auto-generated)');\n }\n\n const signingResult = await signAddon({\n apiKey,\n apiSecret,\n apiUrlPrefix,\n apiProxy,\n timeout,\n verbose,\n id,\n xpiPath: buildResult.extensionPath,\n version: manifestData.version,\n downloadDir: artifactsDir,\n channel,\n });\n\n if (signingResult.id) {\n await saveIdToSourceDir(sourceDir, signingResult.id);\n }\n\n // All information about the downloaded files would have\n // already been logged by signAddon().\n if (signingResult.success) {\n log.info(`Extension ID: ${signingResult.id}`);\n log.info('SUCCESS');\n } else {\n log.info('FAIL');\n throw new WebExtError(\n 'The extension could not be signed');\n }\n\n return signingResult;\n }\n );\n}\n\n\nexport async function getIdFromSourceDir(\n sourceDir: string,\n asyncFsReadFile: typeof defaultAsyncFsReadFile = defaultAsyncFsReadFile,\n): Promise<string | void> {\n const filePath = path.join(sourceDir, extensionIdFile);\n\n let content;\n\n try {\n content = await asyncFsReadFile(filePath);\n } catch (error) {\n if (isErrorWithCode('ENOENT', error)) {\n log.debug(`No ID file found at: ${filePath}`);\n return;\n }\n throw error;\n }\n\n let lines = content.toString().split('\\n');\n lines = lines.filter((line) => {\n line = line.trim();\n if (line && !line.startsWith('#')) {\n return line;\n }\n });\n\n const id = lines[0];\n log.debug(`Found extension ID ${id} in ${filePath}`);\n\n if (!id) {\n throw new UsageError(`No ID found in extension ID file ${filePath}`);\n }\n\n return id;\n}\n\n\nexport async function saveIdToSourceDir(\n sourceDir: string, id: string\n): Promise<void> {\n const filePath = path.join(sourceDir, extensionIdFile);\n await fs.writeFile(filePath, [\n '# This file was created by https://github.com/mozilla/web-ext',\n '# Your auto-generated extension ID for addons.mozilla.org is:',\n id.toString(),\n ].join('\\n'));\n\n log.debug(`Saved auto-generated ID ${id} to ${filePath}`);\n}\n"],"mappings":"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"}
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import importFresh from 'import-fresh';
|
|
4
|
+
import camelCase from 'camelcase';
|
|
5
|
+
import decamelize from 'decamelize';
|
|
6
|
+
import fileExists from './util/file-exists.js';
|
|
7
|
+
import { createLogger } from './util/logger.js';
|
|
8
|
+
import { UsageError, WebExtError } from './errors.js';
|
|
9
|
+
const log = createLogger(import.meta.url);
|
|
10
|
+
export function applyConfigToArgv({
|
|
11
|
+
argv,
|
|
12
|
+
argvFromCLI,
|
|
13
|
+
configObject,
|
|
14
|
+
options,
|
|
15
|
+
configFileName
|
|
16
|
+
}) {
|
|
17
|
+
let newArgv = { ...argv
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
for (const option of Object.keys(configObject)) {
|
|
21
|
+
if (camelCase(option) !== option) {
|
|
22
|
+
throw new UsageError(`The config option "${option}" must be ` + `specified in camel case: "${camelCase(option)}"`);
|
|
23
|
+
} // A config option cannot be a sub-command config
|
|
24
|
+
// object if it is an array.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if (!Array.isArray(configObject[option]) && typeof options[option] === 'object' && typeof configObject[option] === 'object') {
|
|
28
|
+
// Descend into the nested configuration for a sub-command.
|
|
29
|
+
newArgv = applyConfigToArgv({
|
|
30
|
+
argv: newArgv,
|
|
31
|
+
argvFromCLI,
|
|
32
|
+
configObject: configObject[option],
|
|
33
|
+
options: options[option],
|
|
34
|
+
configFileName
|
|
35
|
+
});
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const decamelizedOptName = decamelize(option, {
|
|
40
|
+
separator: '-'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (typeof options[decamelizedOptName] !== 'object') {
|
|
44
|
+
throw new UsageError(`The config file at ${configFileName} specified ` + `an unknown option: "${option}"`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (options[decamelizedOptName].type === undefined) {
|
|
48
|
+
// This means yargs option type wasn't not defined correctly
|
|
49
|
+
throw new WebExtError(`Option: ${option} was defined without a type.`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const expectedType = options[decamelizedOptName].type === 'count' ? 'number' : options[decamelizedOptName].type;
|
|
53
|
+
const optionType = Array.isArray(configObject[option]) ? 'array' : typeof configObject[option];
|
|
54
|
+
|
|
55
|
+
if (optionType !== expectedType) {
|
|
56
|
+
throw new UsageError(`The config file at ${configFileName} specified ` + `the type of "${option}" incorrectly as "${optionType}"` + ` (expected type "${expectedType}")`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let defaultValue;
|
|
60
|
+
|
|
61
|
+
if (options[decamelizedOptName]) {
|
|
62
|
+
if (options[decamelizedOptName].default !== undefined) {
|
|
63
|
+
defaultValue = options[decamelizedOptName].default;
|
|
64
|
+
} else if (expectedType === 'boolean') {
|
|
65
|
+
defaultValue = false;
|
|
66
|
+
}
|
|
67
|
+
} // This is our best effort (without patching yargs) to detect
|
|
68
|
+
// if a value was set on the CLI instead of in the config.
|
|
69
|
+
// It looks for a default value and if the argv value is
|
|
70
|
+
// different, it assumes that the value was configured on the CLI.
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
const wasValueSetOnCLI = typeof argvFromCLI[option] !== 'undefined' && argvFromCLI[option] !== defaultValue;
|
|
74
|
+
|
|
75
|
+
if (wasValueSetOnCLI) {
|
|
76
|
+
log.debug(`Favoring CLI: ${option}=${argvFromCLI[option]} over ` + `configuration: ${option}=${configObject[option]}`);
|
|
77
|
+
newArgv[option] = argvFromCLI[option];
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
newArgv[option] = configObject[option];
|
|
82
|
+
const coerce = options[decamelizedOptName].coerce;
|
|
83
|
+
|
|
84
|
+
if (coerce) {
|
|
85
|
+
log.debug(`Calling coerce() on configured value for ${option}`);
|
|
86
|
+
newArgv[option] = coerce(newArgv[option]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
newArgv[decamelizedOptName] = newArgv[option];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return newArgv;
|
|
93
|
+
}
|
|
94
|
+
export function loadJSConfigFile(filePath) {
|
|
95
|
+
const resolvedFilePath = path.resolve(filePath);
|
|
96
|
+
log.debug(`Loading JS config file: "${filePath}" ` + `(resolved to "${resolvedFilePath}")`);
|
|
97
|
+
let configObject;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
configObject = importFresh(resolvedFilePath);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
log.debug('Handling error:', error);
|
|
103
|
+
throw new UsageError(`Cannot read config file: ${resolvedFilePath}\n` + `Error: ${error.message}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (filePath.endsWith('package.json')) {
|
|
107
|
+
log.debug('Looking for webExt key inside package.json file');
|
|
108
|
+
configObject = configObject.webExt || {};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (Object.keys(configObject).length === 0) {
|
|
112
|
+
log.debug(`Config file ${resolvedFilePath} did not define any options. ` + 'Did you set module.exports = {...}?');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return configObject;
|
|
116
|
+
}
|
|
117
|
+
export async function discoverConfigFiles({
|
|
118
|
+
getHomeDir = os.homedir
|
|
119
|
+
} = {}) {
|
|
120
|
+
const magicConfigName = 'web-ext-config.js'; // Config files will be loaded in this order.
|
|
121
|
+
|
|
122
|
+
const possibleConfigs = [// Look for a magic hidden config (preceded by dot) in home dir.
|
|
123
|
+
path.join(getHomeDir(), `.${magicConfigName}`), // Look for webExt key inside package.json file
|
|
124
|
+
path.join(process.cwd(), 'package.json'), // Look for a magic config in the current working directory.
|
|
125
|
+
path.join(process.cwd(), magicConfigName)];
|
|
126
|
+
const configs = await Promise.all(possibleConfigs.map(async fileName => {
|
|
127
|
+
const resolvedFileName = path.resolve(fileName);
|
|
128
|
+
|
|
129
|
+
if (await fileExists(resolvedFileName)) {
|
|
130
|
+
return resolvedFileName;
|
|
131
|
+
} else {
|
|
132
|
+
log.debug(`Discovered config "${resolvedFileName}" does not ` + 'exist or is not readable');
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
}));
|
|
136
|
+
const existingConfigs = [];
|
|
137
|
+
configs.forEach(f => {
|
|
138
|
+
if (typeof f === 'string') {
|
|
139
|
+
existingConfigs.push(f);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return existingConfigs;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","names":["os","path","importFresh","camelCase","decamelize","fileExists","createLogger","UsageError","WebExtError","log","import","meta","url","applyConfigToArgv","argv","argvFromCLI","configObject","options","configFileName","newArgv","option","Object","keys","Array","isArray","decamelizedOptName","separator","type","undefined","expectedType","optionType","defaultValue","default","wasValueSetOnCLI","debug","coerce","loadJSConfigFile","filePath","resolvedFilePath","resolve","error","message","endsWith","webExt","length","discoverConfigFiles","getHomeDir","homedir","magicConfigName","possibleConfigs","join","process","cwd","configs","Promise","all","map","fileName","resolvedFileName","existingConfigs","forEach","f","push"],"sources":["../src/config.js"],"sourcesContent":["/* @flow */\nimport os from 'os';\nimport path from 'path';\n\nimport importFresh from 'import-fresh';\nimport camelCase from 'camelcase';\nimport decamelize from 'decamelize';\n\nimport fileExists from './util/file-exists.js';\nimport {createLogger} from './util/logger.js';\nimport {UsageError, WebExtError} from './errors.js';\n\nconst log = createLogger(import.meta.url);\n\ntype ApplyConfigToArgvParams = {|\n // This is the argv object which will get updated by each\n // config applied.\n argv: Object,\n // This is the argv that only has CLI values applied to it.\n argvFromCLI: Object,\n configObject: Object,\n options: Object,\n configFileName: string,\n|};\n\nexport function applyConfigToArgv({\n argv,\n argvFromCLI,\n configObject,\n options,\n configFileName,\n}: ApplyConfigToArgvParams): Object {\n let newArgv = {...argv};\n\n for (const option of Object.keys(configObject)) {\n if (camelCase(option) !== option) {\n throw new UsageError(\n `The config option \"${option}\" must be ` +\n `specified in camel case: \"${camelCase(option)}\"`);\n }\n\n // A config option cannot be a sub-command config\n // object if it is an array.\n if (!Array.isArray(configObject[option]) &&\n typeof options[option] === 'object' &&\n typeof configObject[option] === 'object') {\n // Descend into the nested configuration for a sub-command.\n newArgv = applyConfigToArgv({\n argv: newArgv,\n argvFromCLI,\n configObject: configObject[option],\n options: options[option],\n configFileName});\n continue;\n }\n\n const decamelizedOptName = decamelize(option, {separator: '-'});\n\n if (typeof options[decamelizedOptName] !== 'object') {\n throw new UsageError(`The config file at ${configFileName} specified ` +\n `an unknown option: \"${option}\"`);\n }\n if (options[decamelizedOptName].type === undefined) {\n // This means yargs option type wasn't not defined correctly\n throw new WebExtError(\n `Option: ${option} was defined without a type.`);\n }\n\n const expectedType = options[decamelizedOptName].type ===\n 'count' ? 'number' : options[decamelizedOptName].type;\n\n const optionType = (\n Array.isArray(configObject[option]) ?\n 'array' : typeof configObject[option]\n );\n\n if (optionType !== expectedType) {\n throw new UsageError(`The config file at ${configFileName} specified ` +\n `the type of \"${option}\" incorrectly as \"${optionType}\"` +\n ` (expected type \"${expectedType}\")`);\n }\n\n let defaultValue;\n if (options[decamelizedOptName]) {\n if (options[decamelizedOptName].default !== undefined) {\n defaultValue = options[decamelizedOptName].default;\n } else if (expectedType === 'boolean') {\n defaultValue = false;\n }\n }\n\n // This is our best effort (without patching yargs) to detect\n // if a value was set on the CLI instead of in the config.\n // It looks for a default value and if the argv value is\n // different, it assumes that the value was configured on the CLI.\n\n const wasValueSetOnCLI =\n typeof argvFromCLI[option] !== 'undefined' &&\n argvFromCLI[option] !== defaultValue;\n if (wasValueSetOnCLI) {\n log.debug(\n `Favoring CLI: ${option}=${argvFromCLI[option]} over ` +\n `configuration: ${option}=${configObject[option]}`);\n newArgv[option] = argvFromCLI[option];\n continue;\n }\n\n newArgv[option] = configObject[option];\n\n const coerce = options[decamelizedOptName].coerce;\n if (coerce) {\n log.debug(\n `Calling coerce() on configured value for ${option}`);\n newArgv[option] = coerce(newArgv[option]);\n }\n\n newArgv[decamelizedOptName] = newArgv[option];\n }\n return newArgv;\n}\n\nexport function loadJSConfigFile(filePath: string): Object {\n const resolvedFilePath = path.resolve(filePath);\n log.debug(\n `Loading JS config file: \"${filePath}\" ` +\n `(resolved to \"${resolvedFilePath}\")`);\n let configObject;\n try {\n configObject = importFresh(resolvedFilePath);\n } catch (error) {\n log.debug('Handling error:', error);\n throw new UsageError(\n `Cannot read config file: ${resolvedFilePath}\\n` +\n `Error: ${error.message}`);\n }\n if (filePath.endsWith('package.json')) {\n log.debug('Looking for webExt key inside package.json file');\n configObject = configObject.webExt || {};\n }\n if (Object.keys(configObject).length === 0) {\n log.debug(`Config file ${resolvedFilePath} did not define any options. ` +\n 'Did you set module.exports = {...}?');\n }\n return configObject;\n}\n\ntype DiscoverConfigFilesParams = {\n getHomeDir: () => string,\n};\n\nexport async function discoverConfigFiles(\n {getHomeDir = os.homedir}: DiscoverConfigFilesParams = {}\n): Promise<Array<string>> {\n const magicConfigName = 'web-ext-config.js';\n\n // Config files will be loaded in this order.\n const possibleConfigs = [\n // Look for a magic hidden config (preceded by dot) in home dir.\n path.join(getHomeDir(), `.${magicConfigName}`),\n // Look for webExt key inside package.json file\n path.join(process.cwd(), 'package.json'),\n // Look for a magic config in the current working directory.\n path.join(process.cwd(), magicConfigName),\n ];\n\n const configs = await Promise.all(possibleConfigs.map(\n async (fileName) => {\n const resolvedFileName = path.resolve(fileName);\n if (await fileExists(resolvedFileName)) {\n return resolvedFileName;\n } else {\n log.debug(\n `Discovered config \"${resolvedFileName}\" does not ` +\n 'exist or is not readable');\n return undefined;\n }\n }\n ));\n\n const existingConfigs = [];\n configs.forEach((f) => {\n if (typeof f === 'string') {\n existingConfigs.push(f);\n }\n });\n return existingConfigs;\n}\n"],"mappings":"AACA,OAAOA,EAAP,MAAe,IAAf;AACA,OAAOC,IAAP,MAAiB,MAAjB;AAEA,OAAOC,WAAP,MAAwB,cAAxB;AACA,OAAOC,SAAP,MAAsB,WAAtB;AACA,OAAOC,UAAP,MAAuB,YAAvB;AAEA,OAAOC,UAAP,MAAuB,uBAAvB;AACA,SAAQC,YAAR,QAA2B,kBAA3B;AACA,SAAQC,UAAR,EAAoBC,WAApB,QAAsC,aAAtC;AAEA,MAAMC,GAAG,GAAGH,YAAY,CAACI,MAAM,CAACC,IAAP,CAAYC,GAAb,CAAxB;AAaA,OAAO,SAASC,iBAAT,CAA2B;EAChCC,IADgC;EAEhCC,WAFgC;EAGhCC,YAHgC;EAIhCC,OAJgC;EAKhCC;AALgC,CAA3B,EAM6B;EAClC,IAAIC,OAAO,GAAG,EAAC,GAAGL;EAAJ,CAAd;;EAEA,KAAK,MAAMM,MAAX,IAAqBC,MAAM,CAACC,IAAP,CAAYN,YAAZ,CAArB,EAAgD;IAC9C,IAAIb,SAAS,CAACiB,MAAD,CAAT,KAAsBA,MAA1B,EAAkC;MAChC,MAAM,IAAIb,UAAJ,CACH,sBAAqBa,MAAO,YAA7B,GACC,6BAA4BjB,SAAS,CAACiB,MAAD,CAAS,GAF3C,CAAN;IAGD,CAL6C,CAO9C;IACA;;;IACA,IAAI,CAACG,KAAK,CAACC,OAAN,CAAcR,YAAY,CAACI,MAAD,CAA1B,CAAD,IACF,OAAOH,OAAO,CAACG,MAAD,CAAd,KAA2B,QADzB,IAEF,OAAOJ,YAAY,CAACI,MAAD,CAAnB,KAAgC,QAFlC,EAE4C;MAC1C;MACAD,OAAO,GAAGN,iBAAiB,CAAC;QAC1BC,IAAI,EAAEK,OADoB;QAE1BJ,WAF0B;QAG1BC,YAAY,EAAEA,YAAY,CAACI,MAAD,CAHA;QAI1BH,OAAO,EAAEA,OAAO,CAACG,MAAD,CAJU;QAK1BF;MAL0B,CAAD,CAA3B;MAMA;IACD;;IAED,MAAMO,kBAAkB,GAAGrB,UAAU,CAACgB,MAAD,EAAS;MAACM,SAAS,EAAE;IAAZ,CAAT,CAArC;;IAEA,IAAI,OAAOT,OAAO,CAACQ,kBAAD,CAAd,KAAuC,QAA3C,EAAqD;MACnD,MAAM,IAAIlB,UAAJ,CAAgB,sBAAqBW,cAAe,aAArC,GAClB,uBAAsBE,MAAO,GAD1B,CAAN;IAED;;IACD,IAAIH,OAAO,CAACQ,kBAAD,CAAP,CAA4BE,IAA5B,KAAqCC,SAAzC,EAAoD;MAClD;MACA,MAAM,IAAIpB,WAAJ,CACH,WAAUY,MAAO,8BADd,CAAN;IAED;;IAED,MAAMS,YAAY,GAAGZ,OAAO,CAACQ,kBAAD,CAAP,CAA4BE,IAA5B,KACnB,OADmB,GACT,QADS,GACEV,OAAO,CAACQ,kBAAD,CAAP,CAA4BE,IADnD;IAGA,MAAMG,UAAU,GACdP,KAAK,CAACC,OAAN,CAAcR,YAAY,CAACI,MAAD,CAA1B,IACE,OADF,GACY,OAAOJ,YAAY,CAACI,MAAD,CAFjC;;IAKA,IAAIU,UAAU,KAAKD,YAAnB,EAAiC;MAC/B,MAAM,IAAItB,UAAJ,CAAgB,sBAAqBW,cAAe,aAArC,GAClB,gBAAeE,MAAO,qBAAoBU,UAAW,GADnC,GAElB,oBAAmBD,YAAa,IAF7B,CAAN;IAGD;;IAED,IAAIE,YAAJ;;IACA,IAAId,OAAO,CAACQ,kBAAD,CAAX,EAAiC;MAC/B,IAAIR,OAAO,CAACQ,kBAAD,CAAP,CAA4BO,OAA5B,KAAwCJ,SAA5C,EAAuD;QACrDG,YAAY,GAAGd,OAAO,CAACQ,kBAAD,CAAP,CAA4BO,OAA3C;MACD,CAFD,MAEO,IAAIH,YAAY,KAAK,SAArB,EAAgC;QACrCE,YAAY,GAAG,KAAf;MACD;IACF,CAvD6C,CAyD9C;IACA;IACA;IACA;;;IAEA,MAAME,gBAAgB,GACpB,OAAOlB,WAAW,CAACK,MAAD,CAAlB,KAA+B,WAA/B,IACAL,WAAW,CAACK,MAAD,CAAX,KAAwBW,YAF1B;;IAGA,IAAIE,gBAAJ,EAAsB;MACpBxB,GAAG,CAACyB,KAAJ,CACG,iBAAgBd,MAAO,IAAGL,WAAW,CAACK,MAAD,CAAS,QAA/C,GACC,kBAAiBA,MAAO,IAAGJ,YAAY,CAACI,MAAD,CAAS,EAFnD;MAGAD,OAAO,CAACC,MAAD,CAAP,GAAkBL,WAAW,CAACK,MAAD,CAA7B;MACA;IACD;;IAEDD,OAAO,CAACC,MAAD,CAAP,GAAkBJ,YAAY,CAACI,MAAD,CAA9B;IAEA,MAAMe,MAAM,GAAGlB,OAAO,CAACQ,kBAAD,CAAP,CAA4BU,MAA3C;;IACA,IAAIA,MAAJ,EAAY;MACV1B,GAAG,CAACyB,KAAJ,CACG,4CAA2Cd,MAAO,EADrD;MAEAD,OAAO,CAACC,MAAD,CAAP,GAAkBe,MAAM,CAAChB,OAAO,CAACC,MAAD,CAAR,CAAxB;IACD;;IAEDD,OAAO,CAACM,kBAAD,CAAP,GAA8BN,OAAO,CAACC,MAAD,CAArC;EACD;;EACD,OAAOD,OAAP;AACD;AAED,OAAO,SAASiB,gBAAT,CAA0BC,QAA1B,EAAoD;EACzD,MAAMC,gBAAgB,GAAGrC,IAAI,CAACsC,OAAL,CAAaF,QAAb,CAAzB;EACA5B,GAAG,CAACyB,KAAJ,CACG,4BAA2BG,QAAS,IAArC,GACC,iBAAgBC,gBAAiB,IAFpC;EAGA,IAAItB,YAAJ;;EACA,IAAI;IACFA,YAAY,GAAGd,WAAW,CAACoC,gBAAD,CAA1B;EACD,CAFD,CAEE,OAAOE,KAAP,EAAc;IACd/B,GAAG,CAACyB,KAAJ,CAAU,iBAAV,EAA6BM,KAA7B;IACA,MAAM,IAAIjC,UAAJ,CACH,4BAA2B+B,gBAAiB,IAA7C,GACC,UAASE,KAAK,CAACC,OAAQ,EAFpB,CAAN;EAGD;;EACD,IAAIJ,QAAQ,CAACK,QAAT,CAAkB,cAAlB,CAAJ,EAAuC;IACrCjC,GAAG,CAACyB,KAAJ,CAAU,iDAAV;IACAlB,YAAY,GAAGA,YAAY,CAAC2B,MAAb,IAAuB,EAAtC;EACD;;EACD,IAAItB,MAAM,CAACC,IAAP,CAAYN,YAAZ,EAA0B4B,MAA1B,KAAqC,CAAzC,EAA4C;IAC1CnC,GAAG,CAACyB,KAAJ,CAAW,eAAcI,gBAAiB,+BAAhC,GACR,qCADF;EAED;;EACD,OAAOtB,YAAP;AACD;AAMD,OAAO,eAAe6B,mBAAf,CACL;EAACC,UAAU,GAAG9C,EAAE,CAAC+C;AAAjB,IAAuD,EADlD,EAEmB;EACxB,MAAMC,eAAe,GAAG,mBAAxB,CADwB,CAGxB;;EACA,MAAMC,eAAe,GAAG,CACtB;EACAhD,IAAI,CAACiD,IAAL,CAAUJ,UAAU,EAApB,EAAyB,IAAGE,eAAgB,EAA5C,CAFsB,EAGtB;EACA/C,IAAI,CAACiD,IAAL,CAAUC,OAAO,CAACC,GAAR,EAAV,EAAyB,cAAzB,CAJsB,EAKtB;EACAnD,IAAI,CAACiD,IAAL,CAAUC,OAAO,CAACC,GAAR,EAAV,EAAyBJ,eAAzB,CANsB,CAAxB;EASA,MAAMK,OAAO,GAAG,MAAMC,OAAO,CAACC,GAAR,CAAYN,eAAe,CAACO,GAAhB,CAChC,MAAOC,QAAP,IAAoB;IAClB,MAAMC,gBAAgB,GAAGzD,IAAI,CAACsC,OAAL,CAAakB,QAAb,CAAzB;;IACA,IAAI,MAAMpD,UAAU,CAACqD,gBAAD,CAApB,EAAwC;MACtC,OAAOA,gBAAP;IACD,CAFD,MAEO;MACLjD,GAAG,CAACyB,KAAJ,CACG,sBAAqBwB,gBAAiB,aAAvC,GACA,0BAFF;MAGA,OAAO9B,SAAP;IACD;EACF,CAX+B,CAAZ,CAAtB;EAcA,MAAM+B,eAAe,GAAG,EAAxB;EACAN,OAAO,CAACO,OAAR,CAAiBC,CAAD,IAAO;IACrB,IAAI,OAAOA,CAAP,KAAa,QAAjB,EAA2B;MACzBF,eAAe,CAACG,IAAhB,CAAqBD,CAArB;IACD;EACF,CAJD;EAKA,OAAOF,eAAP;AACD"}
|