vtex
Version:
The platform for e-commerce apps
141 lines (140 loc) • 6.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupTypings = exports.getBuilderDependencies = void 0;
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const ramda_1 = tslib_1.__importDefault(require("ramda"));
const env_1 = require("../../api/env");
const Builder_1 = require("../../api/clients/IOClients/apps/Builder");
const ErrorKinds_1 = require("../../api/error/ErrorKinds");
const ErrorReport_1 = require("../../api/error/ErrorReport");
const SessionManager_1 = require("../../api/session/SessionManager");
const locator_1 = require("../../api/locator");
const logger_1 = tslib_1.__importDefault(require("../../api/logger"));
const utils_1 = require("../../api/modules/utils");
const utils_2 = require("../utils");
const consts_1 = require("./consts");
const utils_3 = require("./utils");
const getVendor = (appId) => appId.split('.')[0];
const typingsURLRegex = /_v\/\w*\/typings/;
const appTypingsURL = async (appName, appMajorLocator, ignoreLinked) => {
const { workspace, account } = SessionManager_1.SessionManager.getSingleton();
const appId = ignoreLinked
? await utils_1.appIdFromRegistry(appName, appMajorLocator)
: await utils_1.resolveAppId(appName, appMajorLocator);
const vendor = getVendor(appId);
const linked = utils_1.isLinked({ version: appId, vendor, name: '', builders: {} });
const oldSuffix = `/_types/react`;
const newSuffix = `/@types/${appName}`;
const base = linked && !ignoreLinked
? `https://${workspace}--${account}.${env_1.publicEndpoint()}/_v/private/typings/linked/v1/${appId}/public`
: `http://${vendor}.vtexassets.com/_v/public/typings/v1/${appId}/public`;
logger_1.default.info(`Checking if ${chalk_1.default.bold(appId)} has new types format`);
try {
const newTypesExist = !(await utils_3.checkIfTarGzIsEmpty(base + newSuffix));
return base + (newTypesExist ? newSuffix : oldSuffix);
}
catch (err) {
logger_1.default.error(`Error checking if types package is empty for ${base + newSuffix}`);
throw err;
}
};
const appsWithTypingsURLs = async (appDependencies, ignoreLinked) => {
const result = {};
const appNamesAndDependencies = ramda_1.default.toPairs(appDependencies);
await Promise.all(appNamesAndDependencies.map(async ([appName, appVersion]) => {
try {
result[appName] = await appTypingsURL(appName, appVersion, ignoreLinked);
}
catch (err) {
logger_1.default.error(`Unable to generate typings URL for ${appName}@${appVersion}.`);
ErrorReport_1.ErrorReport.createAndMaybeRegisterOnTelemetry({
kind: ErrorKinds_1.ErrorKinds.SETUP_TYPINGS_ERROR,
originalError: err,
}).logErrorForUser({
coreLogLevelDefault: 'debug',
logLevels: { core: { errorId: 'error' } },
});
}
}));
return result;
};
exports.getBuilderDependencies = (manifestDependencies, typingsData, version, builder) => {
var _a, _b;
const injectedDependencies = ((_b = (_a = typingsData === null || typingsData === void 0 ? void 0 : typingsData[builder]) === null || _a === void 0 ? void 0 : _a[version]) === null || _b === void 0 ? void 0 : _b.injectedDependencies) || {};
return {
...manifestDependencies.dependencies,
...manifestDependencies.peerDependencies,
...injectedDependencies,
};
};
const injectTypingsInPackageJson = async (appDeps, ignoreLinked, builder) => {
let packageJson;
try {
packageJson = utils_3.packageJsonEditor.read(builder);
}
catch (e) {
if (e.code === 'ENOENT') {
logger_1.default.warn(`No package.json found in ${utils_3.packageJsonEditor.path(builder)}.`);
}
else
logger_1.default.error(e);
return;
}
logger_1.default.info(`Injecting typings on ${builder}'s package.json`);
const oldDevDeps = packageJson.devDependencies || {};
const oldTypingsEntries = ramda_1.default.filter(ramda_1.default.test(typingsURLRegex), oldDevDeps);
const newTypingsEntries = await appsWithTypingsURLs(appDeps, ignoreLinked);
if (!ramda_1.default.equals(oldTypingsEntries, newTypingsEntries)) {
const cleanOldDevDeps = ramda_1.default.reject(ramda_1.default.test(typingsURLRegex), oldDevDeps);
utils_3.packageJsonEditor.write(builder, {
...packageJson,
...{ devDependencies: utils_3.sortObject({ ...cleanOldDevDeps, ...newTypingsEntries }) },
});
try {
utils_2.runYarn(builder, true);
}
catch (e) {
logger_1.default.error(`Error running Yarn in ${builder}.`);
ErrorReport_1.ErrorReport.createAndMaybeRegisterOnTelemetry({
kind: ErrorKinds_1.ErrorKinds.SETUP_TSCONFIG_ERROR,
originalError: e,
});
utils_3.packageJsonEditor.write(builder, packageJson); // Revert package.json to original state.
}
}
};
exports.setupTypings = async (manifest, ignoreLinked, buildersWithTypes = consts_1.BUILDERS_WITH_TYPES) => {
logger_1.default.info('Setting up typings');
const appName = `${manifest.vendor}.${manifest.name}`;
const appMajor = locator_1.toMajorRange(manifest.version);
const builderClient = Builder_1.Builder.createClient({}, { retries: 2, timeout: 10000 });
const builders = ramda_1.default.keys(ramda_1.default.prop('builders', manifest) || {});
const filteredBuilders = ramda_1.default.intersection(builders, buildersWithTypes);
const shouldIncludeSelfAsDevDependency = builder => ['node', 'react'].includes(builder);
try {
logger_1.default.info('Fetching names of dependencies injected by BuilderHub');
const typingsData = await builderClient.typingsInfo();
const allDependencies = {
dependencies: manifest.dependencies,
peerDependencies: manifest.peerDependencies,
};
const buildersWithAllDeps = filteredBuilders.map((builder) => {
return {
builder,
deps: {
...exports.getBuilderDependencies(allDependencies, typingsData, manifest.builders[builder], builder),
...(shouldIncludeSelfAsDevDependency(builder) ? { [appName]: appMajor } : {}),
},
};
});
await Promise.all(buildersWithAllDeps.map(({ builder, deps }) => injectTypingsInPackageJson(deps, ignoreLinked, builder)));
logger_1.default.info('Finished setting up typings');
}
catch (err) {
ErrorReport_1.ErrorReport.createAndMaybeRegisterOnTelemetry({
kind: ErrorKinds_1.ErrorKinds.SETUP_TYPINGS_ERROR,
originalError: err,
}).logErrorForUser();
}
};