@contember/schema-migrations 1.2.0-alpha.18 → 1.2.0-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/src/Migration.d.ts +2 -0
  2. package/dist/src/Migration.d.ts.map +1 -1
  3. package/dist/src/Migration.js +2 -2
  4. package/dist/src/Migration.js.map +1 -1
  5. package/dist/src/MigrationCreator.d.ts +3 -1
  6. package/dist/src/MigrationCreator.d.ts.map +1 -1
  7. package/dist/src/MigrationCreator.js +2 -2
  8. package/dist/src/MigrationCreator.js.map +1 -1
  9. package/dist/src/MigrationFilesManager.d.ts.map +1 -1
  10. package/dist/src/MigrationFilesManager.js +10 -19
  11. package/dist/src/MigrationFilesManager.js.map +1 -1
  12. package/dist/src/MigrationsResolver.d.ts.map +1 -1
  13. package/dist/src/MigrationsResolver.js +2 -0
  14. package/dist/src/MigrationsResolver.js.map +1 -1
  15. package/dist/src/SchemaDiffer.d.ts +6 -1
  16. package/dist/src/SchemaDiffer.d.ts.map +1 -1
  17. package/dist/src/SchemaDiffer.js +10 -6
  18. package/dist/src/SchemaDiffer.js.map +1 -1
  19. package/dist/src/modifications/ModificationHandlerFactory.d.ts.map +1 -1
  20. package/dist/src/modifications/ModificationHandlerFactory.js +2 -0
  21. package/dist/src/modifications/ModificationHandlerFactory.js.map +1 -1
  22. package/dist/src/modifications/settings/UpdateSettingsModification.d.ts +28 -0
  23. package/dist/src/modifications/settings/UpdateSettingsModification.d.ts.map +1 -0
  24. package/dist/src/modifications/settings/UpdateSettingsModification.js +64 -0
  25. package/dist/src/modifications/settings/UpdateSettingsModification.js.map +1 -0
  26. package/dist/src/modifications/settings/index.d.ts +2 -0
  27. package/dist/src/modifications/settings/index.d.ts.map +1 -0
  28. package/dist/src/modifications/settings/index.js +18 -0
  29. package/dist/src/modifications/settings/index.js.map +1 -0
  30. package/dist/src/modifications/utils/schemaUpdateUtils.d.ts.map +1 -1
  31. package/dist/src/modifications/utils/schemaUpdateUtils.js +8 -1
  32. package/dist/src/modifications/utils/schemaUpdateUtils.js.map +1 -1
  33. package/dist/src/tsconfig.tsbuildinfo +1 -1
  34. package/dist/tests/cases/integration/createView.test.js +80 -0
  35. package/dist/tests/cases/integration/createView.test.js.map +1 -1
  36. package/dist/tests/cases/integration/removeField.test.js +72 -0
  37. package/dist/tests/cases/integration/removeField.test.js.map +1 -1
  38. package/dist/tests/scripts/checkCreateConsistentMigrations.js +5 -4
  39. package/dist/tests/scripts/checkCreateConsistentMigrations.js.map +1 -1
  40. package/dist/tests/src/tests.d.ts.map +1 -1
  41. package/dist/tests/src/tests.js +15 -5
  42. package/dist/tests/src/tests.js.map +1 -1
  43. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +6 -6
  45. package/src/Migration.ts +3 -1
  46. package/src/MigrationCreator.ts +2 -1
  47. package/src/MigrationFilesManager.ts +10 -20
  48. package/src/MigrationsResolver.ts +1 -0
  49. package/src/SchemaDiffer.ts +15 -6
  50. package/src/modifications/ModificationHandlerFactory.ts +2 -0
  51. package/src/modifications/settings/UpdateSettingsModification.ts +87 -0
  52. package/src/modifications/settings/index.ts +1 -0
  53. package/src/modifications/utils/schemaUpdateUtils.ts +8 -1
  54. package/src/tsconfig.json +2 -2
  55. package/tests/cases/integration/createView.test.ts +70 -0
  56. package/tests/cases/integration/removeField.test.ts +58 -0
  57. package/tests/scripts/checkCreateConsistentMigrations.ts +3 -2
  58. package/tests/src/tests.ts +16 -7
@@ -1,38 +1,28 @@
1
1
  import { MigrationVersionHelper } from './MigrationVersionHelper'
