@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
74 lines • 3.19 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import { SemanticVersion } from '../../../../business/utils/semantic-version.js';
import { SchemaValidationError } from './schema-validation-error.js';
export class SchemaDefinitionBase {
mapper;
constructor(mapper) {
this.mapper = mapper;
}
async transform(data, sourceVersion) {
if (data === undefined || data === null) {
return null;
}
const clone = structuredClone(data);
let dataVersion = clone.schemaVersion;
if (!dataVersion) {
dataVersion = sourceVersion ? sourceVersion.major : 0;
}
const migrated = await this.applyMigrations(clone, new SemanticVersion(dataVersion));
return this.mapper.fromObject(this.classConstructor, migrated);
}
async validateMigrations() {
if (this.migrations.length === 0) {
return;
}
// eslint-disable-next-line unicorn/no-array-sort
const versionJumps = this.migrations.map((value) => value.version.major).sort();
for (let index = 1; index < versionJumps.length; index++) {
if (versionJumps[index] === versionJumps[index - 1]) {
throw new SchemaValidationError(`Duplicate migration version '${versionJumps[index]}'`);
}
}
let currentVersion = this.nextVersionJump(new SemanticVersion(0));
for (const versionJump of versionJumps) {
const v = new SemanticVersion(versionJump);
if (!v.equals(currentVersion)) {
throw new SchemaValidationError(`Invalid migration version sequence detected; expected version '${v.major}' but got '${currentVersion.major}'`);
}
currentVersion = this.nextVersionJump(currentVersion);
}
return;
}
nextVersionJump(currentVersion) {
const targetMigrations = this.findMigrations(currentVersion);
if (!targetMigrations || targetMigrations.length === 0) {
// No migration found for the current version - fail with an error
throw new SchemaValidationError(`No migration found for version '${currentVersion.major}'; there is a gap in the migration sequence`);
}
return targetMigrations[0].version;
}
/*
* DV < version = 1 >
* M1 < range = [0, 6), version = 6 >
* M1.1 < range = [0, 4), version = 5 >
* M2 < range = [6, 7), version = 8 >
*/
async applyMigrations(data, dataVersion) {
let migrations = this.findMigrations(dataVersion);
while (migrations.length > 0) {
const migration = migrations[0];
data = await migration.migrate(data);
dataVersion = migration.version;
migrations = this.findMigrations(dataVersion);
}
return data;
}
findMigrations(dataVersion) {
const eligibleMigrations = this.migrations.filter((value) => value.range.contains(dataVersion));
if (eligibleMigrations.length > 0) {
eligibleMigrations.sort((l, r) => l.version.compare(r.version));
}
return eligibleMigrations;
}
}
//# sourceMappingURL=schema-definition-base.js.map