@sprucelabs/spruce-cli
Version:
Command line interface for building Spruce skills.
247 lines • 12.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
const uniq_1 = __importDefault(require("lodash/uniq"));
const syncSchemasOptions_schema_1 = __importDefault(require("./../../../.spruce/schemas/spruceCli/v2020_07_22/syncSchemasOptions.schema"));
const SpruceError_1 = __importDefault(require("../../../errors/SpruceError"));
const SchemaTemplateItemBuilder_1 = __importDefault(require("../../../templateItemBuilders/SchemaTemplateItemBuilder"));
const action_utility_1 = __importDefault(require("../../../utilities/action.utility"));
const AbstractAction_1 = __importDefault(require("../../AbstractAction"));
const schemaDisk_utility_1 = __importDefault(require("../utilities/schemaDisk.utility"));
const ValueTypeBuilder_1 = __importDefault(require("../ValueTypeBuilder"));
class SyncAction extends AbstractAction_1.default {
optionsSchema = syncSchemasOptions_schema_1.default;
commandAliases = ['sync.schemas'];
invocationMessage = 'Building schemas and generating types... 📃';
schemaWriter = this.Writer('schema');
schemaStore = this.Store('schema');
skillStore = this.Store('skill');
async execute(options) {
const normalizedOptions = this.validateAndNormalizeOptions(options);
let { schemaTypesDestinationDirOrFile, fieldTypesDestinationDir, schemaLookupDir, addonsLookupDir, shouldEnableVersioning, globalSchemaNamespace, shouldFetchRemoteSchemas, shouldGenerateCoreSchemaTypes, shouldFetchLocalSchemas, generateFieldTypes, generateStandaloneTypesFile, deleteDestinationDirIfNoSchemas, shouldFetchCoreSchemas, registerBuiltSchemas, syncingMessage, deleteOrphanedSchemas, moduleToImportFromWhenRemote, shouldInstallMissingDependencies, } = normalizedOptions;
this.ui.startLoading('Loading details about your skill... 🧐');
let localNamespace = await this.skillStore.loadCurrentSkillsNamespace();
let shouldImportCoreSchemas = true;
if (shouldGenerateCoreSchemaTypes) {
shouldFetchRemoteSchemas = false;
shouldFetchLocalSchemas = true;
shouldFetchCoreSchemas = false;
registerBuiltSchemas = true;
generateStandaloneTypesFile = true;
shouldImportCoreSchemas = false;
localNamespace = spruce_skill_utils_1.CORE_NAMESPACE;
}
let coreSyncResults;
const { resolvedFieldTypesDestination, resolvedSchemaTypesDestinationDirOrFile, resolvedSchemaTypesDestination, } = schemaDisk_utility_1.default.resolveTypeFilePaths({
cwd: this.cwd,
generateStandaloneTypesFile,
schemaTypesDestinationDirOrFile,
fieldTypesDestinationDir,
language: this.getProjectLanguage(),
});
this.ui.startLoading('Generating field types...');
const { fieldTemplateItems, fieldErrors, generateFieldFiles } = await this.generateFieldTemplateItems({
addonsLookupDir,
shouldGenerateFieldTypes: generateFieldTypes,
resolvedFieldTypesDestination,
});
this.ui.startLoading(syncingMessage);
const schemaErrors = [];
let schemaTemplateItems;
let typeResults = [];
try {
const templateResults = await this.generateSchemaTemplateItems({
schemaLookupDir,
shouldFetchLocalSchemas,
moduleToImportFromWhenRemote,
resolvedSchemaTypesDestinationDirOrFile,
shouldEnableVersioning,
shouldFetchRemoteSchemas,
shouldFetchCoreSchemas,
localNamespace,
});
schemaErrors.push(...templateResults.schemaErrors);
schemaTemplateItems = templateResults.schemaTemplateItems;
}
catch (err) {
schemaErrors.push(err);
}
if (schemaErrors.length === 0 && schemaTemplateItems) {
if (deleteDestinationDirIfNoSchemas &&
schemaTemplateItems.length === 0) {
spruce_skill_utils_1.diskUtil.deleteDir(resolvedSchemaTypesDestinationDirOrFile);
return {};
}
if (deleteOrphanedSchemas) {
this.ui.startLoading('Identifying orphaned schemas...');
await schemaDisk_utility_1.default.deleteOrphanedSchemas(resolvedSchemaTypesDestinationDirOrFile, schemaTemplateItems);
}
await this.optionallyInstallRemoteModules(schemaTemplateItems, shouldInstallMissingDependencies);
let valueTypes;
try {
valueTypes = this.isInGoProject()
? undefined
: await this.generateValueTypes({
resolvedDestination: resolvedFieldTypesDestination,
fieldTemplateItems,
schemaTemplateItems,
globalSchemaNamespace: globalSchemaNamespace ?? undefined,
});
}
catch (err) {
schemaErrors.push(err);
}
if (valueTypes || this.isInGoProject()) {
try {
this.ui.startLoading('Determining what changed... ⚡️');
let goModuleNameAndPath = undefined;
if (this.isInGoProject()) {
goModuleNameAndPath = this.skillStore.getGoModuleName({
shouldIncludePathFromCwd: true,
});
}
typeResults = await this.schemaWriter.writeSchemasAndTypes(resolvedSchemaTypesDestination, {
registerBuiltSchemas,
fieldTemplateItems,
schemaTemplateItems,
shouldImportCoreSchemas,
valueTypes,
goModuleNameAndPath,
language: this.getProjectLanguage(),
globalSchemaNamespace: globalSchemaNamespace ?? undefined,
typesTemplate: this.resolveTypesTemplate(generateStandaloneTypesFile),
});
}
catch (err) {
schemaErrors.push(err);
}
}
}
const p = resolvedSchemaTypesDestination;
const dir = spruce_skill_utils_1.diskUtil.isDir(p) ? p : path_1.default.dirname(p);
if (spruce_skill_utils_1.diskUtil.doesDirExist(dir)) {
spruce_skill_utils_1.diskUtil.deleteEmptyDirs(dir);
}
this.ui.stopLoading();
const errors = [...schemaErrors, ...fieldErrors];
return action_utility_1.default.mergeActionResults(coreSyncResults || {}, {
files: [...typeResults, ...generateFieldFiles],
errors: errors.length > 0 ? errors : undefined,
meta: {
schemaTemplateItems,
fieldTemplateItems,
},
});
}
resolveTypesTemplate(generateStandaloneTypesFile) {
if (this.isInGoProject()) {
return 'schema/schemas.go.hbs';
}
return generateStandaloneTypesFile
? 'schema/core.schemas.types.ts.hbs'
: undefined;
}
async optionallyInstallRemoteModules(schemaTemplateItems, forceInstall) {
const modules = (0, uniq_1.default)(schemaTemplateItems
.map((item) => item.importFrom)
.filter((i) => !!i));
if (this.isInGoProject()) {
return;
}
const notInstalled = [];
const pkg = this.Service('pkg');
for (const m of modules) {
if (!pkg.isInstalled(m) && notInstalled.indexOf(m) === -1) {
notInstalled.push(m);
}
}
if (notInstalled.length > 0) {
if (!forceInstall) {
this.ui.stopLoading();
this.ui.renderSection({
headline: `Missing ${notInstalled.length} module${notInstalled.length === 1 ? '' : 's'}`,
lines: [
`Looks like I need to install the following modules to continue to sync schemas:`,
'',
...notInstalled,
],
});
const confirm = await this.ui.confirm('Should we do that now?');
if (!confirm) {
throw new SpruceError_1.default({
code: 'ACTION_CANCELLED',
friendlyMessage: `I can't sync schemas because of the missing modules.`,
});
}
}
this.ui.startLoading(`Installing ${notInstalled.length} missing module${notInstalled.length === 1 ? '' : 's...'}`);
const pkg = this.Service('pkg');
await pkg.install(notInstalled);
this.ui.stopLoading();
}
}
async generateSchemaTemplateItems(options) {
const { schemaLookupDir, resolvedSchemaTypesDestinationDirOrFile, shouldEnableVersioning, shouldFetchRemoteSchemas, shouldFetchCoreSchemas, shouldFetchLocalSchemas, localNamespace, moduleToImportFromWhenRemote, } = options;
this.ui.startLoading('Loading builders...');
const { schemasByNamespace, errors: schemaErrors } = await this.schemaStore.fetchSchemas({
localSchemaLookupDir: schemaLookupDir,
shouldFetchLocalSchemas,
shouldFetchRemoteSchemas,
shouldEnableVersioning,
moduleToImportFromWhenRemote,
localNamespace,
shouldFetchCoreSchemas,
didUpdateHandler: (message) => {
this.ui.startLoading(message);
},
});
const hashSpruceDestination = this.isInGoProject()
? this.cwd
: resolvedSchemaTypesDestinationDirOrFile.replace(spruce_skill_utils_1.diskUtil.resolveHashSprucePath(this.cwd), '#spruce');
let total = 0;
let totalNamespaces = 0;
for (const namespace of Object.keys(schemasByNamespace)) {
totalNamespaces++;
total += schemasByNamespace[namespace].length;
}
this.ui.startLoading(`Building ${total} schemas from ${totalNamespaces} namespaces.`);
const schemaTemplateItemBuilder = new SchemaTemplateItemBuilder_1.default(localNamespace);
const schemaTemplateItems = schemaTemplateItemBuilder.buildTemplateItems(schemasByNamespace, hashSpruceDestination);
return { schemaTemplateItems, schemaErrors };
}
isInGoProject() {
return this.getProjectLanguage() === 'go';
}
async generateFieldTemplateItems(options) {
if (this.isInGoProject()) {
return {
generateFieldFiles: [],
fieldTemplateItems: [],
fieldErrors: [],
};
}
const { addonsLookupDir, shouldGenerateFieldTypes: generateFieldTypes, resolvedFieldTypesDestination, } = options;
const action = this.Action('schema', 'syncFields');
const results = await action.execute({
fieldTypesDestinationDir: resolvedFieldTypesDestination,
addonsLookupDir,
generateFieldTypes,
});
return {
generateFieldFiles: results.files ?? [],
fieldTemplateItems: results.meta?.fieldTemplateItems ?? [],
fieldErrors: results.errors ?? [],
};
}
async generateValueTypes(options) {
this.ui.startLoading('Generating value types...');
const builder = new ValueTypeBuilder_1.default(this.schemaWriter, this.Service('import'));
return builder.generateValueTypes(options);
}
}
exports.default = SyncAction;
//# sourceMappingURL=SyncAction.js.map