@contember/schema-migrations 2.0.0-alpha.19 → 2.0.0-alpha.21

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 (24) hide show
  1. package/dist/development/src/modifications/columns/columnUtils.cjs +1 -1
  2. package/dist/development/src/modifications/columns/columnUtils.cjs.map +1 -1
  3. package/dist/development/src/modifications/columns/columnUtils.js +1 -1
  4. package/dist/development/src/modifications/columns/columnUtils.js.map +1 -1
  5. package/dist/development/src/modifications/entities/RemoveEntityModification.cjs +18 -1
  6. package/dist/development/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
  7. package/dist/development/src/modifications/entities/RemoveEntityModification.js +19 -2
  8. package/dist/development/src/modifications/entities/RemoveEntityModification.js.map +1 -1
  9. package/dist/production/src/modifications/columns/columnUtils.cjs +1 -1
  10. package/dist/production/src/modifications/columns/columnUtils.cjs.map +1 -1
  11. package/dist/production/src/modifications/columns/columnUtils.js +1 -1
  12. package/dist/production/src/modifications/columns/columnUtils.js.map +1 -1
  13. package/dist/production/src/modifications/entities/RemoveEntityModification.cjs +18 -1
  14. package/dist/production/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
  15. package/dist/production/src/modifications/entities/RemoveEntityModification.js +19 -2
  16. package/dist/production/src/modifications/entities/RemoveEntityModification.js.map +1 -1
  17. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  18. package/dist/types/modifications/entities/RemoveEntityModification.d.ts.map +1 -1
  19. package/dist/types/tsconfig.tsbuildinfo +1 -1
  20. package/package.json +7 -7
  21. package/src/modifications/columns/columnUtils.ts +1 -1
  22. package/src/modifications/entities/RemoveEntityModification.ts +15 -3
  23. package/tests/cases/integration/createColumn.test.ts +72 -2
  24. package/tests/cases/integration/removeEntity.test.ts +96 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/schema-migrations",
3
- "version": "2.0.0-alpha.19",
3
+ "version": "2.0.0-alpha.21",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/production/index.js",
6
6
  "typings": "./dist/types/index.d.ts",
@@ -23,16 +23,16 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@contember/database": "2.0.0-alpha.19",
27
- "@contember/database-migrations": "2.0.0-alpha.19",
28
- "@contember/engine-common": "2.0.0-alpha.19",
29
- "@contember/schema": "2.0.0-alpha.19",
30
- "@contember/schema-utils": "2.0.0-alpha.19",
26
+ "@contember/database": "2.0.0-alpha.21",
27
+ "@contember/database-migrations": "2.0.0-alpha.21",
28
+ "@contember/engine-common": "2.0.0-alpha.21",
29
+ "@contember/schema": "2.0.0-alpha.21",
30
+ "@contember/schema-utils": "2.0.0-alpha.21",
31
31
  "fast-deep-equal": "^3.1.3",
32
32
  "rfc6902": "^5.1.1"
33
33
  },
