@sprucelabs/spruce-cli
Version:
Command line interface for building Spruce skills.
244 lines • 12.7 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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 mercury_core_events_1 = require("@sprucelabs/mercury-core-events");
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 test_utils_1 = require("@sprucelabs/test-utils");
const AbstractEventTest_1 = __importDefault(require("../../../tests/AbstractEventTest"));
const coreContract = spruce_event_utils_1.eventContractUtil.unifyContracts(mercury_core_events_1.coreEventContracts);
class KeepingEventsInSyncTest extends AbstractEventTest_1.default {
static get eventContractPath() {
return this.resolveHashSprucePath('events', 'events.contract.ts');
}
static async hasSyncEventsAction() {
await this.Cli();
test_utils_1.assert.isFunction(this.Action('event', 'sync').execute);
}
static async syncsWithoutSavingCoreEventsByDefault() {
await this.FeatureFixture().installCachedFeatures('eventsInNodeModule');
const results = await this.skipInstallSkillPrompts(() => this.Action('event', 'sync').execute({}));
await this.assertValidSyncEventsResults(results);
}
static async mergesGlobalEvents() {
await this.FeatureFixture().installCachedFeatures('events');
const skills = this.getSkillFixture();
await skills.registerCurrentSkill({
name: 'events in sync skill',
});
const skill2 = await skills.seedDemoSkill({ name: 'a temp skill' });
await this.Service('dependency').add({
id: skill2.id,
namespace: skill2.slug,
});
await skills.registerEventContract(skill2, {
eventSignatures: {
'test-sync::v2021_01_01': {
isGlobal: true,
},
},
});
const results = await this.Action('event', 'sync').execute({});
await this.assertValidSyncEventsResults(results);
const fqen = spruce_event_utils_1.eventNameUtil.join({
eventName: 'test-sync',
version: 'v2021_01_01',
eventNamespace: skill2.slug,
});
await this.assertGlobalEventsAreTyped(fqen);
}
static async canSetSkillEventContractTypesFile() {
await this.FeatureFixture().installCachedFeatures('eventsInNodeModule');
await this.skipInstallSkillPrompts(() => this.Action('event', 'sync').execute({
skillEventContractTypesFile: 'testy test',
}));
const contents = spruce_skill_utils_1.diskUtil.readFile(this.eventContractPath);
test_utils_1.assert.doesInclude(contents, `declare module 'testy test'`);
}
static async canSyncOnlyCoreEvents() {
await this.FeatureFixture().installCachedFeatures('eventsInNodeModule');
const promise = this.syncCoreEventsPretendingToBeMercuryTypes();
await this.skipInstallSkillPrompts();
const results = await promise;
await this.assertValidSyncEventsResults(results, true);
}
static async syncingSchemasDoesNotSyncEventSchemasIfEventsHaveNeverBeenSynced() {
const cli = await this.FeatureFixture().installCachedFeatures('events');
const event = cli.getFeature('event');
let wasHit = false;
//@ts-ignore
event.getEventContractBuilder = () => {
wasHit = true;
};
const results = await this.Action('schema', 'sync').execute({});
this.assertCoreEventContractsSavedToDisk(false);
this.assertCorePayloadSchemasAreCreated(results, false);
test_utils_1.assert.isFalse(wasHit);
test_utils_1.assert.isFalse(spruce_skill_utils_1.diskUtil.doesFileExist(this.eventContractPath));
}
static async syncingSchemaAfterSyncEventsSyncsSchemasAndDoesNotWriteCoreEvents() {
const cli = await this.FeatureFixture().installCachedFeatures('events');
await this.Action('event', 'sync').execute({});
const event = cli.getFeature('event');
let wasHit = false;
const oldGetter = event.getEventContractBuilder.bind(event);
//@ts-ignore
event.getEventContractBuilder = () => {
wasHit = true;
return oldGetter();
};
const results = await this.Action('schema', 'sync').execute({});
test_utils_1.assert.isTrue(wasHit);
await this.assertValidSyncSchemasResults(results, false);
}
static async syncingSchemasAfterSyncingCoreEventsSavesCoreEvents() {
await this.FeatureFixture().installCachedFeatures('events');
await this.syncCoreEventsPretendingToBeMercuryTypes();
const results = await this.Action('schema', 'sync').execute({});
await this.assertValidSyncSchemasResults(results, true);
}
static async syncCoreEventsPretendingToBeMercuryTypes() {
const results = await this.Action('event', 'sync').execute({
shouldSyncOnlyCoreEvents: true,
eventBuilderFile: '../../../builder',
skillEventContractTypesFile: '../../builder',
});
const builder = `
export function buildEventContract(..._: any[]):any { return _[0] }
export function buildPermissionContract(..._: any[]):any { return _[0] }
`;
spruce_skill_utils_1.diskUtil.writeFile(this.resolvePath('src', 'builder.ts'), builder);
await this.Service('pkg').uninstall([
'@sprucelabs/mercury-types',
'@sprucelabs/mercury-client',
'@sprucelabs/spruce-event-plugin',
]);
return results;
}
static async assertValidSyncEventsResults(results, shouldSyncOnlyCoreEvents = false) {
test_utils_1.assert.isFalsy(results.errors);
await this.assertValidSyncSchemasResults(results, shouldSyncOnlyCoreEvents);
}
static async assertGlobalEventsAreTyped(eventName) {
const contents = spruce_skill_utils_1.diskUtil.readFile(this.eventContractPath);
test_utils_1.assert.doesInclude(contents, `'${eventName}':`);
}
static async assertValidSyncSchemasResults(results, shouldSyncOnlyCoreEvents) {
test_utils_1.assert.isFalsy(results.errors);
this.assertCoreEventContractsSavedToDisk(shouldSyncOnlyCoreEvents);
this.assertCorePayloadSchemasAreCreated(results, shouldSyncOnlyCoreEvents);
await this.assertEventsHavePayloads(results);
await this.assertCombinedContractContents();
const coreContractContents = spruce_skill_utils_1.diskUtil.readFile(this.eventContractPath);
const search = `did-message::v2020_12_25': MercuryDidMessageEventContract_v2020_12_25['eventSignatures']['did-message::v2020_12_25']`;
if (shouldSyncOnlyCoreEvents) {
test_utils_1.assert.doesInclude(coreContractContents, search);
}
else {
test_utils_1.assert.doesNotInclude(coreContractContents, search);
}
}
static async assertCombinedContractContents() {
const imported = await this.importCombinedContractsFile();
test_utils_1.assert.isTruthy(imported);
test_utils_1.assert.isArray(imported);
const localContract = spruce_event_utils_1.eventContractUtil.unifyContracts(imported);
test_utils_1.assert.isTruthy(localContract);
const sigs = spruce_event_utils_1.eventContractUtil.getNamedEventSignatures(coreContract);
for (const sig of sigs) {
spruce_event_utils_1.eventContractUtil.getSignatureByName(localContract, sig.fullyQualifiedEventName);
}
}
static async importCombinedContractsFile() {
const eventContractsFile = this.eventContractPath;
// hack import to bring types in when importing contract file
if (spruce_skill_utils_1.diskUtil.doesDirExist(this.resolvePath('node_modules/@sprucelabs/mercury-types'))) {
const contents = spruce_skill_utils_1.diskUtil.readFile(eventContractsFile);
spruce_skill_utils_1.diskUtil.writeFile(eventContractsFile, `import '@sprucelabs/mercury-types'\n${contents}`);
}
const imported = await this.Service('import').importDefault(eventContractsFile);
return imported;
}
static async assertEventsHavePayloads(results, eventName = 'authenticate') {
const imported = await this.importCombinedContractsFile();
const contract = spruce_event_utils_1.eventContractUtil.unifyContracts(imported);
test_utils_1.assert.isTruthy(contract);
(0, mercury_types_1.validateEventContract)(contract);
const signature = spruce_event_utils_1.eventContractUtil.getSignatureByName(contract, eventName);
test_utils_1.assert.isTruthy(signature.emitPayloadSchema);
(0, schema_1.validateSchema)(signature.emitPayloadSchema);
test_utils_1.assert.isTruthy(signature.responsePayloadSchema);
(0, schema_1.validateSchema)(signature.responsePayloadSchema);
}
static assertCorePayloadSchemasAreCreated(results, shouldHaveWritten = true) {
const filesToCheck = [
{
name: `unregisterListenersEmitTargetAndPayload.schema.ts`,
path: `schemas${path_1.default.sep}${spruce_skill_utils_1.MERCURY_API_NAMESPACE}`,
},
];
this.assertFilesWereGenerated(filesToCheck, results, shouldHaveWritten);
}
static assertFilesWereGenerated(filesToCheck, results, shouldHaveWritten = true) {
for (const file of filesToCheck) {
const expected = this.resolveHashSprucePath('schemas/mercury/v2020_12_25', file.name);
const doesExist = spruce_skill_utils_1.diskUtil.doesFileExist(expected);
if (shouldHaveWritten) {
test_utils_1.assert.isTrue(doesExist, `Expected to find ${file} on the filesystem.`);
}
else {
test_utils_1.assert.isFalse(doesExist, `Should not have written ${file}.`);
}
}
}
static assertCoreEventContractsSavedToDisk(shouldHaveWritten = true) {
const sigs = spruce_event_utils_1.eventContractUtil.getNamedEventSignatures(coreContract);
for (const sig of sigs) {
const expected = this.resolveHashSprucePath(`events/mercury/${spruce_skill_utils_1.namesUtil.toCamel(sig.eventName)}.v2020_12_25.contract.ts`);
const doesExist = spruce_skill_utils_1.diskUtil.doesFileExist(expected);
if (shouldHaveWritten) {
test_utils_1.assert.isTrue(doesExist, `Expected to write a file ${expected}.`);
}
else {
test_utils_1.assert.isFalse(doesExist, `Generated contract for ${sig.fullyQualifiedEventName} and it should not have because it's a core contract.`);
}
}
}
}
exports.default = KeepingEventsInSyncTest;
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "hasSyncEventsAction", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "syncsWithoutSavingCoreEventsByDefault", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "mergesGlobalEvents", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "canSetSkillEventContractTypesFile", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "canSyncOnlyCoreEvents", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "syncingSchemasDoesNotSyncEventSchemasIfEventsHaveNeverBeenSynced", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "syncingSchemaAfterSyncEventsSyncsSchemasAndDoesNotWriteCoreEvents", null);
__decorate([
(0, test_utils_1.test)()
], KeepingEventsInSyncTest, "syncingSchemasAfterSyncingCoreEventsSavesCoreEvents", null);
//# sourceMappingURL=KeepingEventsInSync.test.js.map