2
- import * as fs from 'fs'
3
- import { promisify } from 'util'
4
- import * as path from 'path'
5
-
6
- const readFile = promisify(fs.readFile)
7
- const fsWrite = promisify(fs.writeFile)
8
- const fsRemove = promisify(fs.unlink)
9
- const fsRealpath = promisify(fs.realpath)
10
- const mkdir = promisify(fs.mkdir)
11
- const lstatFile = promisify(fs.lstat)
12
- const readDir = promisify(fs.readdir)
13
- const mvFile = promisify(fs.rename)
2
+ import * as fs from 'node:fs/promises'
3
+ import * as path from 'node:path'
14
4
 
15
5
  class MigrationFilesManager {
16
6
  constructor(public readonly directory: string) {}
17
7
 
18
8
  public async createFile(content: string, name: string): Promise<string> {
19
9
  const path = this.formatPath(name)
20
- await fsWrite(path, content, { encoding: 'utf8' })
21
- return await fsRealpath(path)
10
+ await fs.writeFile(path, content, { encoding: 'utf8' })
11
+ return await fs.realpath(path)
22
12
  }
23
13
 
24
14
  public async removeFile(name: string) {
25
15
  const path = this.formatPath(name)
26
- await fsRemove(path)
16
+ await fs.unlink(path)
27
17
  }
28
18
 
29
19
  public async moveFile(oldName: string, newName: string) {
30
- await mvFile(this.formatPath(oldName), this.formatPath(newName))
20
+ await fs.rename(this.formatPath(oldName), this.formatPath(newName))
31
21
  }
32
22
 
33
23
  public async createDirIfNotExist(): Promise<void> {
34
24
  try {
35
- await mkdir(this.directory)
25
+ await fs.mkdir(this.directory)
36
26
  } catch (e) {
37
27
  if (!(e instanceof Error) || !('code' in e) || (e as any).code !== 'EEXIST') {
38
28
  throw e
@@ -47,7 +37,7 @@ class MigrationFilesManager {
47
37
  files
48
38
  .filter(file => file.endsWith(`.json`))
49
39
  .filter(async file => {
50
- return (await lstatFile(`${this.directory}/${file}`)).isFile()
40
+ return (await fs.lstat(`${this.directory}/${file}`)).isFile()
51
41
  }),
52
42
  )
53
43
  return filteredFiles.sort()
@@ -55,7 +45,7 @@ class MigrationFilesManager {
55
45
 
56
46
  private async tryReadDir(): Promise<string[]> {
57
47
  try {
58
- return await readDir(this.directory)
48
+ return await fs.readdir(this.directory)
59
49
  } catch (e) {
60
50
  if (e instanceof Error && 'code' in e && (e as any).code === 'ENOENT') {
61
51
  return []
@@ -72,7 +62,7 @@ class MigrationFilesManager {
72
62
  const filesWithContent = files.map(async filename => ({
73
63
  filename: filename,
74
64
  path: `${this.directory}/${filename}`,
75
- content: await readFile(`${this.directory}/${filename}`, { encoding: 'utf8' }),
65
+ content: await fs.readFile(`${this.directory}/${filename}`, { encoding: 'utf8' }),
76
66
  }))
77
67
 
78
68
  return await Promise.all(filesWithContent)
@@ -18,6 +18,7 @@ export class MigrationsResolver {
18
18
  name: MigrationVersionHelper.extractName(filename),
19
19
  formatVersion: parsed.formatVersion || VERSION_INITIAL,
20
20
  modifications: parsed.modifications,
21
+ skippedErrors: parsed.skippedErrors ?? [],
21
22
  }
22
23
  })
23
24
  }
@@ -44,14 +44,22 @@ import {
44
44
  import { ChangeViewNonViewDiffer, RemoveChangedFieldDiffer, RemoveChangedViewDiffer } from './modifications/differs'
45
45
  import { CreateIndexDiffer, RemoveIndexDiffer } from './modifications/indexes'
46
46
  import { SchemaWithMeta } from './modifications/utils/schemaMeta'
47
+ import { UpdateSettingsDiffer } from './modifications/settings'
48
+
49
+ type DiffOptions = { skipRecreateValidation?: boolean; skipInitialSchemaValidation?: boolean }
47
50
 
48
51
  export class SchemaDiffer {
49
52
  constructor(private readonly schemaMigrator: SchemaMigrator) {}
50
53
 
51
- diffSchemas(originalSchema: Schema, updatedSchema: Schema, checkRecreate: boolean = true): Migration.Modification[] {
52
- const originalErrors = SchemaValidator.validate(originalSchema)
53
- if (originalErrors.length > 0) {
54
- throw new InvalidSchemaException('original schema is not valid', originalErrors)
54
+ diffSchemas(originalSchema: Schema, updatedSchema: Schema, {
55
+ skipInitialSchemaValidation = false,
56
+ skipRecreateValidation = false,
57
+ }: DiffOptions = {}): Migration.Modification[] {
58
+ if (!skipInitialSchemaValidation) {
59
+ const originalErrors = SchemaValidator.validate(originalSchema)
60
+ if (originalErrors.length > 0) {
61
+ throw new InvalidSchemaException('original schema is not valid', originalErrors)
62
+ }
55
63
  }
56
64
  const updatedErrors = SchemaValidator.validate(updatedSchema)
57
65
  if (updatedErrors.length > 0) {
@@ -59,6 +67,7 @@ export class SchemaDiffer {
59
67
  }
60
68
 
61
69
  const differs: Differ[] = [
70
+ new UpdateSettingsDiffer(),
62
71
  new ConvertOneToManyRelationDiffer(),
63
72
  new ConvertOneHasManyToManyHasManyRelationDiffer(),
64
73
  new RemoveUniqueConstraintDiffer(),
@@ -84,8 +93,8 @@ export class SchemaDiffer {
84
93
  new RemoveChangedFieldDiffer(it => isRelation(it) && isInverseRelation(it)),
85
94
  new CreateEntityDiffer(),
86
95
  new CreateColumnDiffer(),
87
- new CreateViewDiffer(),
88
96
  new CreateRelationDiffer(),
97
+ new CreateViewDiffer(),
89
98
  new CreateRelationInverseSideDiffer(),
90
99
  new CreateUniqueConstraintDiffer(),
91
100
  new CreateIndexDiffer(),
@@ -103,7 +112,7 @@ export class SchemaDiffer {
103
112
  }
104
113
 
105
114
 
106
- if (checkRecreate) {
115
+ if (!skipRecreateValidation) {
107
116
  const { meta, ...appliedDiffsSchema2 } = appliedDiffsSchema as SchemaWithMeta
108
117
  const errors = deepCompare(updatedSchema, appliedDiffsSchema2, [])
109
118
  if (errors.length === 0) {
@@ -30,6 +30,7 @@ import {
30
30
  import { patchValidationSchemaModification, updateValidationSchemaModification } from './validation'
31
31
  import { createIndexModification, removeIndexModification } from './indexes'
32
32
  import { SchemaWithMeta } from './utils/schemaMeta'
33
+ import { updateSettingsModification } from './settings'
33
34
 
34
35
 
35
36
  class ModificationHandlerFactory {
@@ -47,6 +48,7 @@ namespace ModificationHandlerFactory {
47
48
  type HandlerMap<D> = { [modificationName: string]: ModificationType<string, D> }
48
49
 
49
50
  const handlers = [
51
+ updateSettingsModification,
50
52
  updateAclSchemaModification,
51
53
  patchAclSchemaModification,
52
54
  createColumnModification,
@@ -0,0 +1,87 @@
1
+ import { MigrationBuilder } from '@contember/database-migrations'
2
+ import { Schema, Settings } from '@contember/schema'
3
+ import { SchemaUpdater } from '../utils/schemaUpdateUtils'
4
+ import { createModificationType, Differ, ModificationHandler } from '../ModificationHandler'
5
+ import deepEqual from 'fast-deep-equal'
6
+
7
+ export class UpdateSettingsModificationHandler implements ModificationHandler<UpdateSettingsModificationData> {
8
+ constructor(
9
+ private readonly data: UpdateSettingsModificationData,
10
+ ) {
11
+ }
12
+
13
+ public createSql(builder: MigrationBuilder): void {
14
+ }
15
+
16
+ public getSchemaUpdater(): SchemaUpdater {
17
+ return ({ schema }) => {
18
+ const { [this.data.key]: _, ...settings } = schema.settings
19
+ if (this.data.op === 'unset') {
20
+ return {
21
+ ...schema,
22
+ settings,
23
+ }
24
+ }
25
+ return {
26
+ ...schema,
27
+ settings: { ...settings, [this.data.key]: this.data.value },
28
+ }
29
+ }
30
+ }
31
+
32
+
33
+ describe() {
34
+ return { message: `Change settings of ${this.data.key}` }
35
+ }
36
+
37
+ }
38
+
39
+ export const updateSettingsModification = createModificationType({
40
+ id: 'updateSettings',
41
+ handler: UpdateSettingsModificationHandler,
42
+ })
43
+
44
+ export class UpdateSettingsDiffer implements Differ {
45
+ createDiff(originalSchema: Schema, updatedSchema: Schema) {
46
+ const allKeys = Array.from(new Set([
47
+ ...Object.keys(originalSchema.settings),
48
+ ...Object.keys(updatedSchema.settings),
49
+ ] as (keyof Settings.Schema)[]))
50
+
51
+ return allKeys
52
+ .filter(key => !deepEqual(originalSchema.settings[key], updatedSchema.settings[key]))
53
+ .map(key => {
54
+ const value = updatedSchema.settings[key]
55
+ if (value === undefined) {
56
+ return updateSettingsModification.createModification({
57
+ op: 'unset',
58
+ key,
59
+ })
60
+ }
61
+ return updateSettingsModification.createModification({
62
+ op: 'set',
63
+ key,
64
+ value,
65
+ })
66
+ })
67
+ }
68
+ }
69
+
70
+
71
+
72
+ export interface SetSettingsModificationData<K extends keyof Settings.Schema = keyof Settings.Schema> {
73
+ op: 'set'
74
+ key: K
75
+ value: Settings.Schema[K]
76
+ }
77
+
78
+
79
+ export interface UnsetSettingsModificationData<K extends keyof Settings.Schema = keyof Settings.Schema> {
80
+ op: 'unset'
81
+ key: K
82
+ }
83
+
84
+
85
+ export type UpdateSettingsModificationData =
86
+ | SetSettingsModificationData
87
+ | UnsetSettingsModificationData
@@ -0,0 +1 @@
1
+ export * from './UpdateSettingsModification'
@@ -271,7 +271,14 @@ export const removeField = (entityName: string, fieldName: string, version: numb
271
271
  updateModel(
272
272
  updateEntity(entity.name, ({ entity }) => {
273
273
  const { [field.name]: removed, ...fields } = entity.fields
274
- return { ...entity, fields }
274
+ const indexes = Object.entries(entity.indexes).filter(([, index]) => !index.fields.includes(field.name))
275
+ const unique = Object.entries(entity.unique).filter(([, index]) => !index.fields.includes(field.name))
276
+ return {
277
+ ...entity,
278
+ fields,
279
+ indexes: Object.fromEntries(indexes),
280
+ unique: Object.fromEntries(unique),
281
+ }
275
282
  }),
276
283
  isRelation(field) && isInverseRelation(field)
277
284
  ? updateEntity(
package/src/tsconfig.json CHANGED
@@ -7,10 +7,10 @@
7
7
  },
8
8
  "references": [
9
9
  {
10
- "path": "../../database-migrations/src"
10
+ "path": "../../database/src"
11
11
  },
12
12
  {
13
- "path": "../../engine-common/src"
13
+ "path": "../../database-migrations/src"
14
14
  },
15
15
  {
16
16
  "path": "../../schema/src"
@@ -86,3 +86,73 @@ testMigrations('create view', {
86
86
  sql: SQL`CREATE VIEW "author_stats" AS SELECT 1;`,
87
87
  })
88
88
 
89
+
90
+ namespace ViewAddRelationOriginalSchema {
91
+ export class Article {
92
+ title = def.stringColumn()
93
+ }
94
+
95
+
96
+ export class Category {
97
+ name = def.stringColumn()
98
+ }
99
+ }
100
+
101
+ namespace ViewAddRelationUpdateSchema {
102
+ export class Article {
103
+ title = def.stringColumn()
104
+ category = def.manyHasOne(Category)
105
+ stats = def.oneHasOneInverse(ArticleStats, 'article')
106
+ }
107
+
108
+ export class Category {
109
+ name = def.stringColumn()
110
+ }
111
+
112
+ @def.View('SELECT 1')
113
+ export class ArticleStats {
114
+ article = def.oneHasOne(Article, 'stats')
115
+ visitCount = def.intColumn()
116
+ }
117
+ }
118
+
119
+
120
+ testMigrations('create a relation and a view', {
121
+ originalSchema: def.createModel(ViewAddRelationOriginalSchema), updatedSchema: def.createModel(ViewAddRelationUpdateSchema), diff: [
122
+ {
123
+ modification: 'createRelation',
124
+ entityName: 'Article',
125
+ owningSide: { name: 'category', nullable: true, type: 'ManyHasOne', target: 'Category', joiningColumn: { columnName: 'category_id', onDelete: 'restrict' } },
126
+ },
127
+ {
128
+ modification: 'createView',
129
+ entity: { name: 'ArticleStats',
130
+ primary: 'id',
131
+ primaryColumn: 'id',
132
+ unique: {},
133
+ indexes: {},
134
+ fields: { id: { name: 'id', columnName: 'id', nullable: false, type: 'Uuid', columnType: 'uuid' },
135
+ article: { name: 'article', inversedBy: 'stats', nullable: true, type: 'OneHasOne', target: 'Article', joiningColumn: { columnName: 'article_id', onDelete: 'restrict' } },
136
+ visitCount: { name: 'visitCount', columnName: 'visit_count', nullable: true, type: 'Integer', columnType: 'integer' } },
137
+ tableName: 'article_stats',
138
+ eventLog: { enabled: true },
139
+ view: { sql: 'SELECT 1' } },
140
+ },
141
+ {
142
+ modification: 'createRelationInverseSide',
143
+ entityName: 'Article',
144
+ relation: {
145
+ name: 'stats',
146
+ ownedBy: 'article',
147
+ target: 'ArticleStats',
148
+ type: 'OneHasOne',
149
+ nullable: true,
150
+ },
151
+ },
152
+ ],
153
+ sql: SQL`ALTER TABLE "article" ADD "category_id" uuid;
154
+ ALTER TABLE "article" ADD CONSTRAINT "fk_article_category_id_703b8b" FOREIGN KEY ("category_id") REFERENCES "category"("id") ON DELETE NO ACTION DEFERRABLE INITIALLY IMMEDIATE;
155
+ CREATE INDEX "article_category_id_index" ON "article" ("category_id");
156
+ CREATE VIEW "article_stats" AS SELECT 1;`,
157
+ })
158
+
@@ -2,6 +2,8 @@ import { testMigrations } from '../../src/tests'
2
2
  import { SchemaBuilder } from '@contember/schema-definition'
3
3
  import { Model } from '@contember/schema'
4
4
  import { SQL } from '../../src/tags'
5
+ import { SchemaDefinition as def } from '@contember/schema-definition'
6
+
5
7
 
6
8
  testMigrations('remove relation (many has one)', {
7
9
  originalSchema: new SchemaBuilder()
@@ -128,3 +130,59 @@ testMigrations('remove relation inverse side', {
128
130
  ],
129
131
  sql: SQL``,
130
132
  })
133
+
134
+
135
+ namespace DropIndexOrigSchema {
136
+
137
+ @def.Unique('title', 'author')
138
+ @def.Index('title', 'author')
139
+ export class Article {
140
+ title = def.stringColumn()
141
+ author = def.manyHasOne(Author)
142
+ }
143
+
144
+ export class Author {
145
+ name = def.stringColumn()
146
+ }
147
+ }
148
+
149
+ namespace DropIndexUpSchema {
150
+ @def.Unique('title', 'author')
151
+ @def.Index('title', 'author')
152
+ export class Article {
153
+ title = def.stringColumn()
154
+ author = def.stringColumn()
155
+ }
156
+
157
+ export class Author {
158
+ name = def.stringColumn()
159
+ }
160
+ }
161
+
162
+
163
+ testMigrations('test drop index / unique when removing a field', {
164
+ originalSchema: def.createModel(DropIndexOrigSchema),
165
+ updatedSchema: def.createModel(DropIndexUpSchema),
166
+ diff: [{
167
+ modification: 'removeField',
168
+ entityName: 'Article',
169
+ fieldName: 'author',
170
+ }, {
171
+ modification: 'createColumn',
172
+ entityName: 'Article',
173
+ field: { name: 'author', columnName: 'author', nullable: true, type: 'String', columnType: 'text' },
174
+ }, {
175
+ modification: 'createUniqueConstraint',
176
+ entityName: 'Article',
177
+ unique: { name: 'unique_Article_title_author_7157ea', fields: ['title', 'author'] },
178
+ }, {
179
+ modification: 'createIndex',
180
+ entityName: 'Article',
181
+ index: { name: 'idx_Article_title_author_7157ea', fields: ['title', 'author'] },
182
+ }],
183
+ sql: SQL`ALTER TABLE "article" DROP "author_id";
184
+ ALTER TABLE "article" ADD "author" text;
185
+ ALTER TABLE "article" ADD CONSTRAINT "unique_Article_title_author_7157ea" UNIQUE ("title", "author");
186
+ CREATE INDEX "idx_Article_title_author_7157ea" ON "article" ("title", "author");`,
187
+ })
188
+
@@ -1,4 +1,4 @@
1
- import { relative } from 'path'
1
+ import { relative } from 'node:path'
2
2
  import {
3
3
  MigrationFilesManager,
4
4
  MigrationsResolver,
@@ -18,7 +18,8 @@ import { emptySchema, schemaType } from '@contember/schema-utils'
18
18
  for (const migration of await migrationsResolver.getMigrations()) {
19
19
  const nextSchema = migrator.applyModifications(schema, migration.modifications, migration.formatVersion)
20
20
  schemaType(nextSchema)
21
- differ.diffSchemas(schema, nextSchema)
21
+ const { meta, ...nextSchemaWithoutMeta } = nextSchema
22
+ differ.diffSchemas(schema, nextSchemaWithoutMeta)
22
23
 
23
24
  schema = nextSchema
24
25
  }
@@ -3,6 +3,7 @@ import { Acl, Model } from '@contember/schema'
3
3
  import { createMigrationBuilder } from '@contember/database-migrations'
4
4
  import { assert, describe, it } from 'vitest'
5
5
  import { SchemaWithMeta } from '../../src/modifications/utils/schemaMeta'
6
+ import { emptySchema } from '@contember/schema-utils'
6
7
 
7
8
  const modificationFactory = new ModificationHandlerFactory(ModificationHandlerFactory.defaultFactoryMap)
8
9
  const schemaMigrator = new SchemaMigrator(modificationFactory)
@@ -28,17 +29,24 @@ export function testDiffSchemas(
28
29
  updatedAcl: Acl.Schema = emptyAcl,
29
30
  ) {
30
31
  const actualDiff = schemaDiffer.diffSchemas(
31
- { model: originalModel, acl: originalAcl, validation: {} },
32
- { model: updatedModel, acl: updatedAcl, validation: {} },
33
- false,
32
+ { ...emptySchema, model: originalModel, acl: originalAcl, validation: {} },
33
+ { ...emptySchema, model: updatedModel, acl: updatedAcl, validation: {} },
34
+ { skipRecreateValidation: true },
34
35
  )
35
- assert.deepStrictEqual(actualDiff, expectedDiff)
36
+ try {
37
+ assert.deepStrictEqual(actualDiff, expectedDiff)
38
+ } catch (e) {
39
+ // eslint-disable-next-line no-console
40
+ console.log(JSON.stringify(actualDiff))
41
+ throw e
42
+ }
36
43
  const { meta, ...schema } = schemaMigrator.applyModifications(
37
- { model: originalModel, acl: originalAcl, validation: {} },
44
+ { ...emptySchema, model: originalModel, acl: originalAcl, validation: {} },
38
45
  actualDiff,
39
46
  VERSION_LATEST,
40
47
  ) as SchemaWithMeta
41
48
  assert.deepStrictEqual(schema, {
49
+ ...emptySchema,
42
50
  model: updatedModel,
43
51
  acl: updatedAcl,
44
52
  validation: {},
@@ -53,12 +61,13 @@ export function testApplyDiff(
53
61
  expectedAcl: Acl.Schema = emptyAcl,
54
62
  ) {
55
63
  const { meta, ...actualSchema } = schemaMigrator.applyModifications(
56
- { model: originalModel, acl: originalAcl, validation: {} },
64
+ { ...emptySchema, model: originalModel, acl: originalAcl, validation: {} },
57
65
  diff,
58
66
  VERSION_LATEST,
59
67
  ) as SchemaWithMeta
60
68
 
61
69
  assert.deepStrictEqual(actualSchema, {
70
+ ...emptySchema,
62
71
  model: expectedModel,
63
72
  acl: expectedAcl,
64
73
  validation: {},
@@ -66,7 +75,7 @@ export function testApplyDiff(
66
75
  }
67
76
 
68
77
  export function testGenerateSql(originalSchema: Model.Schema, diff: Migration.Modification[], expectedSql: string) {
69
- let schema = { model: originalSchema, acl: emptyAcl, validation: {} }
78
+ let schema = { ...emptySchema, model: originalSchema, acl: emptyAcl, validation: {} }
70
79
  const builder = createMigrationBuilder()
71
80
  for (let { modification, ...data } of diff) {
72
81
  const modificationHandler = modificationFactory.create(modification, data, schema, { formatVersion: VERSION_LATEST, systemSchema: 'system' })