@vendure/cli
Version:
A modern, headless ecommerce framework
216 lines • 8.56 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.analyzeProject = analyzeProject;
exports.selectPlugin = selectPlugin;
exports.selectEntity = selectEntity;
exports.selectMultiplePluginClasses = selectMultiplePluginClasses;
exports.selectServiceRef = selectServiceRef;
exports.getServices = getServices;
const prompts_1 = require("@clack/prompts");
const path_1 = __importDefault(require("path"));
const picocolors_1 = __importDefault(require("picocolors"));
const add_service_1 = require("../commands/add/service/add-service");
const constants_1 = require("../constants");
const ast_utils_1 = require("../utilities/ast-utils");
const utils_1 = require("../utilities/utils");
const service_ref_1 = require("./service-ref");
const vendure_plugin_ref_1 = require("./vendure-plugin-ref");
function createPluginOptions(pluginClasses, project) {
var _a, _b;
const pluginNames = pluginClasses.map(c => c.getName());
const nameCounts = pluginNames.reduce((acc, name) => {
acc[name] = (acc[name] || 0) + 1;
return acc;
}, {});
const projectRoot = ((_a = project.getDirectory('.')) === null || _a === void 0 ? void 0 : _a.getPath()) || ((_b = project.getRootDirectories()[0]) === null || _b === void 0 ? void 0 : _b.getPath()) || '';
return pluginClasses.map(c => {
const name = c.getName();
const hasDuplicates = nameCounts[name] > 1;
let label = picocolors_1.default.bold(name);
if (hasDuplicates) {
const fullPath = c.getSourceFile().getFilePath();
const relativePath = path_1.default.relative(projectRoot, fullPath);
label = `${picocolors_1.default.bold(name)} ${picocolors_1.default.dim(picocolors_1.default.italic(`(${relativePath})`))}`;
}
return {
value: c,
label,
};
});
}
async function analyzeProject(options) {
const providedVendurePlugin = options.providedVendurePlugin;
let project = providedVendurePlugin === null || providedVendurePlugin === void 0 ? void 0 : providedVendurePlugin.classDeclaration.getProject();
let tsConfigPath;
let vendureTsConfig;
let rootTsConfig;
let isMonorepo;
if (!providedVendurePlugin) {
const projectSpinner = (0, prompts_1.spinner)();
const tsConfigFile = (0, ast_utils_1.selectTsConfigFile)();
projectSpinner.start('Analyzing project...');
await (0, utils_1.pauseForPromptDisplay)();
const result = await (0, ast_utils_1.getTsMorphProject)({
compilerOptions: {
rootDir: './src',
},
}, tsConfigFile);
project = result.project;
tsConfigPath = result.tsConfigPath;
vendureTsConfig = result.vendureTsConfig;
rootTsConfig = result.rootTsConfig;
isMonorepo = result.isMonorepo;
projectSpinner.stop('Project analyzed');
}
return {
project: project,
tsConfigPath,
vendureTsConfig,
rootTsConfig,
isMonorepo,
config: options.config,
};
}
async function selectPlugin(project, cancelledMessage) {
const pluginClasses = (0, ast_utils_1.getPluginClasses)(project);
if (pluginClasses.length === 0) {
(0, prompts_1.cancel)(constants_1.Messages.NoPluginsFound);
process.exit(0);
}
const targetPlugin = await (0, utils_1.withInteractiveTimeout)(async () => {
return await (0, prompts_1.select)({
message: 'To which plugin would you like to add the feature?',
options: createPluginOptions(pluginClasses, project),
maxItems: 10,
});
});
if ((0, prompts_1.isCancel)(targetPlugin)) {
(0, prompts_1.cancel)(cancelledMessage);
process.exit(0);
}
return new vendure_plugin_ref_1.VendurePluginRef(targetPlugin);
}
async function selectEntity(plugin) {
const entities = plugin.getEntities();
if (entities.length === 0) {
throw new Error(constants_1.Messages.NoEntitiesFound);
}
const targetEntity = await (0, utils_1.withInteractiveTimeout)(async () => {
return await (0, prompts_1.select)({
message: 'Select an entity',
options: entities
.filter(e => !e.isTranslation())
.map(e => ({
value: e,
label: e.name,
})),
maxItems: 10,
});
});
if ((0, prompts_1.isCancel)(targetEntity)) {
(0, prompts_1.cancel)('Cancelled');
process.exit(0);
}
return targetEntity;
}
async function selectMultiplePluginClasses(project, cancelledMessage) {
const pluginClasses = (0, ast_utils_1.getPluginClasses)(project);
if (pluginClasses.length === 0) {
(0, prompts_1.cancel)(constants_1.Messages.NoPluginsFound);
process.exit(0);
}
const selectAll = await (0, utils_1.withInteractiveTimeout)(async () => {
return await (0, prompts_1.select)({
message: 'To which plugin would you like to add the feature?',
options: [
{
value: 'all',
label: 'All plugins',
},
{
value: 'specific',
label: 'Specific plugins (you will be prompted to select the plugins)',
},
],
});
});
if ((0, prompts_1.isCancel)(selectAll)) {
(0, prompts_1.cancel)(cancelledMessage);
process.exit(0);
}
if (selectAll === 'all') {
return pluginClasses.map(pluginClass => new vendure_plugin_ref_1.VendurePluginRef(pluginClass));
}
const targetPlugins = await (0, utils_1.withInteractiveTimeout)(async () => {
return await (0, prompts_1.multiselect)({
message: 'Select one or more plugins (use ↑, ↓, space to select)',
options: createPluginOptions(pluginClasses, project),
});
});
if ((0, prompts_1.isCancel)(targetPlugins)) {
(0, prompts_1.cancel)(cancelledMessage);
process.exit(0);
}
return targetPlugins.map(pluginClass => new vendure_plugin_ref_1.VendurePluginRef(pluginClass));
}
async function selectServiceRef(project, plugin, canCreateNew = true) {
const serviceRefs = getServices(project).filter(sr => {
return sr.classDeclaration
.getSourceFile()
.getDirectoryPath()
.includes(plugin.getSourceFile().getDirectoryPath());
});
if (serviceRefs.length === 0 && !canCreateNew) {
throw new Error(constants_1.Messages.NoServicesFound);
}
const result = await (0, utils_1.withInteractiveTimeout)(async () => {
return await (0, prompts_1.select)({
message: 'Which service contains the business logic for this API extension?',
maxItems: 8,
options: [
...(canCreateNew
? [
{
value: 'new',
label: `Create new generic service`,
},
]
: []),
...serviceRefs.map(sr => {
const features = sr.crudEntityRef
? `CRUD service for ${sr.crudEntityRef.name}`
: `Generic service`;
const label = `${sr.name}: (${features})`;
return {
value: sr,
label,
};
}),
],
});
});
if ((0, prompts_1.isCancel)(result)) {
(0, prompts_1.cancel)('Cancelled');
process.exit(0);
}
if (result === 'new') {
return add_service_1.addServiceCommand.run({ type: 'basic', plugin }).then(r => r.serviceRef);
}
else {
return result;
}
}
function getServices(project) {
const servicesSourceFiles = project.getSourceFiles().filter(sf => {
return (sf.getDirectory().getPath().endsWith('/services') ||
sf.getDirectory().getPath().endsWith('/service'));
});
return servicesSourceFiles
.flatMap(sf => sf.getClasses())
.filter(classDeclaration => classDeclaration.getDecorator('Injectable'))
.map(classDeclaration => new service_ref_1.ServiceRef(classDeclaration));
}
//# sourceMappingURL=shared-prompts.js.map