electron-builder
Version:
A complete solution to package and build a ready for distribution Electron app for MacOS, Windows and Linux with “auto update” support out of the box
575 lines (528 loc) • 27.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getResolvedPublishConfig = exports.PlatformPackager = exports.TargetEx = exports.Target = undefined;
var _bluebirdLstC;
function _load_bluebirdLstC() {
return _bluebirdLstC = require("bluebird-lst-c");
}
var _bluebirdLstC2;
function _load_bluebirdLstC2() {
return _bluebirdLstC2 = _interopRequireDefault(require("bluebird-lst-c"));
}
let getResolvedPublishConfig = exports.getResolvedPublishConfig = (() => {
var _ref2 = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* (packager, publishConfig, errorIfCannot) {
let getInfo = (() => {
var _ref3 = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const info = yield (0, (_repositoryInfo || _load_repositoryInfo()).getRepositoryInfo)(packager.metadata, packager.devMetadata);
if (info != null) {
return info;
}
if (!errorIfCannot) {
return null;
}
(0, (_log || _load_log()).warn)("Cannot detect repository by .git/config");
throw new Error(`Please specify "repository" in the dev package.json ('${ packager.devPackageFile }').\nPlease see https://github.com/electron-userland/electron-builder/wiki/Publishing-Artifacts`);
});
return function getInfo() {
return _ref3.apply(this, arguments);
};
})();
if (publishConfig.provider === "generic") {
if (publishConfig.url == null) {
throw new Error(`Please specify "url" for "generic" update server`);
}
return publishConfig;
}
let owner = publishConfig.owner;
let project = publishConfig.provider === "github" ? publishConfig.repo : publishConfig.package;
if (!owner || !project) {
const info = yield getInfo();
if (info == null) {
return null;
}
if (!owner) {
owner = info.user;
}
if (!project) {
project = info.project;
}
}
const copy = Object.assign({}, publishConfig);
if (copy.owner == null) {
copy.owner = owner;
}
if (publishConfig.provider === "github") {
const options = copy;
if (options.repo == null) {
options.repo = project;
}
return options;
} else if (publishConfig.provider === "bintray") {
const options = copy;
if (options.package == null) {
options.package = project;
}
return options;
} else {
return null;
}
});
return function getResolvedPublishConfig(_x2, _x3, _x4) {
return _ref2.apply(this, arguments);
};
})();
//# sourceMappingURL=platformPackager.js.map
exports.getArchSuffix = getArchSuffix;
exports.smarten = smarten;
exports.normalizeExt = normalizeExt;
exports.getPublishConfigs = getPublishConfigs;
var _metadata;
function _load_metadata() {
return _metadata = require("./metadata");
}
var _path;
function _load_path() {
return _path = _interopRequireWildcard(require("path"));
}
var _fsExtraP;
function _load_fsExtraP() {
return _fsExtraP = require("fs-extra-p");
}
var _util;
function _load_util() {
return _util = require("./util/util");
}
var _archive;
function _load_archive() {
return _archive = require("./targets/archive");
}
var _asarUtil;
function _load_asarUtil() {
return _asarUtil = require("./asarUtil");
}
var _log;
function _load_log() {
return _log = require("./util/log");
}
var _filter;
function _load_filter() {
return _filter = require("./util/filter");
}
var _dirPackager;
function _load_dirPackager() {
return _dirPackager = require("./packager/dirPackager");
}
var _fileMatcher;
function _load_fileMatcher() {
return _fileMatcher = require("./fileMatcher");
}
var _repositoryInfo;
function _load_repositoryInfo() {
return _repositoryInfo = require("./repositoryInfo");
}
var _yarn;
function _load_yarn() {
return _yarn = require("./yarn");
}
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class Target {
constructor(name) {
this.name = name;
}
finishBuild() {
return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve();
}
}
exports.Target = Target;
class TargetEx extends Target {}
exports.TargetEx = TargetEx;
class PlatformPackager {
constructor(info) {
this.info = info;
this.devMetadata = info.devMetadata;
this.platformSpecificBuildOptions = this.normalizePlatformSpecificBuildOptions(info.devMetadata.build[this.platform.buildConfigurationKey]);
this.appInfo = this.prepareAppInfo(info.appInfo);
this.options = info.options;
this.projectDir = info.projectDir;
this.buildResourcesDir = (_path || _load_path()).resolve(this.projectDir, this.relativeBuildResourcesDirname);
this.resourceList = (0, (_fsExtraP || _load_fsExtraP()).readdir)(this.buildResourcesDir).catch(e => {
if (e.code !== "ENOENT") {
throw e;
}
return [];
});
}
prepareAppInfo(appInfo) {
return appInfo;
}
normalizePlatformSpecificBuildOptions(options) {
return options == null ? Object.create(null) : options;
}
getCscPassword() {
const password = this.doGetCscPassword();
if ((0, (_util || _load_util()).isEmptyOrSpaces)(password)) {
(0, (_log || _load_log()).log)("CSC_KEY_PASSWORD is not defined, empty password will be used");
return "";
} else {
return password.trim();
}
}
doGetCscPassword() {
return this.options.cscKeyPassword || process.env.CSC_KEY_PASSWORD;
}
get relativeBuildResourcesDirname() {
return (0, (_util || _load_util()).use)(this.devMetadata.directories, it => it.buildResources) || "build";
}
computeAppOutDir(outDir, arch) {
return (_path || _load_path()).join(outDir, `${ this.platform.buildConfigurationKey }${ getArchSuffix(arch) }${ this.platform === (_metadata || _load_metadata()).Platform.MAC ? "" : "-unpacked" }`);
}
dispatchArtifactCreated(file, artifactName) {
this.info.eventEmitter.emit("artifactCreated", {
file: file,
artifactName: artifactName,
packager: this
});
}
getExtraFileMatchers(isResources, appOutDir, fileMatchOptions, customBuildOptions) {
const base = isResources ? this.getResourcesDir(appOutDir) : this.platform === (_metadata || _load_metadata()).Platform.MAC ? (_path || _load_path()).join(appOutDir, `${ this.appInfo.productFilename }.app`, "Contents") : appOutDir;
return this.getFileMatchers(isResources ? "extraResources" : "extraFiles", this.projectDir, base, true, fileMatchOptions, customBuildOptions);
}
doPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions) {
var _this = this;
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const asarOptions = _this.computeAsarOptions(platformSpecificBuildOptions);
const fileMatchOptions = {
arch: (_metadata || _load_metadata()).Arch[arch],
os: _this.platform.buildConfigurationKey
};
const extraResourceMatchers = _this.getExtraFileMatchers(true, appOutDir, fileMatchOptions, platformSpecificBuildOptions);
const extraFileMatchers = _this.getExtraFileMatchers(false, appOutDir, fileMatchOptions, platformSpecificBuildOptions);
const resourcesPath = _this.platform === (_metadata || _load_metadata()).Platform.MAC ? (_path || _load_path()).join(appOutDir, "Electron.app", "Contents", "Resources") : (_path || _load_path()).join(appOutDir, "resources");
(0, (_log || _load_log()).log)(`Packaging for ${ platformName } ${ (_metadata || _load_metadata()).Arch[arch] } using electron ${ _this.info.electronVersion } to ${ (_path || _load_path()).relative(_this.projectDir, appOutDir) }`);
yield (0, (_dirPackager || _load_dirPackager()).pack)(_this, appOutDir, platformName, (_metadata || _load_metadata()).Arch[arch], _this.info.electronVersion, (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const appDir = _this.info.appDir;
const ignoreFiles = new Set([(_path || _load_path()).resolve(appDir, outDir), (_path || _load_path()).resolve(appDir, _this.buildResourcesDir)]);
// prune dev or not listed dependencies
yield (0, (_yarn || _load_yarn()).dependencies)(appDir, true, ignoreFiles);
if ((_util || _load_util()).debug.enabled) {
const nodeModulesDir = (_path || _load_path()).join(appDir, "node_modules");
(0, (_util || _load_util()).debug)(`Pruned dev or extraneous dependencies: ${ Array.from(ignoreFiles).slice(2).map(function (it) {
return (_path || _load_path()).relative(nodeModulesDir, it);
}).join(", ") }`);
}
const patterns = _this.getFileMatchers("files", appDir, (_path || _load_path()).join(resourcesPath, "app"), false, fileMatchOptions, platformSpecificBuildOptions);
let defaultMatcher = patterns != null ? patterns[0] : new (_fileMatcher || _load_fileMatcher()).FileMatcher(appDir, (_path || _load_path()).join(resourcesPath, "app"), fileMatchOptions);
if (defaultMatcher.isEmpty()) {
defaultMatcher.addPattern("**/*");
} else {
defaultMatcher.addPattern("package.json");
}
defaultMatcher.addPattern("!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts}");
defaultMatcher.addPattern("!**/node_modules/.bin");
defaultMatcher.addPattern("!**/*.{o,hprof,orig,pyc,pyo,rbc,swp}");
defaultMatcher.addPattern("!**/._*");
//noinspection SpellCheckingInspection
defaultMatcher.addPattern("!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.editorconfig,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity}");
let rawFilter = null;
const deprecatedIgnore = _this.devMetadata.build.ignore;
if (deprecatedIgnore != null) {
if (typeof deprecatedIgnore === "function") {
(0, (_log || _load_log()).warn)(`"ignore" is specified as function, may be new "files" option will be suit your needs? Please see https://github.com/electron-userland/electron-builder/wiki/Options#BuildMetadata-files`);
} else {
(0, (_log || _load_log()).warn)(`"ignore" is deprecated, please use "files", see https://github.com/electron-userland/electron-builder/wiki/Options#BuildMetadata-files`);
}
rawFilter = (0, (_fileMatcher || _load_fileMatcher()).deprecatedUserIgnoreFilter)(deprecatedIgnore, appDir);
}
let excludePatterns = [];
if (extraResourceMatchers != null) {
for (let i = 0; i < extraResourceMatchers.length; i++) {
const patterns = extraResourceMatchers[i].getParsedPatterns(_this.info.projectDir);
excludePatterns = excludePatterns.concat(patterns);
}
}
if (extraFileMatchers != null) {
for (let i = 0; i < extraFileMatchers.length; i++) {
const patterns = extraFileMatchers[i].getParsedPatterns(_this.info.projectDir);
excludePatterns = excludePatterns.concat(patterns);
}
}
const filter = defaultMatcher.createFilter(ignoreFiles, rawFilter, excludePatterns.length ? excludePatterns : null);
const promise = asarOptions == null ? (0, (_filter || _load_filter()).copyFiltered)(appDir, (_path || _load_path()).join(resourcesPath, "app"), filter, _this.info.devMetadata.build.dereference || _this.platform === (_metadata || _load_metadata()).Platform.WINDOWS) : (0, (_asarUtil || _load_asarUtil()).createAsarArchive)(appDir, resourcesPath, asarOptions, filter);
const promises = [promise, (0, (_util || _load_util()).unlinkIfExists)((_path || _load_path()).join(resourcesPath, "default_app.asar")), (0, (_util || _load_util()).unlinkIfExists)((_path || _load_path()).join(appOutDir, "version"))];
if (_this.info.electronVersion != null && _this.info.electronVersion[0] === "0") {
// electron release >= 0.37.4 - the default_app/ folder is a default_app.asar file
promises.push((0, (_fsExtraP || _load_fsExtraP()).remove)((_path || _load_path()).join(resourcesPath, "default_app")));
}
promises.push(_this.postInitApp(appOutDir));
yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(promises);
}));
yield _this.doCopyExtraFiles(extraResourceMatchers);
yield _this.doCopyExtraFiles(extraFileMatchers);
const afterPack = _this.devMetadata.build.afterPack;
if (afterPack != null) {
yield afterPack({
appOutDir: appOutDir,
options: _this.devMetadata.build,
packager: _this
});
}
yield _this.sanityCheckPackage(appOutDir, asarOptions != null);
})();
}
postInitApp(executableFile) {
return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve(null);
}
getIconPath() {
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
return null;
})();
}
computeAsarOptions(customBuildOptions) {
let result = this.devMetadata.build.asar;
let platformSpecific = customBuildOptions.asar;
if (platformSpecific != null) {
result = platformSpecific;
}
if (result === false) {
return null;
}
const buildMetadata = this.devMetadata.build;
if (buildMetadata["asar-unpack"] != null) {
(0, (_log || _load_log()).warn)("asar-unpack is deprecated, please set as asar.unpack");
}
if (buildMetadata["asar-unpack-dir"] != null) {
(0, (_log || _load_log()).warn)("asar-unpack-dir is deprecated, please set as asar.unpackDir");
}
if (result == null || result === true) {
result = {
unpack: buildMetadata["asar-unpack"],
unpackDir: buildMetadata["asar-unpack-dir"]
};
}
return Object.assign(result, {
extraMetadata: this.options.extraMetadata
});
}
doCopyExtraFiles(patterns) {
if (patterns == null || patterns.length === 0) {
return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve();
} else {
const promises = [];
for (let i = 0; i < patterns.length; i++) {
if (patterns[i].isEmpty()) {
patterns[i].addPattern("**/*");
}
promises.push((0, (_filter || _load_filter()).copyFiltered)(patterns[i].from, patterns[i].to, patterns[i].createFilter(), this.platform === (_metadata || _load_metadata()).Platform.WINDOWS));
}
return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(promises);
}
}
getFileMatchers(name, defaultSrc, defaultDest, allowAdvancedMatching, fileMatchOptions, customBuildOptions) {
let globalPatterns = this.devMetadata.build[name];
let platformSpecificPatterns = customBuildOptions[name];
const defaultMatcher = new (_fileMatcher || _load_fileMatcher()).FileMatcher(defaultSrc, defaultDest, fileMatchOptions);
const fileMatchers = [];
function addPatterns(patterns) {
if (patterns == null) {
return;
} else if (!Array.isArray(patterns)) {
defaultMatcher.addPattern(patterns);
return;
}
for (let i = 0; i < patterns.length; i++) {
const pattern = patterns[i];
if (typeof pattern === "string") {
defaultMatcher.addPattern(pattern);
} else if (allowAdvancedMatching) {
const from = pattern.from ? (_path || _load_path()).isAbsolute(pattern.from) ? pattern.from : (_path || _load_path()).join(defaultSrc, pattern.from) : defaultSrc;
const to = pattern.to ? (_path || _load_path()).isAbsolute(pattern.to) ? pattern.to : (_path || _load_path()).join(defaultDest, pattern.to) : defaultDest;
fileMatchers.push(new (_fileMatcher || _load_fileMatcher()).FileMatcher(from, to, fileMatchOptions, pattern.filter));
} else {
throw new Error(`Advanced file copying not supported for "${ name }"`);
}
}
}
addPatterns(globalPatterns);
addPatterns(platformSpecificPatterns);
if (!defaultMatcher.isEmpty()) {
// Default matcher should be first in the array
fileMatchers.unshift(defaultMatcher);
}
return fileMatchers.length ? fileMatchers : null;
}
getResourcesDir(appOutDir) {
return this.platform === (_metadata || _load_metadata()).Platform.MAC ? this.getOSXResourcesDir(appOutDir) : (_path || _load_path()).join(appOutDir, "resources");
}
getOSXResourcesDir(appOutDir) {
return (_path || _load_path()).join(appOutDir, `${ this.appInfo.productFilename }.app`, "Contents", "Resources");
}
checkFileInPackage(resourcesDir, file, messagePrefix, isAsar) {
var _this2 = this;
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const relativeFile = (_path || _load_path()).relative(_this2.info.appDir, (_path || _load_path()).resolve(_this2.info.appDir, file));
if (isAsar) {
yield (0, (_asarUtil || _load_asarUtil()).checkFileInArchive)((_path || _load_path()).join(resourcesDir, "app.asar"), relativeFile, messagePrefix);
return;
}
const pathParsed = (_path || _load_path()).parse(file);
// Even when packaging to asar is disabled, it does not imply that the main file can not be inside an .asar archive.
// This may occur when the packaging is done manually before processing with electron-builder.
if (pathParsed.dir.indexOf(".asar") !== -1) {
// The path needs to be split to the part with an asar archive which acts like a directory and the part with
// the path to main file itself. (e.g. path/arch.asar/dir/index.js -> path/arch.asar, dir/index.js)
const pathSplit = pathParsed.dir.split((_path || _load_path()).sep);
let partWithAsarIndex = 0;
pathSplit.some(function (pathPart, index) {
partWithAsarIndex = index;
return pathPart.endsWith(".asar");
});
const asarPath = (_path || _load_path()).join.apply(_path || _load_path(), pathSplit.slice(0, partWithAsarIndex + 1));
let mainPath = pathSplit.length > partWithAsarIndex + 1 ? (_path || _load_path()).join.apply(pathSplit.slice(partWithAsarIndex + 1)) : "";
mainPath += (_path || _load_path()).join(mainPath, pathParsed.base);
yield (0, (_asarUtil || _load_asarUtil()).checkFileInArchive)((_path || _load_path()).join(resourcesDir, "app", asarPath), mainPath, messagePrefix);
} else {
const outStat = yield (0, (_util || _load_util()).statOrNull)((_path || _load_path()).join(resourcesDir, "app", relativeFile));
if (outStat == null) {
throw new Error(`${ messagePrefix } "${ relativeFile }" does not exist. Seems like a wrong configuration.`);
} else if (!outStat.isFile()) {
throw new Error(`${ messagePrefix } "${ relativeFile }" is not a file. Seems like a wrong configuration.`);
}
}
})();
}
sanityCheckPackage(appOutDir, isAsar) {
var _this3 = this;
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const outStat = yield (0, (_util || _load_util()).statOrNull)(appOutDir);
if (outStat == null) {
throw new Error(`Output directory "${ appOutDir }" does not exist. Seems like a wrong configuration.`);
} else if (!outStat.isDirectory()) {
throw new Error(`Output directory "${ appOutDir }" is not a directory. Seems like a wrong configuration.`);
}
const resourcesDir = _this3.getResourcesDir(appOutDir);
yield _this3.checkFileInPackage(resourcesDir, _this3.appInfo.metadata.main || "index.js", "Application entry file", isAsar);
yield _this3.checkFileInPackage(resourcesDir, "package.json", "Application", isAsar);
})();
}
archiveApp(format, appOutDir, outFile) {
var _this4 = this;
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const isMac = _this4.platform === (_metadata || _load_metadata()).Platform.MAC;
return (0, (_archive || _load_archive()).archiveApp)(_this4.devMetadata.build.compression, format, outFile, isMac ? (_path || _load_path()).join(appOutDir, `${ _this4.appInfo.productFilename }.app`) : appOutDir, isMac);
})();
}
generateName(ext, arch, deployment) {
let classifier = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
let c = null;
if (arch === (_metadata || _load_metadata()).Arch.x64) {
if (ext === "AppImage") {
c = "x86_64";
} else if (ext === "deb") {
c = "amd64";
}
} else {
c = (_metadata || _load_metadata()).Arch[arch];
}
if (c == null) {
c = classifier;
} else if (classifier != null) {
c += `-${ classifier }`;
}
return this.generateName2(ext, c, deployment);
}
generateName2(ext, classifier, deployment) {
const dotExt = ext == null ? "" : `.${ ext }`;
return `${ deployment ? this.appInfo.name : this.appInfo.productFilename }-${ this.appInfo.version }${ classifier == null ? "" : `-${ classifier }` }${ dotExt }`;
}
getDefaultIcon(ext) {
var _this5 = this;
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
const resourceList = yield _this5.resourceList;
const name = `icon.${ ext }`;
if (resourceList.indexOf(name) !== -1) {
return (_path || _load_path()).join(_this5.buildResourcesDir, name);
} else {
(0, (_log || _load_log()).warn)("Application icon is not set, default Electron icon will be used");
return null;
}
})();
}
getTempFile(suffix) {
return this.info.tempDirManager.getTempFile(suffix);
}
getFileAssociations() {
return (0, (_util || _load_util()).asArray)(this.devMetadata.build.fileAssociations).concat((0, (_util || _load_util()).asArray)(this.platformSpecificBuildOptions.fileAssociations));
}
getResource(custom) {
var _this6 = this;
for (var _len = arguments.length, names = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
names[_key - 1] = arguments[_key];
}
return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () {
if (custom === undefined) {
const resourceList = yield _this6.resourceList;
for (let name of names) {
if (resourceList.indexOf(name) !== -1) {
return (_path || _load_path()).join(_this6.buildResourcesDir, name);
}
}
} else if (!(0, (_util || _load_util()).isEmptyOrSpaces)(custom)) {
return (_path || _load_path()).resolve(_this6.projectDir, custom);
}
return null;
})();
}
}
exports.PlatformPackager = PlatformPackager;
function getArchSuffix(arch) {
return arch === (_metadata || _load_metadata()).Arch.x64 ? "" : `-${ (_metadata || _load_metadata()).Arch[arch] }`;
}
// fpm bug - rpm build --description is not escaped, well... decided to replace quite to smart quote
// http://leancrew.com/all-this/2010/11/smart-quotes-in-javascript/
function smarten(s) {
// opening singles
s = s.replace(/(^|[-\u2014\s(\["])'/g, "$1\u2018");
// closing singles & apostrophes
s = s.replace(/'/g, "\u2019");
// opening doubles
s = s.replace(/(^|[-\u2014/\[(\u2018\s])"/g, "$1\u201c");
// closing doubles
s = s.replace(/"/g, "\u201d");
return s;
}
// remove leading dot
function normalizeExt(ext) {
return ext.startsWith(".") ? ext.substring(1) : ext;
}
function getPublishConfigs(packager, platformSpecificBuildOptions) {
// check build.nsis (target)
let publishers = platformSpecificBuildOptions.publish;
// if explicitly set to null - do not publish
if (publishers === null) {
return null;
}
// check build.win (platform)
if (packager.platformSpecificBuildOptions !== platformSpecificBuildOptions) {
publishers = packager.platformSpecificBuildOptions.publish;
if (publishers === null) {
return null;
}
}
if (publishers == null) {
publishers = packager.info.devMetadata.build.publish;
if (publishers === null) {
return null;
}
if (publishers == null && !(0, (_util || _load_util()).isEmptyOrSpaces)(process.env.GH_TOKEN)) {
publishers = [{ provider: "github" }];
}
// if both tokens are set — still publish to github (because default publisher is github)
if (publishers == null && !(0, (_util || _load_util()).isEmptyOrSpaces)(process.env.BT_TOKEN)) {
publishers = [{ provider: "bintray" }];
}
}
return (0, (_util || _load_util()).asArray)(publishers).map(it => typeof it === "string" ? { provider: it } : it);
}