@sprucelabs/spruce-cli
Version:
Command line interface for building Spruce skills.
211 lines • 8.94 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 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