UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

211 lines • 8.94 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 globby_1 = __importDefault(require("@sprucelabs/globby")); const mercury_types_1 = require("@sprucelabs/mercury-types"); const schema_1 = require("@sprucelabs/schema"); const spruce_event_utils_1 = require("@sprucelabs/spruce-event-utils"); const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils"); const lodash_1 = require("lodash"); const SpruceError_1 = __importDefault(require("../../../errors/SpruceError")); const AbstractStore_1 = __importDefault(require("../../../stores/AbstractStore")); const eventContractCleaner_utility_1 = require("../../../utilities/eventContractCleaner.utility"); class EventStore extends AbstractStore_1.default { name = 'event'; static contractCache = {}; static localEventCache; static clearCache() { EventStore.localEventCache = undefined; EventStore.contractCache = {}; } async fetchEventContracts(options) { const { localNamespace, didUpdateHandler, namespaces, shouldOnlySyncRemoteEvents, } = options ?? {}; didUpdateHandler?.('Pulling remote contracts...'); let contracts; try { contracts = await this.fetchRemoteContracts(namespaces); } catch (err) { const error = err.options?.responseErrors?.[0] ?? err; throw error; } if (shouldOnlySyncRemoteEvents) { return { contracts, errors: [], }; } const localContract = localNamespace && (await this.loadLocalContract(localNamespace, didUpdateHandler)); if (localNamespace) { this.filterOutLocalEventsFromRemoteContractsMutating(contracts, localNamespace); } if (localContract) { contracts.push(localContract); } return { contracts, errors: [], }; } async fetchRemoteContracts(namespaces) { const key = namespaces?.join('|') ?? '_'; if (!EventStore.contractCache[key]) { const client = await this.connectToApi({ shouldAuthAsCurrentSkill: true, }); const [{ contracts }] = await client.emitAndFlattenResponses('get-event-contracts::v2020_12_25', { target: { namespaces, }, }); EventStore.contractCache[key] = contracts; } return (0, lodash_1.cloneDeep)(EventStore.contractCache[key]); } filterOutLocalEventsFromRemoteContractsMutating(remoteContracts, localNamespace) { const ns = spruce_skill_utils_1.namesUtil.toKebab(localNamespace); for (const contract of remoteContracts) { const sigs = spruce_event_utils_1.eventContractUtil.getNamedEventSignatures(contract); for (const sig of sigs) { if (sig.eventNamespace === ns) { delete contract.eventSignatures[sig.fullyQualifiedEventName]; } } } } async loadLocalContract(localNamespace, didUpdateHandler) { if (EventStore.localEventCache) { return EventStore.localEventCache; } const localMatches = await (0, globby_1.default)(this.generateGlobbyForLocalEvents()); const ns = spruce_skill_utils_1.namesUtil.toKebab(localNamespace); const eventSignatures = {}; const filesByFqenAndEventKey = []; didUpdateHandler?.(`Importing ${localMatches.length} local event signature files...`); await Promise.all(localMatches.map(async (match) => { let fqen; let eventKey; try { const { eventName, version } = spruce_event_utils_1.eventDiskUtil.splitPathToEvent(match); fqen = spruce_event_utils_1.eventNameUtil.join({ eventName, version, eventNamespace: ns, }); const filename = path_1.default.basename(match); const map = eventFileNamesImportKeyMap[filename]; if (map) { //@ts-ignore eventKey = map.key; filesByFqenAndEventKey.push({ fqen, isSchema: map.isSchema, match, eventKey: eventKey, }); } } catch (err) { throw new SpruceError_1.default({ code: 'INVALID_EVENT_CONTRACT', fullyQualifiedEventName: fqen ?? 'Bad event name', brokenProperty: eventKey ?? '*** major failure ***', originalError: err, }); } })); const matches = filesByFqenAndEventKey.map((o) => o.match); const importsInOrder = (await this.Service('import').bulkImport(matches)); const importsByName = {}; for (let idx = 0; idx < filesByFqenAndEventKey.length; idx++) { const imported = importsInOrder[idx]; const { fqen, eventKey, isSchema } = filesByFqenAndEventKey[idx]; if (isSchema) { try { (0, schema_1.validateSchema)(imported); } catch (err) { throw new SpruceError_1.default({ code: 'INVALID_EVENT_CONTRACT', fullyQualifiedEventName: fqen, brokenProperty: eventKey, originalError: err, }); } } if (!importsByName[fqen]) { importsByName[fqen] = {}; } //@ts-ignore importsByName[fqen][eventKey] = imported; } Object.keys(importsByName).forEach((fqen) => { const imported = importsByName[fqen]; const { eventName } = spruce_event_utils_1.eventNameUtil.split(fqen); eventSignatures[fqen] = { emitPayloadSchema: (0, spruce_event_utils_1.buildEmitTargetAndPayloadSchema)({ eventName, payloadSchema: imported.emitPayload, targetSchema: imported.emitTarget, }), responsePayloadSchema: imported.responsePayload, emitPermissionContract: imported.emitPermissions, listenPermissionContract: imported.listenPermissions, ...imported.options, }; }); didUpdateHandler?.(`Loaded ${Object.keys(eventSignatures).length} local event signatures...`); if (Object.keys(eventSignatures).length > 0) { const cleaned = eventContractCleaner_utility_1.eventContractCleanerUtil.cleanPayloadsAndPermissions({ eventSignatures, }); (0, mercury_types_1.validateEventContract)(cleaned); EventStore.localEventCache = cleaned; return cleaned; } return null; } generateGlobbyForLocalEvents() { return spruce_skill_utils_1.diskUtil.resolvePath(this.cwd, 'src', '**', 'events', '**/*.(builder|options).ts'); } async registerEventContract(options) { const client = await this.connectToApi({ shouldAuthAsCurrentSkill: true, }); const results = await client.emit('register-events::v2020_12_25', { payload: { contract: options.eventContract, }, }); spruce_event_utils_1.eventResponseUtil.getFirstResponseOrThrow(results); EventStore.contractCache = {}; return results; } async unRegisterEvents(options) { const client = await this.connectToApi({ shouldAuthAsCurrentSkill: true, }); const results = await client.emit('unregister-events::v2020_12_25', { payload: options, }); spruce_event_utils_1.eventResponseUtil.getFirstResponseOrThrow(results); EventStore.contractCache = {}; } } exports.default = EventStore; const eventFileNamesImportKeyMap = { 'event.options.ts': { key: 'options', isSchema: false }, 'emitPayload.builder.ts': { key: 'emitPayload', isSchema: true }, 'emitTarget.builder.ts': { key: 'emitTarget', isSchema: true }, 'responsePayload.builder.ts': { key: 'responsePayload', isSchema: true }, 'emitPermissions.builder.ts': { key: 'emitPermissions', isSchema: false }, 'listenPermissions.builder.ts': { key: 'listenPermissions', isSchema: false, }, }; //# sourceMappingURL=EventStore.js.map