@contember/engine-system-api 2.1.0-alpha.1 → 2.1.0-alpha.10

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 (57) hide show
  1. package/dist/development/src/migrations/2025-03-14-110000-fix-missing-index.cjs +63 -0
  2. package/dist/development/src/migrations/2025-03-14-110000-fix-missing-index.cjs.map +1 -0
  3. package/dist/development/src/migrations/2025-03-14-110000-fix-missing-index.js +64 -0
  4. package/dist/development/src/migrations/2025-03-14-110000-fix-missing-index.js.map +1 -0
  5. package/dist/development/src/migrations/runner.cjs +3 -1
  6. package/dist/development/src/migrations/runner.cjs.map +1 -1
  7. package/dist/development/src/migrations/runner.js +3 -1
  8. package/dist/development/src/migrations/runner.js.map +1 -1
  9. package/dist/development/src/model/migrations/ProjectMigrator.cjs +1 -1
  10. package/dist/development/src/model/migrations/ProjectMigrator.cjs.map +1 -1
  11. package/dist/development/src/model/migrations/ProjectMigrator.js +1 -1
  12. package/dist/development/src/model/migrations/ProjectMigrator.js.map +1 -1
  13. package/dist/development/src/model/queries/events/LatestTransactionIdByStageQuery.cjs +1 -5
  14. package/dist/development/src/model/queries/events/LatestTransactionIdByStageQuery.cjs.map +1 -1
  15. package/dist/development/src/model/queries/events/LatestTransactionIdByStageQuery.js +1 -5
  16. package/dist/development/src/model/queries/events/LatestTransactionIdByStageQuery.js.map +1 -1
  17. package/dist/production/src/migrations/2025-03-14-110000-fix-missing-index.cjs +63 -0
  18. package/dist/production/src/migrations/2025-03-14-110000-fix-missing-index.cjs.map +1 -0
  19. package/dist/production/src/migrations/2025-03-14-110000-fix-missing-index.js +64 -0
  20. package/dist/production/src/migrations/2025-03-14-110000-fix-missing-index.js.map +1 -0
  21. package/dist/production/src/migrations/runner.cjs +3 -1
  22. package/dist/production/src/migrations/runner.cjs.map +1 -1
  23. package/dist/production/src/migrations/runner.js +3 -1
  24. package/dist/production/src/migrations/runner.js.map +1 -1
  25. package/dist/production/src/model/migrations/ProjectMigrator.cjs +1 -1
  26. package/dist/production/src/model/migrations/ProjectMigrator.cjs.map +1 -1
  27. package/dist/production/src/model/migrations/ProjectMigrator.js +1 -1
  28. package/dist/production/src/model/migrations/ProjectMigrator.js.map +1 -1
  29. package/dist/production/src/model/queries/events/LatestTransactionIdByStageQuery.cjs +1 -5
  30. package/dist/production/src/model/queries/events/LatestTransactionIdByStageQuery.cjs.map +1 -1
  31. package/dist/production/src/model/queries/events/LatestTransactionIdByStageQuery.js +1 -5
  32. package/dist/production/src/model/queries/events/LatestTransactionIdByStageQuery.js.map +1 -1
  33. package/dist/tests/cases/migrations/2025-03-14-110000-fix-missing-index.test.d.ts +2 -0
  34. package/dist/tests/cases/migrations/2025-03-14-110000-fix-missing-index.test.d.ts.map +1 -0
  35. package/dist/tests/src/uuid.d.ts.map +1 -1
  36. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  37. package/dist/types/migrations/2025-03-14-110000-fix-missing-index.d.ts +4 -0
  38. package/dist/types/migrations/2025-03-14-110000-fix-missing-index.d.ts.map +1 -0
  39. package/dist/types/migrations/runner.d.ts.map +1 -1
  40. package/dist/types/migrations/snapshot-factory.d.ts.map +1 -1
  41. package/dist/types/model/events/EventResponseHelper.d.ts.map +1 -1
  42. package/dist/types/model/events/identityUtils.d.ts.map +1 -1
  43. package/dist/types/model/helpers/modelHelpers.d.ts.map +1 -1
  44. package/dist/types/model/queries/events/EventQueryHelpers.d.ts.map +1 -1
  45. package/dist/types/model/queries/events/LatestTransactionIdByStageQuery.d.ts +2 -2
  46. package/dist/types/model/queries/events/LatestTransactionIdByStageQuery.d.ts.map +1 -1
  47. package/dist/types/model/queries/migrations/ExecutedMigrationsQueryHelper.d.ts.map +1 -1
  48. package/dist/types/resolvers/types/OldValuesHelpers.d.ts.map +1 -1
  49. package/dist/types/tsconfig.tsbuildinfo +1 -1
  50. package/dist/types/utils/batchQuery.d.ts.map +1 -1
  51. package/dist/types/utils/tuple.d.ts.map +1 -1
  52. package/package.json +13 -13
  53. package/src/migrations/2025-03-14-110000-fix-missing-index.ts +71 -0
  54. package/src/migrations/runner.ts +2 -0
  55. package/src/model/migrations/ProjectMigrator.ts +1 -1
  56. package/src/model/queries/events/LatestTransactionIdByStageQuery.ts +3 -7
  57. package/tests/cases/migrations/2025-03-14-110000-fix-missing-index.test.ts +62 -0
