@sprucelabs/spruce-cli
Version:
Command line interface for building Spruce skills.
223 lines • 9.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.coreSchemas = void 0;
const path_1 = __importDefault(require("path"));
const globby_1 = __importDefault(require("@sprucelabs/globby"));
const schema_1 = require("@sprucelabs/schema");
const spruce_core_schemas_1 = require("@sprucelabs/spruce-core-schemas");
const spruce_event_utils_1 = require("@sprucelabs/spruce-event-utils");
const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
const spruce_skill_utils_2 = require("@sprucelabs/spruce-skill-utils");
const spruce_skill_utils_3 = require("@sprucelabs/spruce-skill-utils");
const lodash_1 = require("lodash");
const SpruceError_1 = __importDefault(require("../../../errors/SpruceError"));
const AbstractStore_1 = __importDefault(require("../../../stores/AbstractStore"));
exports.coreSchemas = {
personSchema: spruce_core_schemas_1.personSchema,
skillSchema: spruce_core_schemas_1.skillSchema,
skillCreatorSchema: spruce_core_schemas_1.skillCreatorSchema,
locationSchema: spruce_core_schemas_1.locationSchema,
organizationSchema: spruce_core_schemas_1.organizationSchema,
personOrganizationSchema: spruce_core_schemas_1.personOrganizationSchema,
personLocationSchema: spruce_core_schemas_1.personLocationSchema,
roleSchema: spruce_core_schemas_1.roleSchema,
messageSchema: spruce_core_schemas_1.messageSchema,
messageSourceSchema: spruce_core_schemas_1.messageSourceSchema,
messageTargetSchema: spruce_core_schemas_1.messageTargetSchema,
sendMessageSchema: spruce_core_schemas_1.sendMessageSchema,
choiceSchema: spruce_core_schemas_1.choiceSchema,
linkSchema: spruce_core_schemas_1.linkSchema,
};
const DEFAULT_LOCAL_SCHEMA_DIR = 'src/schemas';
class SchemaStore extends AbstractStore_1.default {
name = 'schema';
async fetchSchemas(options) {
const { localSchemaLookupDir: localSchemaDir = DEFAULT_LOCAL_SCHEMA_DIR, shouldFetchLocalSchemas = true, shouldFetchRemoteSchemas = true, shouldEnableVersioning = true, localNamespace, shouldFetchCoreSchemas = true, didUpdateHandler, moduleToImportFromWhenRemote, } = options || {};
const results = {
errors: [],
schemasByNamespace: {},
};
if (shouldFetchCoreSchemas) {
results.schemasByNamespace[spruce_skill_utils_3.CORE_NAMESPACE] = Object.values(exports.coreSchemas).map((schema) => ({
...schema,
namespace: spruce_skill_utils_3.CORE_NAMESPACE,
}));
}
if (shouldFetchLocalSchemas) {
const locals = await this.loadLocalSchemas(localSchemaDir, localNamespace, shouldEnableVersioning, didUpdateHandler);
if (moduleToImportFromWhenRemote) {
locals.schemas.forEach((local) => {
local.moduleToImportFromWhenRemote =
moduleToImportFromWhenRemote;
});
}
results.schemasByNamespace[localNamespace] = locals.schemas;
results.errors.push(...locals.errors);
}
if (shouldFetchRemoteSchemas) {
await this.emitDidFetchSchemasAndMixinResults(localNamespace, results);
}
return results;
}
async emitDidFetchSchemasAndMixinResults(localNamespace, results) {
const schemas = [];
for (const namespace in results.schemasByNamespace) {
schemas.push(...results.schemasByNamespace[namespace]);
}
const remoteResults = await this.emitter.emit('schema.did-fetch-schemas', {
schemas,
});
const { payloads, errors } = spruce_event_utils_1.eventResponseUtil.getAllResponsePayloadsAndErrors(remoteResults, SpruceError_1.default);
if (errors && errors.length > 0) {
results.errors.push(...errors);
}
else {
payloads.forEach((payload) => {
payload?.schemas?.forEach((schema) => {
this.mixinSchemaOrThrowIfExists(schema, localNamespace, results);
});
});
}
}
mixinSchemaOrThrowIfExists(schema, localNamespace, results) {
const namespace = schema.namespace ?? localNamespace;
if (!results.schemasByNamespace[namespace]) {
results.schemasByNamespace[namespace] = [];
}
const idWithVersion = (0, schema_1.normalizeSchemaToIdWithVersion)(schema);
const match = results.schemasByNamespace[namespace].find((s) => (0, lodash_1.isEqual)((0, schema_1.normalizeSchemaToIdWithVersion)(s), idWithVersion));
if (!match) {
results.schemasByNamespace[namespace].push(schema);
}
}
async hasLocalSchemas() {
const matches = await this.globbyLocalBuilders(DEFAULT_LOCAL_SCHEMA_DIR);
return matches.length > 0;
}
async loadLocalSchemas(localLookupDir, localNamespace, shouldEnableVersioning, didUpdateHandler) {
const localMatches = await this.globbyLocalBuilders(localLookupDir);
const errors = [];
const schemas = [];
didUpdateHandler?.(`Starting import of ${localMatches.length} schema builders...`);
try {
const importer = this.Service('import');
const imported = await importer.bulkImport(localMatches);
for (let c = 0; c < localMatches.length; c++) {
try {
const local = localMatches[c];
let schema = imported[c];
let version = this.resolveLocalVersion(shouldEnableVersioning, local, errors);
if (version || shouldEnableVersioning === false) {
schema = this.prepareLocalSchema(schema, localNamespace, version, didUpdateHandler);
schemas.push(schema);
}
}
catch (err) {
errors.push(new SpruceError_1.default({
code: 'SCHEMA_FAILED_TO_IMPORT',
file: err?.options?.file ?? '**UNKNOWN**',
originalError: err?.originalError ?? err,
}));
}
}
}
catch (err) {
throw new SpruceError_1.default({
code: 'SCHEMA_FAILED_TO_IMPORT',
file: err?.options?.file ?? '**UNKNOWN**',
originalError: err?.originalError ?? err,
});
}
return {
schemas,
errors,
};
}
async globbyLocalBuilders(localLookupDir) {
return await (0, globby_1.default)(spruce_skill_utils_2.diskUtil.resolvePath(this.cwd, localLookupDir, '**/*.builder.[t|j]s'));
}
resolveLocalVersion(shouldEnableVersioning, local, errors) {
let version;
try {
version =
shouldEnableVersioning === false
? undefined
: spruce_skill_utils_1.versionUtil.extractVersion(this.cwd, local).constValue;
}
catch (err) {
errors.push(new SpruceError_1.default({
// @ts-ignore
code: 'VERSION_MISSING',
friendlyMessage: `It looks like your schema's are not versioned. Make sure schemas are in a directory like src/schemas/${spruce_skill_utils_1.versionUtil.generateVersion().dirValue}/*.ts`,
}));
}
return version;
}
prepareLocalSchema(schema, localNamespace, version, didUpdateHandler) {
let errors = [];
if (schema.version) {
errors.push('version_should_not_be_set');
}
if (schema.namespace) {
errors.push('namespace_should_not_be_set');
}
schema.namespace = localNamespace;
if (errors.length > 0) {
throw new schema_1.SchemaError({
code: 'INVALID_SCHEMA',
schemaId: schema.id,
errors,
friendlyMessage: 'You should not set a namespace nor version in your schema builder.',
});
}
schema.version = version;
didUpdateHandler?.(`Imported ${schema.id} builder.`);
return schema;
}
async fetchFields(options) {
const { localAddonsDir } = options || {};
const coreAddons = schema_1.fieldRegistrations.map((registration) => {
return {
registration,
isLocal: false,
};
});
const localErrors = [];
const localAddons = !localAddonsDir
? []
: await Promise.all((await (0, globby_1.default)([
path_1.default.join(localAddonsDir, '/*Field.addon.[t|j]s'),
])).map(async (file) => {
try {
const importService = this.Service('import');
const registration = await importService.importDefault(file);
return {
path: file,
registration,
isLocal: true,
};
}
catch (err) {
localErrors.push(new SpruceError_1.default({
code: 'FAILED_TO_IMPORT',
file,
originalError: err,
}));
return false;
}
}));
const allFields = (0, lodash_1.uniqBy)([
...coreAddons,
...localAddons.filter((addon) => !!addon),
], 'registration.type');
return {
fields: allFields,
errors: localErrors,
};
}
}
exports.default = SchemaStore;
//# sourceMappingURL=SchemaStore.js.map