@expo/entity-database-adapter-knex 0.40.0 → 0.42.0
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.
- package/build/EntityFields.d.ts +3 -3
- package/build/EntityFields.js.map +1 -1
- package/build/PostgresEntityDatabaseAdapter.d.ts +2 -2
- package/build/PostgresEntityDatabaseAdapter.js +31 -5
- package/build/PostgresEntityDatabaseAdapter.js.map +1 -1
- package/build/PostgresEntityDatabaseAdapterProvider.d.ts +1 -1
- package/build/PostgresEntityDatabaseAdapterProvider.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +9 -7
- package/src/EntityFields.ts +11 -3
- package/src/PostgresEntityDatabaseAdapter.ts +38 -7
- package/src/PostgresEntityDatabaseAdapterProvider.ts +3 -3
- package/src/__integration-tests__/PostgresEntityIntegration-test.ts +209 -250
- package/src/__integration-tests__/PostgresEntityQueryContextProvider-test.ts +17 -26
- package/src/__integration-tests__/PostgresInvalidSetup-test.ts +13 -18
- package/src/__integration-tests__/errors-test.ts +3 -15
- package/src/{testfixtures → __testfixtures__}/ErrorsTestEntity.ts +9 -12
- package/src/{testfixtures → __testfixtures__}/InvalidTestEntity.ts +12 -8
- package/src/{testfixtures → __testfixtures__}/PostgresTestEntity.ts +13 -9
- package/src/{testfixtures → __testfixtures__}/PostgresTriggerTestEntity.ts +29 -27
- package/src/{testfixtures → __testfixtures__}/PostgresUniqueTestEntity.ts +26 -24
- package/src/{testfixtures → __testfixtures__}/PostgresValidatorTestEntity.ts +28 -26
- package/src/{testfixtures → __testfixtures__}/createKnexIntegrationTestEntityCompanionProvider.ts +1 -1
- package/src/__tests__/EntityFields-test.ts +1 -1
- package/build/__integration-tests__/PostgresEntityIntegration-test.d.ts +0 -1
- package/build/__integration-tests__/PostgresEntityIntegration-test.js +0 -589
- package/build/__integration-tests__/PostgresEntityIntegration-test.js.map +0 -1
- package/build/__integration-tests__/PostgresEntityQueryContextProvider-test.d.ts +0 -1
- package/build/__integration-tests__/PostgresEntityQueryContextProvider-test.js +0 -95
- package/build/__integration-tests__/PostgresEntityQueryContextProvider-test.js.map +0 -1
- package/build/__integration-tests__/PostgresInvalidSetup-test.d.ts +0 -1
- package/build/__integration-tests__/PostgresInvalidSetup-test.js +0 -74
- package/build/__integration-tests__/PostgresInvalidSetup-test.js.map +0 -1
- package/build/__integration-tests__/errors-test.d.ts +0 -1
- package/build/__integration-tests__/errors-test.js +0 -139
- package/build/__integration-tests__/errors-test.js.map +0 -1
- package/build/__tests__/EntityFields-test.d.ts +0 -1
- package/build/__tests__/EntityFields-test.js +0 -8
- package/build/__tests__/EntityFields-test.js.map +0 -1
- package/build/errors/__tests__/wrapNativePostgresCallAsync-test.d.ts +0 -1
- package/build/errors/__tests__/wrapNativePostgresCallAsync-test.js +0 -24
- package/build/errors/__tests__/wrapNativePostgresCallAsync-test.js.map +0 -1
- package/build/testfixtures/ErrorsTestEntity.d.ts +0 -24
- package/build/testfixtures/ErrorsTestEntity.js +0 -106
- package/build/testfixtures/ErrorsTestEntity.js.map +0 -1
- package/build/testfixtures/InvalidTestEntity.d.ts +0 -19
- package/build/testfixtures/InvalidTestEntity.js +0 -61
- package/build/testfixtures/InvalidTestEntity.js.map +0 -1
- package/build/testfixtures/PostgresTestEntity.d.ts +0 -31
- package/build/testfixtures/PostgresTestEntity.js +0 -95
- package/build/testfixtures/PostgresTestEntity.js.map +0 -1
- package/build/testfixtures/PostgresTriggerTestEntity.d.ts +0 -19
- package/build/testfixtures/PostgresTriggerTestEntity.js +0 -101
- package/build/testfixtures/PostgresTriggerTestEntity.js.map +0 -1
- package/build/testfixtures/PostgresUniqueTestEntity.d.ts +0 -19
- package/build/testfixtures/PostgresUniqueTestEntity.js +0 -62
- package/build/testfixtures/PostgresUniqueTestEntity.js.map +0 -1
- package/build/testfixtures/PostgresValidatorTestEntity.d.ts +0 -19
- package/build/testfixtures/PostgresValidatorTestEntity.js +0 -77
- package/build/testfixtures/PostgresValidatorTestEntity.js.map +0 -1
- package/build/testfixtures/createKnexIntegrationTestEntityCompanionProvider.d.ts +0 -3
- package/build/testfixtures/createKnexIntegrationTestEntityCompanionProvider.js +0 -29
- package/build/testfixtures/createKnexIntegrationTestEntityCompanionProvider.js.map +0 -1
package/build/EntityFields.d.ts
CHANGED
|
@@ -2,19 +2,19 @@ import { EntityFieldDefinition } from '@expo/entity';
|
|
|
2
2
|
/**
|
|
3
3
|
* EntityFieldDefinition for a Postres column with a JS JSON array type.
|
|
4
4
|
*/
|
|
5
|
-
export declare class JSONArrayField extends EntityFieldDefinition<any[]> {
|
|
5
|
+
export declare class JSONArrayField<TRequireExplicitCache extends boolean> extends EntityFieldDefinition<any[], TRequireExplicitCache> {
|
|
6
6
|
protected validateInputValueInternal(value: any[]): boolean;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* EntityFieldDefinition for a Postgres column that may be a JS JSON array type.
|
|
10
10
|
* Does not do any validation.
|
|
11
11
|
*/
|
|
12
|
-
export declare class MaybeJSONArrayField extends EntityFieldDefinition<any | any[]> {
|
|
12
|
+
export declare class MaybeJSONArrayField<TRequireExplicitCache extends boolean> extends EntityFieldDefinition<any | any[], TRequireExplicitCache> {
|
|
13
13
|
protected validateInputValueInternal(_value: any): boolean;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* EntityFieldDefinition for a Postgres BIGINT column.
|
|
17
17
|
*/
|
|
18
|
-
export declare class BigIntField extends EntityFieldDefinition<string> {
|
|
18
|
+
export declare class BigIntField<TRequireExplicitCache extends boolean> extends EntityFieldDefinition<string, TRequireExplicitCache> {
|
|
19
19
|
protected validateInputValueInternal(value: string): boolean;
|
|
20
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityFields.js","sourceRoot":"","sources":["../src/EntityFields.ts"],"names":[],"mappings":";;;AAAA,yCAAqD;AAErD;;GAEG;AACH,MAAa,
|
|
1
|
+
{"version":3,"file":"EntityFields.js","sourceRoot":"","sources":["../src/EntityFields.ts"],"names":[],"mappings":";;;AAAA,yCAAqD;AAErD;;GAEG;AACH,MAAa,cAAsD,SAAQ,8BAG1E;IACW,0BAA0B,CAAC,KAAY;QAC/C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;CACF;AAPD,wCAOC;AAED;;;GAGG;AACH,MAAa,mBAEX,SAAQ,8BAAyD;IACvD,0BAA0B,CAAC,MAAW;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAND,kDAMC;AAED;;GAEG;AACH,MAAa,WAAmD,SAAQ,8BAGvE;IACW,0BAA0B,CAAC,KAAa;QAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC;IACnC,CAAC;CACF;AAPD,kCAOC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { EntityDatabaseAdapter, FieldTransformerMap, TableQuerySelectionModifiers, TableFieldSingleValueEqualityCondition, TableFieldMultiValueEqualityCondition, TableQuerySelectionModifiersWithOrderByRaw } from '@expo/entity';
|
|
2
2
|
import { Knex } from 'knex';
|
|
3
|
-
export default class PostgresEntityDatabaseAdapter<TFields extends Record<string, any
|
|
3
|
+
export default class PostgresEntityDatabaseAdapter<TFields extends Record<string, any>, TIDField extends keyof TFields> extends EntityDatabaseAdapter<TFields, TIDField> {
|
|
4
4
|
protected getFieldTransformerMap(): FieldTransformerMap;
|
|
5
|
-
protected fetchManyWhereInternalAsync(queryInterface: Knex, tableName: string,
|
|
5
|
+
protected fetchManyWhereInternalAsync(queryInterface: Knex, tableName: string, tableColumns: readonly string[], tableTuples: any[][]): Promise<object[]>;
|
|
6
6
|
private applyQueryModifiersToQueryOrderByRaw;
|
|
7
7
|
private applyQueryModifiersToQuery;
|
|
8
8
|
protected fetchManyByFieldEqualityConjunctionInternalAsync(queryInterface: Knex, tableName: string, tableFieldSingleValueEqualityOperands: TableFieldSingleValueEqualityCondition[], tableFieldMultiValueEqualityOperands: TableFieldMultiValueEqualityCondition[], querySelectionModifiers: TableQuerySelectionModifiers): Promise<object[]>;
|
|
@@ -32,11 +32,37 @@ class PostgresEntityDatabaseAdapter extends entity_1.EntityDatabaseAdapter {
|
|
|
32
32
|
],
|
|
33
33
|
]);
|
|
34
34
|
}
|
|
35
|
-
async fetchManyWhereInternalAsync(queryInterface, tableName,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
async fetchManyWhereInternalAsync(queryInterface, tableName, tableColumns, tableTuples) {
|
|
36
|
+
// For single column queries, use the ANY operator to derive a consistent
|
|
37
|
+
// query shape in the postgres query stats table.
|
|
38
|
+
// This produces a query of the form `SELECT * FROM table WHERE ("id") = ANY(?)`
|
|
39
|
+
// with value bindings of the form `[[1]]`, thus not making different value cardinalities
|
|
40
|
+
// produce different query shapes.
|
|
41
|
+
//
|
|
42
|
+
// But for multi-column queries, we must use the IN operator as the ANY operator
|
|
43
|
+
// does not support anonymous composite types. The solution to keep using the ANY operator would be explicit
|
|
44
|
+
// postgres type casting on each value in each tableTuple, thus creating a unique query shape and defeating the purpose.
|
|
45
|
+
// The same applies to using UNNEST on anonymous composite types.
|
|
46
|
+
// Note that this solution is not possible in entity though since we don't have the postgres column types and they
|
|
47
|
+
// can't be derived dynamically.
|
|
48
|
+
//
|
|
49
|
+
// Therefore, for multi-column quries, we use the IN operator which produces a query of the form
|
|
50
|
+
// `SELECT * FROM table WHERE ("id", "name") IN ((?, ?), (?, ?))` with value bindings of the form
|
|
51
|
+
// `[[1, 'a'], [2, 'b']]`, which will produce a unique query shape in the postgres query stats table for
|
|
52
|
+
// each value cardinality.
|
|
53
|
+
//
|
|
54
|
+
// We could use the IN operator for single column queries as well, but we prefer to use ANY to at least keep some
|
|
55
|
+
// consistency in the query shape for the stats table.
|
|
56
|
+
if (tableColumns.length === 1) {
|
|
57
|
+
return await (0, wrapNativePostgresCallAsync_1.default)(() => queryInterface
|
|
58
|
+
.select()
|
|
59
|
+
.from(tableName)
|
|
60
|
+
.whereRaw(`(??) = ANY(?)`, [
|
|
61
|
+
tableColumns[0],
|
|
62
|
+
tableTuples.map((tableTuple) => tableTuple[0]),
|
|
63
|
+
]));
|
|
64
|
+
}
|
|
65
|
+
return await (0, wrapNativePostgresCallAsync_1.default)(() => queryInterface.select().from(tableName).whereIn(tableColumns, tableTuples));
|
|
40
66
|
}
|
|
41
67
|
applyQueryModifiersToQueryOrderByRaw(query, querySelectionModifiers) {
|
|
42
68
|
let ret = this.applyQueryModifiersToQuery(query, querySelectionModifiers);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostgresEntityDatabaseAdapter.js","sourceRoot":"","sources":["../src/PostgresEntityDatabaseAdapter.ts"],"names":[],"mappings":";;;;;AAAA,yCAQsB;AAGtB,iDAAqE;AACrE,uGAA+E;AAE/E,MAAqB,
|
|
1
|
+
{"version":3,"file":"PostgresEntityDatabaseAdapter.js","sourceRoot":"","sources":["../src/PostgresEntityDatabaseAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { IEntityDatabaseAdapterProvider, EntityConfiguration, EntityDatabaseAdapter } from '@expo/entity';
|
|
2
2
|
export default class PostgresEntityDatabaseAdapterProvider implements IEntityDatabaseAdapterProvider {
|
|
3
|
-
getDatabaseAdapter<TFields extends Record<string, any
|
|
3
|
+
getDatabaseAdapter<TFields extends Record<string, any>, TIDField extends keyof TFields>(entityConfiguration: EntityConfiguration<TFields, TIDField>): EntityDatabaseAdapter<TFields, TIDField>;
|
|
4
4
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostgresEntityDatabaseAdapterProvider.js","sourceRoot":"","sources":["../src/PostgresEntityDatabaseAdapterProvider.ts"],"names":[],"mappings":";;;;;AAMA,oGAA4E;AAE5E,MAAqB,qCAAqC;IAGxD,kBAAkB,CAChB,
|
|
1
|
+
{"version":3,"file":"PostgresEntityDatabaseAdapterProvider.js","sourceRoot":"","sources":["../src/PostgresEntityDatabaseAdapterProvider.ts"],"names":[],"mappings":";;;;;AAMA,oGAA4E;AAE5E,MAAqB,qCAAqC;IAGxD,kBAAkB,CAChB,mBAA2D;QAE3D,OAAO,IAAI,uCAA6B,CAAC,mBAAmB,CAAC,CAAC;IAChE,CAAC;CACF;AARD,wDAQC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/entityfields.ts","../src/postgresentitydatabaseadapter.ts","../src/postgresentitydatabaseadapterprovider.ts","../src/postgresentityquerycontextprovider.ts","../src/index.ts","../src/errors/wrapnativepostgrescallasync.ts"],"version":"5.8.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/entity-database-adapter-knex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"description": "Knex database adapter for @expo/entity",
|
|
5
5
|
"files": [
|
|
6
6
|
"build",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"types": "build/index.d.ts",
|
|
11
11
|
"scripts": {
|
|
12
12
|
"tsc": "tsc",
|
|
13
|
+
"build": "tsc -b tsconfig.build.json",
|
|
13
14
|
"clean": "rm -rf build coverage coverage-integration",
|
|
14
15
|
"lint": "eslint src",
|
|
15
16
|
"lint-fix": "eslint src --fix",
|
|
@@ -27,23 +28,24 @@
|
|
|
27
28
|
"author": "Expo",
|
|
28
29
|
"license": "MIT",
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@expo/entity": "^0.
|
|
31
|
+
"@expo/entity": "^0.42.0",
|
|
31
32
|
"knex": "^3.1.0"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
|
-
"@
|
|
35
|
+
"@expo/entity-testing-utils": "^0.42.0",
|
|
36
|
+
"@types/jest": "^29.5.14",
|
|
35
37
|
"@types/node": "^20.14.1",
|
|
36
38
|
"ctix": "^2.7.0",
|
|
37
39
|
"eslint": "^8.57.1",
|
|
38
40
|
"eslint-config-universe": "^14.0.0",
|
|
39
41
|
"eslint-plugin-tsdoc": "^0.3.0",
|
|
40
42
|
"jest": "^29.7.0",
|
|
41
|
-
"pg": "8.
|
|
43
|
+
"pg": "8.14.1",
|
|
42
44
|
"prettier": "^3.3.3",
|
|
43
45
|
"prettier-plugin-organize-imports": "^4.1.0",
|
|
44
|
-
"ts-jest": "^29.
|
|
46
|
+
"ts-jest": "^29.3.1",
|
|
45
47
|
"ts-mockito": "^2.6.1",
|
|
46
|
-
"typescript": "^5.
|
|
48
|
+
"typescript": "^5.8.3"
|
|
47
49
|
},
|
|
48
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "8414d96d948882735687da146e84913397cd8368"
|
|
49
51
|
}
|
package/src/EntityFields.ts
CHANGED
|
@@ -3,7 +3,10 @@ import { EntityFieldDefinition } from '@expo/entity';
|
|
|
3
3
|
/**
|
|
4
4
|
* EntityFieldDefinition for a Postres column with a JS JSON array type.
|
|
5
5
|
*/
|
|
6
|
-
export class JSONArrayField extends EntityFieldDefinition<
|
|
6
|
+
export class JSONArrayField<TRequireExplicitCache extends boolean> extends EntityFieldDefinition<
|
|
7
|
+
any[],
|
|
8
|
+
TRequireExplicitCache
|
|
9
|
+
> {
|
|
7
10
|
protected validateInputValueInternal(value: any[]): boolean {
|
|
8
11
|
return Array.isArray(value);
|
|
9
12
|
}
|
|
@@ -13,7 +16,9 @@ export class JSONArrayField extends EntityFieldDefinition<any[]> {
|
|
|
13
16
|
* EntityFieldDefinition for a Postgres column that may be a JS JSON array type.
|
|
14
17
|
* Does not do any validation.
|
|
15
18
|
*/
|
|
16
|
-
export class MaybeJSONArrayField
|
|
19
|
+
export class MaybeJSONArrayField<
|
|
20
|
+
TRequireExplicitCache extends boolean,
|
|
21
|
+
> extends EntityFieldDefinition<any | any[], TRequireExplicitCache> {
|
|
17
22
|
protected validateInputValueInternal(_value: any): boolean {
|
|
18
23
|
return true;
|
|
19
24
|
}
|
|
@@ -22,7 +27,10 @@ export class MaybeJSONArrayField extends EntityFieldDefinition<any | any[]> {
|
|
|
22
27
|
/**
|
|
23
28
|
* EntityFieldDefinition for a Postgres BIGINT column.
|
|
24
29
|
*/
|
|
25
|
-
export class BigIntField extends EntityFieldDefinition<
|
|
30
|
+
export class BigIntField<TRequireExplicitCache extends boolean> extends EntityFieldDefinition<
|
|
31
|
+
string,
|
|
32
|
+
TRequireExplicitCache
|
|
33
|
+
> {
|
|
26
34
|
protected validateInputValueInternal(value: string): boolean {
|
|
27
35
|
return typeof value === 'string';
|
|
28
36
|
}
|
|
@@ -14,7 +14,8 @@ import wrapNativePostgresCallAsync from './errors/wrapNativePostgresCallAsync';
|
|
|
14
14
|
|
|
15
15
|
export default class PostgresEntityDatabaseAdapter<
|
|
16
16
|
TFields extends Record<string, any>,
|
|
17
|
-
|
|
17
|
+
TIDField extends keyof TFields,
|
|
18
|
+
> extends EntityDatabaseAdapter<TFields, TIDField> {
|
|
18
19
|
protected getFieldTransformerMap(): FieldTransformerMap {
|
|
19
20
|
return new Map<string, FieldTransformer<any>>([
|
|
20
21
|
[
|
|
@@ -44,14 +45,44 @@ export default class PostgresEntityDatabaseAdapter<
|
|
|
44
45
|
protected async fetchManyWhereInternalAsync(
|
|
45
46
|
queryInterface: Knex,
|
|
46
47
|
tableName: string,
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
tableColumns: readonly string[],
|
|
49
|
+
tableTuples: any[][],
|
|
49
50
|
): Promise<object[]> {
|
|
51
|
+
// For single column queries, use the ANY operator to derive a consistent
|
|
52
|
+
// query shape in the postgres query stats table.
|
|
53
|
+
// This produces a query of the form `SELECT * FROM table WHERE ("id") = ANY(?)`
|
|
54
|
+
// with value bindings of the form `[[1]]`, thus not making different value cardinalities
|
|
55
|
+
// produce different query shapes.
|
|
56
|
+
//
|
|
57
|
+
// But for multi-column queries, we must use the IN operator as the ANY operator
|
|
58
|
+
// does not support anonymous composite types. The solution to keep using the ANY operator would be explicit
|
|
59
|
+
// postgres type casting on each value in each tableTuple, thus creating a unique query shape and defeating the purpose.
|
|
60
|
+
// The same applies to using UNNEST on anonymous composite types.
|
|
61
|
+
// Note that this solution is not possible in entity though since we don't have the postgres column types and they
|
|
62
|
+
// can't be derived dynamically.
|
|
63
|
+
//
|
|
64
|
+
// Therefore, for multi-column quries, we use the IN operator which produces a query of the form
|
|
65
|
+
// `SELECT * FROM table WHERE ("id", "name") IN ((?, ?), (?, ?))` with value bindings of the form
|
|
66
|
+
// `[[1, 'a'], [2, 'b']]`, which will produce a unique query shape in the postgres query stats table for
|
|
67
|
+
// each value cardinality.
|
|
68
|
+
//
|
|
69
|
+
// We could use the IN operator for single column queries as well, but we prefer to use ANY to at least keep some
|
|
70
|
+
// consistency in the query shape for the stats table.
|
|
71
|
+
|
|
72
|
+
if (tableColumns.length === 1) {
|
|
73
|
+
return await wrapNativePostgresCallAsync(() =>
|
|
74
|
+
queryInterface
|
|
75
|
+
.select()
|
|
76
|
+
.from(tableName)
|
|
77
|
+
.whereRaw(`(??) = ANY(?)`, [
|
|
78
|
+
tableColumns[0],
|
|
79
|
+
tableTuples.map((tableTuple) => tableTuple[0]),
|
|
80
|
+
]),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
50
84
|
return await wrapNativePostgresCallAsync(() =>
|
|
51
|
-
queryInterface
|
|
52
|
-
.select()
|
|
53
|
-
.from(tableName)
|
|
54
|
-
.whereRaw('?? = ANY(?)', [tableField, tableValues as any[]]),
|
|
85
|
+
queryInterface.select().from(tableName).whereIn(tableColumns, tableTuples),
|
|
55
86
|
);
|
|
56
87
|
}
|
|
57
88
|
|
|
@@ -9,9 +9,9 @@ import PostgresEntityDatabaseAdapter from './PostgresEntityDatabaseAdapter';
|
|
|
9
9
|
export default class PostgresEntityDatabaseAdapterProvider
|
|
10
10
|
implements IEntityDatabaseAdapterProvider
|
|
11
11
|
{
|
|
12
|
-
getDatabaseAdapter<TFields extends Record<string, any
|
|
13
|
-
entityConfiguration: EntityConfiguration<TFields>,
|
|
14
|
-
): EntityDatabaseAdapter<TFields> {
|
|
12
|
+
getDatabaseAdapter<TFields extends Record<string, any>, TIDField extends keyof TFields>(
|
|
13
|
+
entityConfiguration: EntityConfiguration<TFields, TIDField>,
|
|
14
|
+
): EntityDatabaseAdapter<TFields, TIDField> {
|
|
15
15
|
return new PostgresEntityDatabaseAdapter(entityConfiguration);
|
|
16
16
|
}
|
|
17
17
|
}
|