Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.

Commit 67d33ea

Browse files
committed
Migration codes
1 parent b64dc78 commit 67d33ea

File tree

3 files changed

+60
-40
lines changed

3 files changed

+60
-40
lines changed

src/base/MigrationRunner.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ describe('MigrationRunner tests', () => {
9999

100100
test('Test when there is schema validation error', () => {
101101
type TypeV0 = { data: number; text: string; prop: { test: 1 } };
102+
102103
const schemaV0: JSONSchemaType<TypeV0> = {
103104
type: 'object',
104105
properties: {
@@ -112,14 +113,16 @@ describe('MigrationRunner tests', () => {
112113
},
113114
required: ['data', 'text'],
114115
};
116+
115117
const migrations: SchemaMigration[] = [{ version: 0, schema: schemaV0 }];
116118

117119
const dataV0 = { fakeData: 77, text: 123, prop: { testFail: 1 } };
120+
118121
const mr = new MigrationRunner(migrations);
119122

120123
expect(() => mr.runMigration(dataV0)).toThrow(
121124
[
122-
'[MigrationRunner] Schema validation error "version=0". Found next errors:',
125+
'Migration to version=0. Schema validation error. Found next errors:',
123126
'"/": "must have required property \'data\'"',
124127
'"/text": "must be string"',
125128
'"/prop": "must have required property \'test\'"',

src/base/MigrationRunner.ts

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
import Ajv from 'ajv';
1+
import Ajv, { ValidateFunction } from 'ajv';
22
import { SchemaMigration } from '../types/SchemaMigration';
33
import { SchemaType } from '../types/SchemaType';
44
import { last } from '../helpers/ArrayHelper';
5-
6-
enum ErrorCodes {
7-
NoMigrations,
8-
NoZeroMigration,
9-
IncorrectMigrationsOrder,
10-
}
5+
import MigrationErrorCodes from '../types/MigrationErrorCodes';
116

127
export default class MigrationRunner {
138
private schemaMigrations: SchemaMigration[] = [];
149
private ajv: Ajv;
15-
private genErrorMsg = (error: ErrorCodes | undefined, message: string) =>
16-
`[MigrationRunner] ${error ?? -1} ${message}`;
10+
private genErrorMsg = (
11+
error: MigrationErrorCodes | undefined,
12+
message: string
13+
) => `[MigrationRunner] [error=${error ?? -1}] ${message}`;
14+
private genValidationErrors = (
15+
validate: ValidateFunction<unknown>,
16+
toVersion: number
17+
) =>
18+
this.genErrorMsg(
19+
MigrationErrorCodes.ValidationFailed,
20+
`Migration to version=${toVersion}. Schema validation error. Found next errors:\n${validate.errors
21+
?.map(
22+
(e) => `"${e.instancePath ? e.instancePath : '/'}": "${e.message}"`
23+
)
24+
?.join('\n')}`
25+
);
1726

1827
constructor(schemaMigrations: SchemaMigration[]) {
1928
const schemaMigrationsSorted = schemaMigrations.slice();
@@ -22,15 +31,16 @@ export default class MigrationRunner {
2231
if (!schemaMigrationsSorted.length) {
2332
throw new Error(
2433
this.genErrorMsg(
25-
ErrorCodes.NoMigrations,
26-
'schemaMigrations can`t be empty'
34+
MigrationErrorCodes.NoMigrations,
35+
`schemaMigrations can't be empty`
2736
)
2837
);
2938
}
3039

3140
if (!schemaMigrationsSorted.find((i) => i.version === 0)) {
3241
throw new Error(
3342
this.genErrorMsg(
43+
MigrationErrorCodes.NoZeroMigration,
3444
'schemaMigrations should have migration for `version=0`'
3545
)
3646
);
@@ -41,7 +51,10 @@ export default class MigrationRunner {
4151
);
4252
if (!hasAllVersions) {
4353
throw new Error(
44-
this.genErrorMsg('Each version should go one after the other')
54+
this.genErrorMsg(
55+
MigrationErrorCodes.IncorrectMigrationsOrder,
56+
'Each version should go one after the other'
57+
)
4558
);
4659
}
4760

@@ -54,44 +67,45 @@ export default class MigrationRunner {
5467
const lastVersion = last(this.schemaMigrations)?.version;
5568

5669
if (lastVersion === undefined) {
57-
throw new Error('There are no migrations');
70+
throw new Error(
71+
this.genErrorMsg(
72+
MigrationErrorCodes.NoMigrations,
73+
'There are no migrations'
74+
)
75+
);
5876
}
5977

60-
const firstMigration = this.schemaMigrations.find((i) => i.version === 0);
78+
const zeroVersion = 0;
79+
const firstMigration = this.schemaMigrations.find(
80+
(i) => i.version === zeroVersion
81+
);
6182
if (!firstMigration) {
6283
throw new Error();
6384
}
85+
6486
const validate = this.ajv.compile(firstMigration.schema);
6587
const validateResult = validate(newData);
6688
if (!validateResult) {
67-
throw new Error(
68-
this.genErrorMsg(
69-
`Schema validation error "version=0". Found next errors:\n${validate.errors
70-
?.map(
71-
(e) =>
72-
`"${e.instancePath ? e.instancePath : '/'}": "${e.message}"`
73-
)
74-
?.join('\n')}`
75-
)
76-
);
89+
throw new Error(this.genValidationErrors(validate, zeroVersion));
7790
}
7891

79-
let nextVersion =
80-
newData.__version !== undefined ? newData.__version + 1 : 1;
92+
let fromVersion = newData.__version;
93+
let toVersion = fromVersion !== undefined ? fromVersion + 1 : 1;
8194

8295
while (true) {
83-
if (nextVersion > lastVersion) {
96+
if (toVersion > lastVersion) {
8497
return newData;
8598
}
8699

87100
const migration = this.schemaMigrations.find(
88-
(m) => m.version === nextVersion
101+
(m) => m.version === toVersion
89102
);
90103

91104
if (!migration) {
92105
throw new Error(
93106
this.genErrorMsg(
94-
`Migration from ${newData.__version} to ${nextVersion} not found`
107+
MigrationErrorCodes.MigrationNotFound,
108+
`Migration from ${fromVersion} to ${toVersion} not found`
95109
)
96110
);
97111
}
@@ -107,19 +121,13 @@ export default class MigrationRunner {
107121
}
108122

109123
const validate = this.ajv.compile(migration.schema);
110-
const validateObj = validate(nextData);
111-
if (!validateObj) {
112-
throw new Error(
113-
this.genErrorMsg(
114-
`Schema validation error. version=${nextVersion}: ${validate.errors?.join(
115-
', '
116-
)}`
117-
)
118-
);
124+
const validateResult = validate(nextData);
125+
if (!validateResult) {
126+
throw new Error(this.genValidationErrors(validate, toVersion));
119127
}
120128

121129
newData = nextData;
122-
nextVersion = nextData.__version + 1;
130+
toVersion = nextData.__version + 1;
123131
}
124132
}
125133
}

src/types/MigrationErrorCodes.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
enum MigrationErrorCodes {
2+
NoMigrations = 0,
3+
NoZeroMigration = 1,
4+
IncorrectMigrationsOrder = 2,
5+
ValidationFailed = 3,
6+
MigrationNotFound = 4,
7+
}
8+
9+
export default MigrationErrorCodes;

0 commit comments

Comments
 (0)