UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

213 lines 10.9 kB
"use strict"; 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'); async execute(options) { const normalizedOptions = this.validateAndNormalizeOptions(options); const isInCoreSchemasModule = this.Service('pkg').get('name') === '@sprucelabs/spruce-core-schemas'; let { schemaTypesDestinationDirOrFile, fieldTypesDestinationDir, schemaLookupDir, addonsLookupDir, shouldEnableVersioning, globalSchemaNamespace, shouldFetchRemoteSchemas, shouldGenerateCoreSchemaTypes = isInCoreSchemasModule, shouldFetchLocalSchemas, generateFieldTypes, generateStandaloneTypesFile, deleteDestinationDirIfNoSchemas, shouldFetchCoreSchemas, registerBuiltSchemas, syncingMessage, deleteOrphanedSchemas, moduleToImportFromWhenRemote, shouldInstallMissingDependencies, } = normalizedOptions; this.ui.startLoading('Loading details about your skill... 🧐'); let localNamespace = await this.Store('skill').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, }); 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 = await this.generateValueTypes({ resolvedDestination: resolvedFieldTypesDestination, fieldTemplateItems, schemaTemplateItems, globalSchemaNamespace: globalSchemaNamespace ?? undefined, }); } catch (err) { schemaErrors.push(err); } if (valueTypes) { try { this.ui.startLoading('Determining what changed... ⚡️'); typeResults = await this.schemaWriter.writeSchemasAndTypes(resolvedSchemaTypesDestination, { registerBuiltSchemas, fieldTemplateItems, schemaTemplateItems, shouldImportCoreSchemas, valueTypes, globalSchemaNamespace: globalSchemaNamespace ?? undefined, typesTemplate: generateStandaloneTypesFile ? 'schema/core.schemas.types.ts.hbs' : undefined, }); } catch (err) { schemaErrors.push(err); } } } const p = resolvedSchemaTypesDestination; spruce_skill_utils_1.diskUtil.deleteEmptyDirs(spruce_skill_utils_1.diskUtil.isDir(p) ? p : path_1.default.dirname(p)); 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, }, }); } async optionallyInstallRemoteModules(schemaTemplateItems, forceInstall) { const modules = (0, uniq_1.default)(schemaTemplateItems .map((item) => item.importFrom) .filter((i) => !!i)); 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 = 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 }; } async generateFieldTemplateItems(options) { 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