34
34
  "devDependencies": {
35
- "@contember/schema-definition": "2.0.0-alpha.19"
35
+ "@contember/schema-definition": "2.0.0-alpha.21"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "pg": "^8.9.0"
@@ -36,7 +36,7 @@ export const formatSeedExpression = ({ model, entity, columnType, fillValue, cop
36
36
  copyValue?: string
37
37
  }): string | null => {
38
38
  if (fillValue !== undefined) {
39
- return escapeValue(fillValue)
39
+ return escapeValue(fillValue).toString()
40
40
  } else if (copyValue !== undefined) {
41
41
  const copyFrom = getColumnName(model, entity, copyValue)
42
42
  return `${wrapIdentifier(copyFrom)}::${columnType}`
@@ -1,5 +1,5 @@
1
1
  import { MigrationBuilder } from '@contember/database-migrations'
2
- import { Acl, Schema } from '@contember/schema'
2
+ import { Acl, Model, Schema } from '@contember/schema'
3
3
  import {
4
4
  removeField,
5
5
  SchemaUpdater,
@@ -18,7 +18,7 @@ import {
18
18
  ModificationHandlerOptions,
19
19
  } from '../ModificationHandler'
20
20
  import { VERSION_ACL_PATCH, VERSION_REMOVE_REFERENCING_RELATIONS } from '../ModificationVersions'
21
- import { isRelation, PredicateDefinitionProcessor } from '@contember/schema-utils'
21
+ import { acceptEveryFieldVisitor, isInverseRelation, isRelation, PredicateDefinitionProcessor } from '@contember/schema-utils'
22
22
  import { removeFieldModification } from '../fields'
23
23
 
24
24
  export class RemoveEntityModificationHandler implements ModificationHandler<RemoveEntityModificationData> {
@@ -40,6 +40,17 @@ export class RemoveEntityModificationHandler implements ModificationHandler<Remo
40
40
  removeFieldHandler.createSql(builder, options)
41
41
  })
42
42
  }
43
+ acceptEveryFieldVisitor(this.schema.model, entity, {
44
+ visitManyHasManyOwning: ({ relation }) => {
45
+ builder.dropTable(relation.joiningTable.tableName)
46
+ },
47
+ visitManyHasManyInverse: () => {},
48
+ visitColumn: () => {},
49
+ visitOneHasOneInverse: () => {},
50
+ visitOneHasOneOwning: () => {},
51
+ visitManyHasOne: () => {},
52
+ visitOneHasMany: () => {},
53
+ })
43
54
  builder.dropTable(entity.tableName)
44
55
  }
45
56
 
@@ -99,7 +110,8 @@ export class RemoveEntityModificationHandler implements ModificationHandler<Remo
99
110
  private getFieldsToRemove(schema: Schema): [entity: string, field: string][] {
100
111
  return Object.values(schema.model.entities).flatMap(entity =>
101
112
  Object.values(entity.fields)
102
- .filter(field => isRelation(field) && field.target === this.data.entityName)
113
+ .filter((field): field is Model.AnyRelation => isRelation(field) && field.target === this.data.entityName)
114
+ .filter(field => !isInverseRelation(field) || entity.name !== this.data.entityName) // skip self-referencing inverse relations
103
115
  .map((field): [string, string] => [entity.name, field.name]),
104
116
  )
105
117
  }
@@ -79,6 +79,10 @@ testMigrations('create a column with default value with "using"', {
79
79
  updated: createSchema({
80
80
  Author: class Author {
81
81
  name = def.stringColumn().default('unnamed author').notNull()
82
+ order = def.intColumn().default(0).notNull()
83
+ score = def.doubleColumn().default(1 / 3).notNull()
84
+ active = def.boolColumn().default(false).notNull()
85
+ createdAt = def.dateTimeColumn().default('2024-01-01 10:00').notNull()
82
86
  email = def.stringColumn().unique()
83
87
  },
84
88
  }),
@@ -97,7 +101,73 @@ testMigrations('create a column with default value with "using"', {
97
101
  fillValue: 'unnamed author',
98
102
  valueMigrationStrategy: 'using',
99
103
  },
104
+ {
105
+ modification: 'createColumn',
106
+ entityName: 'Author',
107
+ field: {
108
+ columnName: 'order',
109
+ name: 'order',
110
+ nullable: false,
111
+ default: 0,
112
+ type: Model.ColumnType.Int,
113
+ columnType: 'integer',
114
+ },
115
+ fillValue: 0,
116
+ valueMigrationStrategy: 'using',
117
+ },
118
+ {
119
+ modification: 'createColumn',
120
+ entityName: 'Author',
121
+ field: {
122
+ columnName: 'score',
123
+ name: 'score',
124
+ nullable: false,
125
+ default: 0.3333333333333333,
126
+ type: Model.ColumnType.Double,
127
+ columnType: 'double precision',
128
+ },
129
+ fillValue: 0.3333333333333333,
130
+ valueMigrationStrategy: 'using',
131
+ },
132
+ {
133
+ modification: 'createColumn',
134
+ entityName: 'Author',
135
+ field: {
136
+ columnName: 'active',
137
+ name: 'active',
138
+ nullable: false,
139
+ default: false,
140
+ type: Model.ColumnType.Bool,
141
+ columnType: 'boolean',
142
+ },
143
+ fillValue: false,
144
+ valueMigrationStrategy: 'using',
145
+ },
146
+ {
147
+ modification: 'createColumn',
148
+ entityName: 'Author',
149
+ field: {
150
+ columnName: 'created_at',
151
+ name: 'createdAt',
152
+ nullable: false,
153
+ default: '2024-01-01 10:00',
154
+ type: Model.ColumnType.DateTime,
155
+ columnType: 'timestamptz',
156
+ },
157
+ fillValue: '2024-01-01 10:00',
158
+ valueMigrationStrategy: 'using',
159
+ },
100
160
  ],
101
- sql: SQL`ALTER TABLE "author" ADD "name" text;
102
- ALTER TABLE "author" ALTER "name" SET DATA TYPE text USING $pga$unnamed author$pga$, ALTER "name" SET NOT NULL;`,
161
+ sql: SQL`
162
+ ALTER TABLE "author" ADD "name" text;
163
+ ALTER TABLE "author" ALTER "name" SET DATA TYPE text USING $pga$unnamed author$pga$, ALTER "name" SET NOT NULL;
164
+ ALTER TABLE "author" ADD "order" integer;
165
+ ALTER TABLE "author" ALTER "order" SET DATA TYPE integer USING 0, ALTER "order" SET NOT NULL;
166
+ ALTER TABLE "author" ADD "score" double precision;
167
+ ALTER TABLE "author" ALTER "score" SET DATA TYPE double precision USING 0.3333333333333333, ALTER "score" SET NOT NULL;
168
+ ALTER TABLE "author" ADD "active" boolean;
169
+ ALTER TABLE "author" ALTER "active" SET DATA TYPE boolean USING false,
170
+ ALTER "active" SET NOT NULL; ALTER TABLE "author" ADD "created_at" timestamptz;
171
+ ALTER TABLE "author" ALTER "created_at" SET DATA TYPE timestamptz USING $pga$2024-01-01 10:00$pga$, ALTER "created_at" SET NOT NULL;
172
+ `,
103
173
  })
@@ -119,3 +119,99 @@ testMigrations('remove a view', {
119
119
  sql: SQL`
120
120
  DROP VIEW "author";`,
121
121
  })
122
+
123
+
124
+ namespace EntityWithManyHasManyOriginalSchema {
125
+
126
+ export class Book {
127
+ title = def.stringColumn()
128
+ tags = def.manyHasMany(Tag, 'books')
129
+ }
130
+
131
+ export class Tag {
132
+ name = def.stringColumn()
133
+ books = def.manyHasManyInverse(Book, 'tags')
134
+ }
135
+ }
136
+ testMigrations('remove junction table, when both entities are removed', {
137
+ original: createSchema(EntityWithManyHasManyOriginalSchema),
138
+ updated: {},
139
+ diff: [
140
+ {
141
+ modification: 'removeEntity',
142
+ entityName: 'Book',
143
+ },
144
+ {
145
+ modification: 'removeEntity',
146
+ entityName: 'Tag',
147
+ },
148
+ ],
149
+ sql: SQL`DROP TABLE "book_tags";
150
+ DROP TABLE "book";
151
+ DROP TABLE "tag";`,
152
+ })
153
+
154
+
155
+ namespace EntityWithManyHasManyUpdatedSchema {
156
+
157
+ export class Tag {
158
+ name = def.stringColumn()
159
+ }
160
+ }
161
+ testMigrations('remove junction table, when owning entity is removed', {
162
+ original: createSchema(EntityWithManyHasManyOriginalSchema),
163
+ updated: createSchema(EntityWithManyHasManyUpdatedSchema),
164
+ diff: [
165
+ {
166
+ modification: 'removeEntity',
167
+ entityName: 'Book',
168
+ },
169
+
170
+ ],
171
+ sql: SQL`DROP TABLE "book_tags";
172
+ DROP TABLE "book";`,
173
+ })
174
+
175
+
176
+ namespace EntityWithManyHasMany2UpdatedSchema {
177
+
178
+ export class Book {
179
+ title = def.stringColumn()
180
+ }
181
+ }
182
+ testMigrations('remove junction table, when inverse entity is removed', {
183
+ original: createSchema(EntityWithManyHasManyOriginalSchema),
184
+ updated: createSchema(EntityWithManyHasMany2UpdatedSchema),
185
+ diff: [
186
+ {
187
+ modification: 'removeEntity',
188
+ entityName: 'Tag',
189
+ },
190
+
191
+ ],
192
+ sql: SQL`
193
+ DROP TABLE "book_tags";
194
+ DROP TABLE "tag";`,
195
+ })
196
+
197
+
198
+ namespace EntityWithSelfReferencingRelationOriginalSchema {
199
+
200
+ export class Person {
201
+ name = def.stringColumn()
202
+ parent = def.manyHasOne(Person, 'children')
203
+ children = def.oneHasMany(Person, 'parent')
204
+ }
205
+ }
206
+
207
+ testMigrations('remove self-referencing relation', {
208
+ original: createSchema(EntityWithSelfReferencingRelationOriginalSchema),
209
+ updated: {},
210
+ diff: [
211
+ {
212
+ modification: 'removeEntity',
213
+ entityName: 'Person',
214
+ },
215
+ ],
216
+ sql: SQL`ALTER TABLE "person" DROP "parent_id"; DROP TABLE "person";`,
217
+ })