@vulcan-sql/extension-store-canner
Version:
Canner persistence store for Vulcan SQL
145 lines • 8.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CannerPersistenceStore = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@vulcan-sql/core");
const inversify_1 = require("inversify");
const storageService_1 = require("../storageService");
const config_1 = require("../config");
const utils_1 = require("./utils");
/**
* Used the string to identify the extension Id not by the enum "ArtifactBuilderProviderType".
* Because if we create another enum to extend the 'ArtifactBuilderProviderType', it seems unnecessary to give the new enum only has 'Canner' as its type."
* */
let CannerPersistenceStore = class CannerPersistenceStore extends core_1.PersistentStore {
constructor(options, config, moduleName) {
super(config, moduleName);
this.logger = this.getLogger();
this.envConfig = (0, config_1.getEnvConfig)();
this.filePath = options.filePath;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
save(data) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
throw new Error('The extension not provide the save method, it only use to load the data from the storage');
});
}
load() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const storageService = yield (0, storageService_1.createStorageService)(this.envConfig.storage);
this.logger.debug('Canner storage service created');
const filesInfo = yield storageService.listObjects({
path: this.filePath,
recursive: true,
});
// get the indicator files path of each workspaces
const files = yield (0, utils_1.getIndicatorFilesOfWorkspaces)(filesInfo);
this.logger.debug(`Succeed to get the indicator files of each workspaces: ${JSON.stringify(files)}`);
// get the latest artifacts of each workspaces
const artifacts = yield this.getLatestArtifactsOfWorkspaces(storageService, files);
// merge the artifacts of each workspaces to one artifact
const artifact = yield this.mergeArtifactsOfWorkspaces(artifacts);
this.logger.debug(`Succeed to merge the artifacts: ${artifact}`);
return Buffer.from(JSON.stringify(artifact), 'utf-8');
});
}
getLatestArtifactsOfWorkspaces(storageService, indicators) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield Promise.all(
// download latest artifact buffer content of each workspace by viewing the indicator.json of the each workspace
indicators.map(({ workspaceId, name: indicatorPath }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const buffer = yield storageService.downObjectAsBuffer({
name: indicatorPath,
});
const indicator = JSON.parse(buffer.toString('utf-8'));
const artifact = yield this.getWorkspaceArtifact(storageService, indicatorPath, indicator);
this.logger.debug('Succeed to download latest artifacts of workspaces');
return {
workspaceSqlName: indicator[workspaceId],
artifact,
};
})));
});
}
getWorkspaceArtifact(storageService, indicatorPath, indicator) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const latestArtifactFolder = indicator[indicator.master];
const vulcanFolderPath = indicatorPath.replace('/indicator.json', '');
const path = `${vulcanFolderPath}/${latestArtifactFolder}/result.json`;
this.logger.debug(`Download the artifact from path: ${path}`);
// download from artifact path name
const buffer = yield storageService.downObjectAsBuffer({
name: path,
});
// parse the artifact buffer content to object
return JSON.parse(buffer.toString('utf-8'));
});
}
mergeArtifactsOfWorkspaces(artifacts) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const merged = artifacts.reduce((merged, { workspaceSqlName, artifact }) => {
// Template
Object.entries(artifact.templates).forEach(([sourceName, value]) => {
// add the workspace sql name prefix to original source name
const workspaceSourceName = `${workspaceSqlName}/${sourceName}`;
merged.templates[workspaceSourceName] = value;
});
// API Schemas
const profile = `canner-${workspaceSqlName}`;
artifact.schemas.forEach((schema) => {
var _a;
// concat the workspace sql name prefix to urlPath, urlPath has the "/" prefix, so concat directly
schema.urlPath = `${workspaceSqlName}${schema.urlPath}`;
// concat the workspace sql name prefix to template source, so it could find the "sourceName" in templates
schema.templateSource = `${workspaceSqlName}/${schema.templateSource}`;
// replace the profile to the canner enterprise integration used profile name, it will match to the profiles from canner profile reader.
schema.profiles = [profile];
schema.cache =
((_a = schema.cache) === null || _a === void 0 ? void 0 : _a.map((cacheData) => (Object.assign(Object.assign({}, cacheData), { profile })))) || [];
merged.schemas.push(schema);
});
// Specs, only support the oas3 specification for canner enterprise integration used
if (!artifact.specs['oas3'])
throw new Error(`The workspace sql name "${workspaceSqlName}" artifact not use "oas3" specification, canner persistence store only support the "oas3" specification`);
if (artifact.specs['oas3']['paths'])
Object.entries(artifact.specs['oas3']['paths']).forEach(([apiEndpoint, endpointInfo]) => {
// concat the workspace sql name prefix to original api endpoint, the "apiEndpoint" has the "/" prefix, so concat directly
const endpoint = `${workspaceSqlName}${apiEndpoint}`;
merged.specs['oas3']['paths'][endpoint] =
endpointInfo;
// Add workspace sql name prefix to original operationId & summary
const { summary, operationId } = merged.specs['oas3']['paths'][endpoint]['get'];
merged.specs['oas3']['paths'][endpoint]['get'] = Object.assign(Object.assign({}, merged.specs['oas3']['paths'][endpoint]['get']), {
// e.g: get/xxx => get/{workspaceSqlName}/xxx
operationId: `get/${workspaceSqlName}/${operationId === null || operationId === void 0 ? void 0 : operationId.slice(4)}`,
// e.g: /xxx => /{workspaceSqlName}/xxx
summary: `/${workspaceSqlName}${summary}` });
});
return merged;
}, {
templates: {},
schemas: [],
specs: { oas3: { paths: {} } },
});
// assign the openapi version and info to the merged artifact
merged.specs['oas3'] = Object.assign(Object.assign({}, merged.specs['oas3']), {
// Follow the OpenAPI specification version 3.0.3
// see https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md
openapi: '3.0.3', info: {
title: 'Data API',
version: 'latest',
description: 'Data API for Canner Enterprise',
} });
return merged;
});
}
};
CannerPersistenceStore = tslib_1.__decorate([
(0, core_1.VulcanExtensionId)('Canner'),
tslib_1.__param(0, (0, inversify_1.inject)(core_1.TYPES.ArtifactBuilderOptions)),
tslib_1.__param(1, (0, inversify_1.inject)(core_1.TYPES.ExtensionConfig)),
tslib_1.__param(2, (0, inversify_1.inject)(core_1.TYPES.ExtensionName)),
tslib_1.__metadata("design:paramtypes", [core_1.ArtifactBuilderOptions, Object, String])
], CannerPersistenceStore);
exports.CannerPersistenceStore = CannerPersistenceStore;
//# sourceMappingURL=persistenceStore.js.map