@@ -1 +1 @@
1
- {"version":3,"file":"batchQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/batchQuery.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEhE,eAAO,MAAM,iBAAiB,GAAI,GAAG,EAAE,MAAM,EAAE,IAAI,gBACpC,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,WACrC,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,KACzC,UAAU,CAAC,GAAG,EAAE,IAAI,CAiBtB,CAAA"}
1
+ {"version":3,"file":"batchQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/batchQuery.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEhE,eAAO,MAAM,iBAAiB,GAAI,GAAG,EAAE,MAAM,EAAE,IAAI,EAClD,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,EAC9C,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,KACzC,UAAU,CAAC,GAAG,EAAE,IAAI,CAiBtB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"tuple.d.ts","sourceRoot":"","sources":["../../../src/utils/tuple.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,GAAG,EAAE,aAAa,CAAC,MAAW,CAAA"}
1
+ {"version":3,"file":"tuple.d.ts","sourceRoot":"","sources":["../../../src/utils/tuple.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,GAAG,EAAE,EAAE,GAAG,QAAQ,CAAC,MAAW,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/engine-system-api",
3
- "version": "2.1.0-alpha.1",
3
+ "version": "2.1.0-alpha.10",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/production/index.js",
6
6
  "typings": "./dist/types/index.d.ts",
@@ -23,22 +23,22 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@contember/authorization": "2.1.0-alpha.1",
27
- "@contember/database": "2.1.0-alpha.1",
28
- "@contember/database-migrations": "2.1.0-alpha.1",
29
- "@contember/dic": "2.1.0-alpha.1",
30
- "@contember/graphql-utils": "2.1.0-alpha.1",
31
- "@contember/logger": "2.1.0-alpha.1",
32
- "@contember/queryable": "2.1.0-alpha.1",
33
- "@contember/schema": "2.1.0-alpha.1",
34
- "@contember/schema-migrations": "2.1.0-alpha.1",
35
- "@contember/schema-utils": "2.1.0-alpha.1",
26
+ "@contember/authorization": "2.1.0-alpha.10",
27
+ "@contember/database": "2.1.0-alpha.10",
28
+ "@contember/database-migrations": "2.1.0-alpha.10",
29
+ "@contember/dic": "2.1.0-alpha.10",
30
+ "@contember/graphql-utils": "2.1.0-alpha.10",
31
+ "@contember/logger": "2.1.0-alpha.10",
32
+ "@contember/queryable": "2.1.0-alpha.10",
33
+ "@contember/schema": "2.1.0-alpha.10",
34
+ "@contember/schema-migrations": "2.1.0-alpha.10",
35
+ "@contember/schema-utils": "2.1.0-alpha.10",
36
36
  "@graphql-tools/utils": "^10.5.5",
37
37
  "graphql-tag": "^2.12.6"
38
38
  },
39
39
  "devDependencies": {
40
- "@contember/schema-definition": "2.1.0-alpha.1",
41
- "@types/node": "^20.16.11",
40
+ "@contember/schema-definition": "2.1.0-alpha.10",
41
+ "@types/node": "^20.17.22",
42
42
  "graphql": "^16.9.0",
43
43
  "pg": "^8.12.0"
44
44
  },
@@ -0,0 +1,71 @@
1
+ import { MigrationArgs, MigrationBuilder } from '@contember/database-migrations'
2
+ import { DatabaseMetadata } from '@contember/database'
3
+ import { SystemMigrationArgs } from './types'
4
+ import { wrapIdentifier } from '@contember/database'
5
+ import { Model } from '@contember/schema'
6
+ import { acceptFieldVisitor } from '@contember/schema-utils'
7
+
8
+ export default async function (builder: MigrationBuilder, args: MigrationArgs<SystemMigrationArgs>) {
9
+ const schema = (await args.schemaResolver(args.connection)).schema
10
+ const stages = (await args.connection.query<{schema: string}>('SELECT schema FROM stage')).rows
11
+ const metadataByStage: Record<string, DatabaseMetadata> = {}
12
+
13
+ for (const entity of Object.values(schema.model.entities)) {
14
+ if (entity.indexes.length === 0) {
15
+ continue
16
+ }
17
+ if (entity.view) {
18
+ continue
19
+ }
20
+
21
+ for (const stage of stages) {
22
+ const databaseMetadata = metadataByStage[stage.schema] ??= await args.databaseMetadataResolver(args.connection, stage.schema)
23
+
24
+ for (const index of entity.indexes) {
25
+ const columns = getIndexColumns({
26
+ entity,
27
+ fields: index.fields,
28
+ model: schema.model,
29
+ })
30
+ const indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns }).getNames()
31
+ if (indexNames.length > 0) {
32
+ continue
33
+ }
34
+
35
+ const tableNameId = wrapIdentifier(entity.tableName)
36
+ const columnNameIds = columns.map(wrapIdentifier)
37
+
38
+ builder.sql(`CREATE INDEX ON ${wrapIdentifier(stage.schema)}.${tableNameId} (${columnNameIds.join(', ')})`)
39
+
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ const getIndexColumns = ({ entity, fields, model }: { fields: readonly string[]; model: Model.Schema; entity: Model.Entity }) => {
46
+ return fields.map(fieldName => {
47
+ return acceptFieldVisitor(model, entity, fieldName, {
48
+ visitColumn: ({ column }) => {
49
+ return column.columnName
50
+ },
51
+ visitManyHasOne: ({ relation }) => {
52
+ return relation.joiningColumn.columnName
53
+ },
54
+ visitOneHasOneOwning: ({ relation }) => {
55
+ return relation.joiningColumn.columnName
56
+ },
57
+ visitOneHasMany: () => {
58
+ throw new Error(`Cannot create index on 1:m relation in ${entity.name}.${fieldName}`)
59
+ },
60
+ visitOneHasOneInverse: () => {
61
+ throw new Error(`Cannot create index on 1:1 inverse relation in ${entity.name}.${fieldName}`)
62
+ },
63
+ visitManyHasManyOwning: () => {
64
+ throw new Error(`Cannot create index on m:m relation in ${entity.name}.${fieldName}`)
65
+ },
66
+ visitManyHasManyInverse: () => {
67
+ throw new Error(`Cannot create index on m:m inverse relation in ${entity.name}.${fieldName}`)
68
+ },
69
+ })
70
+ })
71
+ }
@@ -29,6 +29,7 @@ import _20240628150000migrationsdropsequence from './2024-06-28-150000-migration
29
29
  import _20240628153000schema from './2024-06-28-153000-schema'
30
30
  import _20240628153001schemainit from './2024-06-28-153001-schema-init'
31
31
  import _20240729150000eventdataindex from './2024-07-29-150000-event-data-index'
32
+ import _20250314110000fixmissingindex from './2025-03-14-110000-fix-missing-index'
32
33
  import snapshot from './snapshot'
33
34
 
34
35
  import { Connection, createDatabaseIfNotExists, DatabaseConfig, DatabaseMetadataResolver } from '@contember/database'
@@ -62,6 +63,7 @@ const migrations = {
62
63
  '2024-06-28-153000-schema': _20240628153000schema,
63
64
  '2024-06-28-153001-schema-init': _20240628153001schemainit,
64
65
  '2024-07-29-150000-event-data-index': _20240729150000eventdataindex,
66
+ '2025-03-14-110000-fix-missing-index': _20250314110000fixmissingindex,
65
67
  }
66
68
 
67
69
 
@@ -227,7 +227,7 @@ export class ProjectMigrator {
227
227
  }
228
228
 
229
229
  private async executeOnStage(db: Client, stage: Stage, sql: string, migrationVersion: string) {
230
- await db.query('SET search_path TO ' + wrapIdentifier(stage.schema))
230
+ await db.query('SET LOCAL search_path TO ' + wrapIdentifier(stage.schema))
231
231
  try {
232
232
  await db.query(sql)
233
233
  } catch (e) {
@@ -1,12 +1,11 @@
1
1
  import { DatabaseQuery, DatabaseQueryable, SelectBuilder } from '@contember/database'
2
- import { ImplementationException } from '../../../utils'
3
2
 
4
- export class LatestTransactionIdByStageQuery extends DatabaseQuery<string> {
3
+ export class LatestTransactionIdByStageQuery extends DatabaseQuery<string | null> {
5
4
  constructor(private readonly stageId: string) {
6
5
  super()
7
6
  }
8
7
 
9
- async fetch(queryable: DatabaseQueryable): Promise<string> {
8
+ async fetch(queryable: DatabaseQueryable): Promise<string | null> {
10
9
  const rows = await SelectBuilder.create<{ transaction_id: string }>()
11
10
  .from('stage_transaction')
12
11
  .select('transaction_id')
@@ -15,9 +14,6 @@ export class LatestTransactionIdByStageQuery extends DatabaseQuery<string> {
15
14
  .limit(1)
16
15
  .getResult(queryable.db)
17
16
 
18
- if (rows.length !== 1) {
19
- throw new ImplementationException()
20
- }
21
- return rows[0].transaction_id
17
+ return rows.length === 0 ? null : rows[0].transaction_id
22
18
  }
23
19
  }
@@ -0,0 +1,62 @@
1
+ import migration from '../../../src/migrations/2025-03-14-110000-fix-missing-index'
2
+ import { createMigrationBuilder } from '@contember/database-migrations'
3
+ import { expect, test } from 'bun:test'
4
+ import { c, createSchema } from '@contember/schema-definition'
5
+ import { createConnectionMock } from '@contember/database-tester'
6
+ import { createDatabaseMetadata } from '@contember/database'
7
+
8
+ namespace IndexModel {
9
+
10
+ @c.Index('colA', 'colB')
11
+ @c.Index('colB', 'colC')
12
+ export class Foo {
13
+ colA = c.stringColumn()
14
+ colB = c.stringColumn()
15
+ colC = c.stringColumn()
16
+ }
17
+
18
+ }
19
+
20
+ test('unique fix test', async () => {
21
+ const builder = createMigrationBuilder()
22
+ const connection = createConnectionMock([{
23
+ sql: 'select schema from stage',
24
+ response: { rows: [{ schema: 'stage_live' }] },
25
+ }])
26
+ await migration(builder, {
27
+ connection: connection,
28
+ databaseMetadataResolver: () => Promise.resolve(createDatabaseMetadata({
29
+ foreignKeys: [],
30
+ indexes: [
31
+ { indexName: 'valid1', tableName: 'foo', columnNames: ['col_a', 'col_b'], unique: false },
32
+ ],
33
+ uniqueConstraints: [],
34
+ })),
35
+ schemaResolver: () => Promise.resolve({
36
+ schema: createSchema(IndexModel),
37
+ meta: {
38
+ id: 1,
39
+ version: '2024-06-28-153001',
40
+ checksum: '_checksum_',
41
+ updatedAt: new Date(),
42
+ },
43
+ }),
44
+ project: {
45
+ slug: 'test',
46
+ stages: [
47
+ {
48
+ slug: 'prod',
49
+ name: 'prod',
50
+ },
51
+ ],
52
+ systemSchema: 'system',
53
+ },
54
+ })
55
+ expect(
56
+ builder.getSql(),
57
+ ).toEqual(
58
+ `CREATE INDEX ON "stage_live"."foo" ("col_b", "col_c");
59
+ `,
60
+ )
61
+ })
62
+