vona-module-a-orm 5.0.83 → 5.0.85
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/cli/databaseDialect/boilerplate/{{sceneName}}.{{beanName}}.ts_ +4 -1
- package/dist/bean/bean.database.d.ts +4 -1
- package/dist/bean/bean.databaseDialectBase.d.ts +8 -2
- package/dist/common/buildWhere.d.ts +2 -1
- package/dist/config/config.d.ts +3 -4
- package/dist/extend/schemaBuilder.d.ts +1 -1
- package/dist/index.js +139 -83
- package/dist/lib/databaseDialect.d.ts +2 -1
- package/dist/service/database.d.ts +1 -2
- package/dist/service/transactionState_.d.ts +4 -4
- package/dist/types/config.d.ts +4 -0
- package/dist/types/database.d.ts +7 -3
- package/dist/types/dialect.d.ts +6 -0
- package/dist/types/onion/databaseDialect.d.ts +2 -0
- package/package.json +3 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { IDecoratorDatabaseDialectOptions } from 'vona-module-a-orm';
|
|
1
2
|
import { BeanDatabaseDialectBase, DatabaseDialect } from 'vona-module-a-orm';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
export interface IDatabaseDialectOptions<%=argv.beanNameCapitalize%> extends IDecoratorDatabaseDialectOptions {}
|
|
5
|
+
|
|
6
|
+
@DatabaseDialect<IDatabaseDialectOptions<%=argv.beanNameCapitalize%>>()
|
|
4
7
|
export class DatabaseDialect<%=argv.beanNameCapitalize%> extends BeanDatabaseDialectBase {}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { FunctionAsync } from 'vona';
|
|
2
2
|
import type { ConfigDatabaseClient } from '../types/config.ts';
|
|
3
|
-
import type { IDatabaseClientRecord, IDbInfo } from '../types/database.ts';
|
|
3
|
+
import type { IDatabaseClientDialectRecord, IDatabaseClientRecord, IDbInfo } from '../types/database.ts';
|
|
4
|
+
import type { BeanDatabaseDialectBase } from './bean.databaseDialectBase.ts';
|
|
4
5
|
import { BeanBase } from 'vona';
|
|
5
6
|
import { ServiceDatabaseClient } from '../service/databaseClient_.ts';
|
|
6
7
|
export declare class BeanDatabase extends BeanBase {
|
|
7
8
|
get current(): import("vona-module-a-orm").ServiceDb;
|
|
8
9
|
getClient(dbInfoOrClientName?: Partial<IDbInfo> | keyof IDatabaseClientRecord, clientConfig?: ConfigDatabaseClient): ServiceDatabaseClient;
|
|
9
10
|
getDb(dbInfoOrClientName?: Partial<IDbInfo> | keyof IDatabaseClientRecord, clientConfig?: ConfigDatabaseClient): import("vona-module-a-orm").ServiceDb;
|
|
11
|
+
getDialect(client: keyof IDatabaseClientDialectRecord): BeanDatabaseDialectBase;
|
|
10
12
|
switchDbIsolate<RESULT>(fn: FunctionAsync<RESULT>, dbInfoOrClientName?: Partial<IDbInfo> | keyof IDatabaseClientRecord): Promise<RESULT>;
|
|
11
13
|
switchDb<RESULT>(fn: FunctionAsync<RESULT>, dbInfoOrClientName?: Partial<IDbInfo> | keyof IDatabaseClientRecord): Promise<RESULT>;
|
|
14
|
+
private _prepareClientConfig;
|
|
12
15
|
}
|
|
@@ -2,18 +2,24 @@ import type { Knex } from 'knex';
|
|
|
2
2
|
import type { TableIdentity } from 'table-identity';
|
|
3
3
|
import type { ITableColumn } from '../types/columns.ts';
|
|
4
4
|
import type { ConfigDatabaseClient } from '../types/config.ts';
|
|
5
|
-
import type { IFetchDatabasesResultItem, IFetchIndexesResultItem } from '../types/dialect.ts';
|
|
5
|
+
import type { IDatabaseDialectCapabilities, IFetchDatabasesResultItem, IFetchIndexesResultItem, TypeDatabaseDialectTableColumnsFn } from '../types/dialect.ts';
|
|
6
6
|
import { BeanBase } from 'vona';
|
|
7
7
|
export declare class BeanDatabaseDialectBase extends BeanBase {
|
|
8
|
+
protected _capabilities?: IDatabaseDialectCapabilities;
|
|
9
|
+
get capabilities(): IDatabaseDialectCapabilities;
|
|
8
10
|
getConfigBase(): ConfigDatabaseClient | undefined;
|
|
9
11
|
fetchDatabases(_schemaBuilder: Knex.SchemaBuilder, _databasePrefix: string): Promise<IFetchDatabasesResultItem[]>;
|
|
10
|
-
createDatabase(_schemaBuilder: Knex.SchemaBuilder, _databaseName: string): Promise<
|
|
12
|
+
createDatabase(_schemaBuilder: Knex.SchemaBuilder, _databaseName: string): Promise<string>;
|
|
11
13
|
dropDatabase(_schemaBuilder: Knex.SchemaBuilder, _databaseName: string): Promise<void>;
|
|
12
14
|
fetchIndexes(_schemaBuilder: Knex.SchemaBuilder, _tableName: string): Promise<IFetchIndexesResultItem[]>;
|
|
13
15
|
insert(_builder: Knex.QueryBuilder, _datas: any[]): Promise<TableIdentity[]>;
|
|
16
|
+
select(_builder: Knex.QueryBuilder, datas: any[], _fn: TypeDatabaseDialectTableColumnsFn): Promise<any[]>;
|
|
14
17
|
query(_result: any): void;
|
|
15
18
|
viewDependents(_builder: Knex.QueryBuilder, _viewName: string): Promise<string[]>;
|
|
16
19
|
coerceColumn(column: Knex.ColumnInfo): ITableColumn;
|
|
20
|
+
protected selectAsSqlite3(_builder: Knex.QueryBuilder, datas: any[], fn: TypeDatabaseDialectTableColumnsFn): Promise<any[]>;
|
|
21
|
+
protected insertAsMysql(builder: Knex.QueryBuilder, datas: any[]): Promise<TableIdentity[]>;
|
|
22
|
+
protected insertAsPg(builder: Knex.QueryBuilder, datas: any[]): Promise<TableIdentity[]>;
|
|
17
23
|
protected _coerceColumnValue(type: string, value: any): any;
|
|
18
24
|
protected _safeNumber(value: any): number | undefined;
|
|
19
25
|
protected _columnTypePrefixes(type: string, prefixes: string[]): boolean;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
+
import type { ServiceDb } from '../service/db_.ts';
|
|
2
3
|
import type { TypeModelWhere } from '../types/modelWhere.ts';
|
|
3
|
-
export declare function buildWhere<TRecord>(
|
|
4
|
+
export declare function buildWhere<TRecord>(db: ServiceDb, builder: Knex.QueryBuilder, wheres: TypeModelWhere<TRecord>, having?: boolean): void;
|
package/dist/config/config.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { TableIdentityType } from 'table-identity';
|
|
2
|
-
import type {
|
|
2
|
+
import type { VonaApplication } from 'vona';
|
|
3
3
|
import type { IOnionOptionsMeta } from 'vona-module-a-onion';
|
|
4
4
|
import type { TSummerCachePreset } from 'vona-module-a-summer';
|
|
5
|
-
import type {
|
|
6
|
-
export type TypeDataBaseConfigDialects = Record<keyof IDatabaseClientDialectRecord, TypeBeanRecordGeneralSelectorKeys<'databaseDialect'>>;
|
|
5
|
+
import type { IDataBaseConfigDialects } from '../types/config.ts';
|
|
7
6
|
export declare function config(_app: VonaApplication): {
|
|
8
7
|
sharding: {
|
|
9
8
|
cache: {
|
|
@@ -34,7 +33,7 @@ export declare function config(_app: VonaApplication): {
|
|
|
34
33
|
enable: boolean;
|
|
35
34
|
expired: number;
|
|
36
35
|
};
|
|
37
|
-
dialects:
|
|
36
|
+
dialects: IDataBaseConfigDialects;
|
|
38
37
|
summer: {
|
|
39
38
|
enable: boolean;
|
|
40
39
|
meta: IOnionOptionsMeta;
|
|
@@ -5,7 +5,7 @@ declare module 'knex' {
|
|
|
5
5
|
namespace Knex {
|
|
6
6
|
interface SchemaBuilder {
|
|
7
7
|
fetchDatabases(databasePrefix: string): Promise<IFetchDatabasesResultItem[]>;
|
|
8
|
-
createDatabase(databaseName: string): Promise<
|
|
8
|
+
createDatabase(databaseName: string): Promise<string>;
|
|
9
9
|
dropDatabase(databaseName: string): Promise<void>;
|
|
10
10
|
fetchIndexes(tableName: string): Promise<IFetchIndexesResultItem[]>;
|
|
11
11
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
|
-
import { BeanInfo, BeanAopMethodBase, BeanBase, deepExtend, appResource,
|
|
2
|
+
import { BeanInfo, BeanAopMethodBase, BeanBase, deepExtend, appResource, beanFullNameFromOnionName, Virtual, cast, useApp, BeanSimple, combineConfigDefault, BeanScopeBase, createBeanDecorator, PickClassInner, $Class } from 'vona';
|
|
3
3
|
import { AopMethod } from 'vona-module-a-aspect';
|
|
4
4
|
import { Service, Bean, Scope } from 'vona-module-a-bean';
|
|
5
5
|
import { AsyncLocalStorage, AsyncResource } from 'node:async_hooks';
|
|
@@ -190,13 +190,6 @@ let ServiceDatabase = (_dec$r = Service(), _dec2$r = BeanInfo({
|
|
|
190
190
|
get configDatabase() {
|
|
191
191
|
return this.app.config.database;
|
|
192
192
|
}
|
|
193
|
-
getDialect(client) {
|
|
194
|
-
if (!client) throw new Error('database dialect not specified');
|
|
195
|
-
const beanFullName = this.scope.config.dialects[client];
|
|
196
|
-
const dialect = this.app.bean._getBean(beanFullName);
|
|
197
|
-
if (!dialect) throw new Error(`database dialect not found: ${client}`);
|
|
198
|
-
return dialect;
|
|
199
|
-
}
|
|
200
193
|
getClientConfig(clientName, original = false) {
|
|
201
194
|
// clientConfig
|
|
202
195
|
let clientConfig = this.configDatabase.clients[clientName];
|
|
@@ -206,7 +199,7 @@ let ServiceDatabase = (_dec$r = Service(), _dec2$r = BeanInfo({
|
|
|
206
199
|
throw new Error(`database config not found: ${clientName}`);
|
|
207
200
|
}
|
|
208
201
|
// configBaseClient
|
|
209
|
-
const dialect = this.
|
|
202
|
+
const dialect = this.bean.database.getDialect(clientConfig.client);
|
|
210
203
|
const configBaseClient = dialect.getConfigBase();
|
|
211
204
|
// combine
|
|
212
205
|
const configBase = this.configDatabase.base;
|
|
@@ -235,7 +228,9 @@ let ServiceDatabase = (_dec$r = Service(), _dec2$r = BeanInfo({
|
|
|
235
228
|
clientName
|
|
236
229
|
};
|
|
237
230
|
}
|
|
238
|
-
prepareClientNameSelector(dbInfo) {
|
|
231
|
+
prepareClientNameSelector(dbInfo, dialect) {
|
|
232
|
+
const dialect2 = typeof dialect === 'string' ? this.bean.database.getDialect(dialect) : dialect;
|
|
233
|
+
if (!dialect2.capabilities.level) return dbInfo.clientName;
|
|
239
234
|
// combine
|
|
240
235
|
return dbInfo.level === 0 ? dbInfo.clientName : `${dbInfo.clientName}:${dbInfo.level}`;
|
|
241
236
|
}
|
|
@@ -390,18 +385,18 @@ let ServiceTransactionState = (_dec$o = Service(), _dec2$o = BeanInfo({
|
|
|
390
385
|
get serviceDatabase() {
|
|
391
386
|
return this.bean._getBean(ServiceDatabase);
|
|
392
387
|
}
|
|
393
|
-
get(
|
|
394
|
-
const selector = this.serviceDatabase.prepareClientNameSelector(
|
|
388
|
+
get(db) {
|
|
389
|
+
const selector = this.serviceDatabase.prepareClientNameSelector(db.info, db.dialect);
|
|
395
390
|
return this._fibers[selector];
|
|
396
391
|
}
|
|
397
|
-
add(
|
|
398
|
-
const selector = this.serviceDatabase.prepareClientNameSelector(
|
|
392
|
+
add(db, connection) {
|
|
393
|
+
const selector = this.serviceDatabase.prepareClientNameSelector(db.info, db.dialect);
|
|
399
394
|
const fiber = this.bean._newBean(ServiceTransactionFiber, connection);
|
|
400
395
|
this._fibers[selector] = fiber;
|
|
401
396
|
return fiber;
|
|
402
397
|
}
|
|
403
|
-
remove(
|
|
404
|
-
const selector = this.serviceDatabase.prepareClientNameSelector(
|
|
398
|
+
remove(db) {
|
|
399
|
+
const selector = this.serviceDatabase.prepareClientNameSelector(db.info, db.dialect);
|
|
405
400
|
delete this._fibers[selector];
|
|
406
401
|
}
|
|
407
402
|
}) || _class$o) || _class$o);
|
|
@@ -447,7 +442,7 @@ let ServiceTransaction = (_dec$m = Service(), _dec2$m = BeanInfo({
|
|
|
447
442
|
return this.bean._getBean(ServiceTransactionAsyncLocalStorage).transactionState;
|
|
448
443
|
}
|
|
449
444
|
get transactionFiber() {
|
|
450
|
-
return this.transactionState.get(this._db
|
|
445
|
+
return this.transactionState.get(this._db);
|
|
451
446
|
}
|
|
452
447
|
get inTransaction() {
|
|
453
448
|
return !!this.transactionFiber;
|
|
@@ -528,7 +523,7 @@ let ServiceTransaction = (_dec$m = Service(), _dec2$m = BeanInfo({
|
|
|
528
523
|
if (!this.inTransaction) {
|
|
529
524
|
const connection = this._db.client.connection;
|
|
530
525
|
const transactionConnection = await connection.transaction(_translateTransactionOptions(options));
|
|
531
|
-
fiber = this.transactionState.add(this._db
|
|
526
|
+
fiber = this.transactionState.add(this._db, transactionConnection);
|
|
532
527
|
}
|
|
533
528
|
// fn
|
|
534
529
|
try {
|
|
@@ -536,19 +531,19 @@ let ServiceTransaction = (_dec$m = Service(), _dec2$m = BeanInfo({
|
|
|
536
531
|
} catch (err) {
|
|
537
532
|
if (fiber) {
|
|
538
533
|
await fiber.doRollback();
|
|
539
|
-
this.transactionState.remove(this._db
|
|
534
|
+
this.transactionState.remove(this._db);
|
|
540
535
|
}
|
|
541
536
|
throw err;
|
|
542
537
|
}
|
|
543
538
|
try {
|
|
544
539
|
if (fiber) {
|
|
545
540
|
await fiber.doCommit();
|
|
546
|
-
this.transactionState.remove(this._db
|
|
541
|
+
this.transactionState.remove(this._db);
|
|
547
542
|
}
|
|
548
543
|
} catch (err) {
|
|
549
544
|
if (fiber) {
|
|
550
545
|
await fiber.doRollback();
|
|
551
|
-
this.transactionState.remove(this._db
|
|
546
|
+
this.transactionState.remove(this._db);
|
|
552
547
|
}
|
|
553
548
|
throw err;
|
|
554
549
|
}
|
|
@@ -613,7 +608,7 @@ let ServiceDb = (_dec$l = Service(), _dec2$l = BeanInfo({
|
|
|
613
608
|
return this.client.clientConfig.client;
|
|
614
609
|
}
|
|
615
610
|
get dialect() {
|
|
616
|
-
return this.
|
|
611
|
+
return this.bean.database.getDialect(this.dialectName);
|
|
617
612
|
}
|
|
618
613
|
async commit(cb, options) {
|
|
619
614
|
return await this.transaction.commit(cb, options);
|
|
@@ -680,8 +675,8 @@ let ServiceDatabaseClient = (_dec$k = Service(), _dec2$k = BeanInfo({
|
|
|
680
675
|
const dbInfo = this.scope.service.database.parseClientNameSelector(clientNameSelector);
|
|
681
676
|
this.level = dbInfo.level;
|
|
682
677
|
this.clientName = dbInfo.clientName;
|
|
683
|
-
// config
|
|
684
|
-
this.clientConfig = clientConfig
|
|
678
|
+
// config: inited by bean.database.getClient
|
|
679
|
+
this.clientConfig = clientConfig;
|
|
685
680
|
// knex
|
|
686
681
|
this._knex = knex(this.clientConfig);
|
|
687
682
|
}
|
|
@@ -704,9 +699,9 @@ let ServiceDatabaseClient = (_dec$k = Service(), _dec2$k = BeanInfo({
|
|
|
704
699
|
_prepareDatabaseName(databaseName) {
|
|
705
700
|
const result = {};
|
|
706
701
|
const connection = this.clientConfig.connection;
|
|
707
|
-
if (connection.database) {
|
|
702
|
+
if (connection.database !== undefined) {
|
|
708
703
|
result.database = databaseName;
|
|
709
|
-
} else if (connection.filename) {
|
|
704
|
+
} else if (connection.filename !== undefined) {
|
|
710
705
|
result.filename = databaseName;
|
|
711
706
|
}
|
|
712
707
|
return result;
|
|
@@ -737,16 +732,26 @@ let BeanDatabase = (_dec$j = Bean(), _dec2$j = BeanInfo({
|
|
|
737
732
|
}
|
|
738
733
|
getClient(dbInfoOrClientName, clientConfig) {
|
|
739
734
|
const dbInfo = this.scope.service.database.prepareDbInfo(dbInfoOrClientName);
|
|
740
|
-
const
|
|
741
|
-
|
|
735
|
+
const clientConfigReal = this._prepareClientConfig(dbInfo.clientName, clientConfig);
|
|
736
|
+
const selector = this.scope.service.database.prepareClientNameSelector(dbInfo, clientConfigReal.client);
|
|
737
|
+
return this.app.bean._getBeanSelector(ServiceDatabaseClient, selector, clientConfigReal);
|
|
742
738
|
}
|
|
743
739
|
getDb(dbInfoOrClientName, clientConfig) {
|
|
744
740
|
return this.getClient(dbInfoOrClientName, clientConfig).db;
|
|
745
741
|
}
|
|
742
|
+
getDialect(client) {
|
|
743
|
+
if (!client) throw new Error('database dialect not specified');
|
|
744
|
+
const beanFullName = beanFullNameFromOnionName(this.scope.config.dialects[client], 'databaseDialect');
|
|
745
|
+
const dialect = this.app.bean._getBean(beanFullName);
|
|
746
|
+
if (!dialect) throw new Error(`database dialect not found: ${client}`);
|
|
747
|
+
return dialect;
|
|
748
|
+
}
|
|
746
749
|
async switchDbIsolate(fn, dbInfoOrClientName) {
|
|
747
750
|
const dbInfo = this.scope.service.database.prepareDbInfo(dbInfoOrClientName);
|
|
751
|
+
// const level = this.app.config.database.defaultClient === 'sqlite3' ? dbInfo.level : dbInfo.level + 1;
|
|
752
|
+
const level = dbInfo.level + 1;
|
|
748
753
|
return this.switchDb(fn, {
|
|
749
|
-
level
|
|
754
|
+
level,
|
|
750
755
|
clientName: dbInfo.clientName
|
|
751
756
|
});
|
|
752
757
|
}
|
|
@@ -761,12 +766,25 @@ let BeanDatabase = (_dec$j = Bean(), _dec2$j = BeanInfo({
|
|
|
761
766
|
return this.bean._getBean(ServiceTransactionAsyncLocalStorage).run(fn);
|
|
762
767
|
});
|
|
763
768
|
}
|
|
769
|
+
|
|
770
|
+
// only for bean.database.getClient
|
|
771
|
+
_prepareClientConfig(clientName, clientConfig) {
|
|
772
|
+
return clientConfig ? deepExtend({}, clientConfig) : this.scope.service.database.getClientConfig(clientName);
|
|
773
|
+
}
|
|
764
774
|
}) || _class$j) || _class$j);
|
|
765
775
|
|
|
766
776
|
var _dec$i, _dec2$i, _dec3$7, _class$i;
|
|
767
777
|
let BeanDatabaseDialectBase = (_dec$i = Bean(), _dec2$i = Virtual(), _dec3$7 = BeanInfo({
|
|
768
778
|
module: "a-orm"
|
|
769
779
|
}), _dec$i(_class$i = _dec2$i(_class$i = _dec3$7(_class$i = class BeanDatabaseDialectBase extends BeanBase {
|
|
780
|
+
constructor(...args) {
|
|
781
|
+
super(...args);
|
|
782
|
+
this._capabilities = void 0;
|
|
783
|
+
}
|
|
784
|
+
get capabilities() {
|
|
785
|
+
if (!this._capabilities) throw new Error('Should provide dialect capabilities');
|
|
786
|
+
return this._capabilities;
|
|
787
|
+
}
|
|
770
788
|
getConfigBase() {
|
|
771
789
|
return undefined;
|
|
772
790
|
}
|
|
@@ -785,6 +803,9 @@ let BeanDatabaseDialectBase = (_dec$i = Bean(), _dec2$i = Virtual(), _dec3$7 = B
|
|
|
785
803
|
async insert(_builder, _datas) {
|
|
786
804
|
throw new Error('Not Implemented');
|
|
787
805
|
}
|
|
806
|
+
async select(_builder, datas, _fn) {
|
|
807
|
+
return datas;
|
|
808
|
+
}
|
|
788
809
|
query(_result) {
|
|
789
810
|
throw new Error('Not Implemented');
|
|
790
811
|
}
|
|
@@ -801,6 +822,51 @@ let BeanDatabaseDialectBase = (_dec$i = Bean(), _dec2$i = Virtual(), _dec3$7 = B
|
|
|
801
822
|
// ok
|
|
802
823
|
return result;
|
|
803
824
|
}
|
|
825
|
+
async selectAsSqlite3(_builder, datas, fn) {
|
|
826
|
+
const columns = await fn();
|
|
827
|
+
// data
|
|
828
|
+
for (const data of datas) {
|
|
829
|
+
for (const columnName in columns) {
|
|
830
|
+
const column = columns[columnName];
|
|
831
|
+
if (Object.prototype.hasOwnProperty.call(data, columnName)) {
|
|
832
|
+
const value = data[columnName];
|
|
833
|
+
if (column.type === 'json' && value !== undefined && typeof value === 'string') {
|
|
834
|
+
data[columnName] = JSON.parse(value);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return datas;
|
|
840
|
+
}
|
|
841
|
+
async insertAsMysql(builder, datas) {
|
|
842
|
+
if (datas.length === 0) return [];
|
|
843
|
+
if (isNil(datas[0].id)) {
|
|
844
|
+
const ids = [];
|
|
845
|
+
for (const data of datas) {
|
|
846
|
+
const builder2 = builder.clone();
|
|
847
|
+
builder2.insert(data);
|
|
848
|
+
const items = await builder2;
|
|
849
|
+
ids.push(items[0]);
|
|
850
|
+
}
|
|
851
|
+
return ids;
|
|
852
|
+
} else {
|
|
853
|
+
builder.insert(datas);
|
|
854
|
+
await builder;
|
|
855
|
+
return datas.map(item => item.id);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
async insertAsPg(builder, datas) {
|
|
859
|
+
if (datas.length === 0) return [];
|
|
860
|
+
if (isNil(datas[0].id)) {
|
|
861
|
+
builder.insert(datas).returning('id');
|
|
862
|
+
const items = await builder;
|
|
863
|
+
return items.map(item => item.id);
|
|
864
|
+
} else {
|
|
865
|
+
builder.insert(datas);
|
|
866
|
+
await builder;
|
|
867
|
+
return datas.map(item => item.id);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
804
870
|
_coerceColumnValue(type, value) {
|
|
805
871
|
// null
|
|
806
872
|
if (isNil(value)) return undefined;
|
|
@@ -934,10 +1000,10 @@ function getClassEntityFromClassModel(modelClass) {
|
|
|
934
1000
|
// return arr;
|
|
935
1001
|
// }
|
|
936
1002
|
|
|
937
|
-
function buildWhere(
|
|
938
|
-
_buildWhereInner(having,
|
|
1003
|
+
function buildWhere(db, builder, wheres, having = false) {
|
|
1004
|
+
_buildWhereInner(having, db, builder, wheres);
|
|
939
1005
|
}
|
|
940
|
-
function _buildWhereInner(having,
|
|
1006
|
+
function _buildWhereInner(having, db, builder, wheres, column) {
|
|
941
1007
|
// skip
|
|
942
1008
|
if (wheres === Op.skip) {
|
|
943
1009
|
return;
|
|
@@ -952,22 +1018,22 @@ function _buildWhereInner(having, knex, builder, wheres, column) {
|
|
|
952
1018
|
const value = wheres[key];
|
|
953
1019
|
if (key[0] !== '_') {
|
|
954
1020
|
// columns
|
|
955
|
-
_buildWhereColumn(having,
|
|
1021
|
+
_buildWhereColumn(having, db, builder, key, value);
|
|
956
1022
|
} else if (OpNormalValues.includes(key)) {
|
|
957
1023
|
// op: normal
|
|
958
1024
|
if (column) {
|
|
959
|
-
_buildWhereColumn(having,
|
|
1025
|
+
_buildWhereColumn(having, db, builder, column, value, key);
|
|
960
1026
|
}
|
|
961
1027
|
} else {
|
|
962
1028
|
const op = _checkOpJoint(key);
|
|
963
1029
|
if (op) {
|
|
964
1030
|
// op: joint
|
|
965
|
-
_buildWhereOpJoint(having,
|
|
1031
|
+
_buildWhereOpJoint(having, db, builder, column, value, op);
|
|
966
1032
|
}
|
|
967
1033
|
}
|
|
968
1034
|
}
|
|
969
1035
|
}
|
|
970
|
-
function _buildWhereOpJoint(having,
|
|
1036
|
+
function _buildWhereOpJoint(having, db, builder, column, wheres, op) {
|
|
971
1037
|
// skip
|
|
972
1038
|
if (wheres === Op.skip) {
|
|
973
1039
|
return;
|
|
@@ -977,7 +1043,7 @@ function _buildWhereOpJoint(having, knex, builder, column, wheres, op) {
|
|
|
977
1043
|
builder[having ? 'having' : 'where'](builder => {
|
|
978
1044
|
for (const key in wheres) {
|
|
979
1045
|
builder.andWhere(builder => {
|
|
980
|
-
_buildWhereInner(false,
|
|
1046
|
+
_buildWhereInner(false, db, builder, {
|
|
981
1047
|
[key]: wheres[key]
|
|
982
1048
|
}, column);
|
|
983
1049
|
});
|
|
@@ -990,7 +1056,7 @@ function _buildWhereOpJoint(having, knex, builder, column, wheres, op) {
|
|
|
990
1056
|
builder[having ? 'having' : 'where'](builder => {
|
|
991
1057
|
for (const key in wheres) {
|
|
992
1058
|
builder.orWhere(builder => {
|
|
993
|
-
_buildWhereInner(false,
|
|
1059
|
+
_buildWhereInner(false, db, builder, {
|
|
994
1060
|
[key]: wheres[key]
|
|
995
1061
|
}, column);
|
|
996
1062
|
});
|
|
@@ -1001,7 +1067,7 @@ function _buildWhereOpJoint(having, knex, builder, column, wheres, op) {
|
|
|
1001
1067
|
// not
|
|
1002
1068
|
if (op === Op.not) {
|
|
1003
1069
|
builder[having ? 'havingNot' : 'whereNot'](builder => {
|
|
1004
|
-
_buildWhereInner(false,
|
|
1070
|
+
_buildWhereInner(false, db, builder, wheres, column);
|
|
1005
1071
|
});
|
|
1006
1072
|
return;
|
|
1007
1073
|
}
|
|
@@ -1015,59 +1081,52 @@ function _buildWhereOpJoint(having, knex, builder, column, wheres, op) {
|
|
|
1015
1081
|
builder[having ? 'havingNotExists' : 'whereNotExists'](wheres);
|
|
1016
1082
|
}
|
|
1017
1083
|
}
|
|
1018
|
-
function _buildWhereColumn(having,
|
|
1084
|
+
function _buildWhereColumn(having, db, builder, column, value, op) {
|
|
1019
1085
|
// skip
|
|
1020
1086
|
if (value === Op.skip) {
|
|
1021
1087
|
return;
|
|
1022
1088
|
}
|
|
1023
1089
|
// raw
|
|
1024
1090
|
if (isRaw(value) || isRef(value)) {
|
|
1025
|
-
_buildWhereColumnOpNormal(having,
|
|
1091
|
+
_buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.eq);
|
|
1026
1092
|
return;
|
|
1027
1093
|
}
|
|
1028
1094
|
// null/undefined
|
|
1029
1095
|
if (isNil(value)) {
|
|
1030
|
-
_buildWhereColumnOpNormal(having,
|
|
1096
|
+
_buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.is);
|
|
1031
1097
|
return;
|
|
1032
1098
|
}
|
|
1033
1099
|
// array
|
|
1034
1100
|
if (Array.isArray(value)) {
|
|
1035
|
-
_buildWhereColumnOpNormal(having,
|
|
1101
|
+
_buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.in);
|
|
1036
1102
|
return;
|
|
1037
1103
|
}
|
|
1038
1104
|
// date
|
|
1039
1105
|
if (value instanceof Date) {
|
|
1040
|
-
_buildWhereColumnOpNormal(having,
|
|
1106
|
+
_buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.eq);
|
|
1041
1107
|
return;
|
|
1042
1108
|
}
|
|
1043
1109
|
// object
|
|
1044
1110
|
if (typeof value === 'object') {
|
|
1045
1111
|
builder[having ? 'having' : 'where'](builder => {
|
|
1046
|
-
_buildWhereInner(false,
|
|
1112
|
+
_buildWhereInner(false, db, builder, value, column);
|
|
1047
1113
|
});
|
|
1048
1114
|
return;
|
|
1049
1115
|
}
|
|
1050
1116
|
// column
|
|
1051
|
-
_buildWhereColumnOpNormal(having,
|
|
1117
|
+
_buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.eq);
|
|
1052
1118
|
}
|
|
1053
|
-
function _buildWhereColumnOpNormal(having,
|
|
1054
|
-
column = _checkHavingColumn(
|
|
1055
|
-
if (_shouldPatchLike(knex)) {
|
|
1056
|
-
if (op === Op.startsWith) op = Op.startsWithI;
|
|
1057
|
-
if (op === Op.endsWith) op = Op.endsWithI;
|
|
1058
|
-
if (op === Op.includes) op = Op.includesI;
|
|
1059
|
-
if (op === Op.eqI) op = Op.eq;
|
|
1060
|
-
if (op === Op.notEqI) op = Op.notEq;
|
|
1061
|
-
}
|
|
1119
|
+
function _buildWhereColumnOpNormal(having, db, builder, column, value, op) {
|
|
1120
|
+
column = _checkHavingColumn(db, column);
|
|
1062
1121
|
if (op === Op.eq) {
|
|
1063
1122
|
builder[having ? 'having' : 'where'](column, '=', value);
|
|
1064
1123
|
} else if (op === Op.notEq) {
|
|
1065
1124
|
builder[having ? 'having' : 'where'](column, '<>', value);
|
|
1066
1125
|
} else if (op === Op.eqI) {
|
|
1067
|
-
builder[having
|
|
1126
|
+
builder[_getOpILikeReal(having, db)](column, value);
|
|
1068
1127
|
} else if (op === Op.notEqI) {
|
|
1069
1128
|
builder[having ? 'havingNot' : 'whereNot'](builder => {
|
|
1070
|
-
builder[having
|
|
1129
|
+
builder[_getOpILikeReal(having, db)](column, value);
|
|
1071
1130
|
});
|
|
1072
1131
|
} else if (op === Op.gt) {
|
|
1073
1132
|
builder[having ? 'having' : 'where'](column, '>', value);
|
|
@@ -1096,27 +1155,23 @@ function _buildWhereColumnOpNormal(having, knex, builder, column, value, op) {
|
|
|
1096
1155
|
} else if (op === Op.includes) {
|
|
1097
1156
|
builder[having ? 'havingLike' : 'whereLike'](column, `%${value}%`);
|
|
1098
1157
|
} else if (op === Op.startsWithI) {
|
|
1099
|
-
builder[having
|
|
1158
|
+
builder[_getOpILikeReal(having, db)](column, `${value}%`);
|
|
1100
1159
|
} else if (op === Op.endsWithI) {
|
|
1101
|
-
builder[having
|
|
1160
|
+
builder[_getOpILikeReal(having, db)](column, `%${value}`);
|
|
1102
1161
|
} else if (op === Op.includesI) {
|
|
1103
|
-
builder[having
|
|
1162
|
+
builder[_getOpILikeReal(having, db)](column, `%${value}%`);
|
|
1104
1163
|
} else if (op === Op.ref) {
|
|
1105
|
-
builder[having ? 'having' : 'where'](column, '=',
|
|
1164
|
+
builder[having ? 'having' : 'where'](column, '=', db.connection.ref(value));
|
|
1106
1165
|
}
|
|
1107
1166
|
}
|
|
1108
|
-
function
|
|
1109
|
-
|
|
1110
|
-
return dialectName === 'mysql' || dialectName === 'mysql2';
|
|
1111
|
-
}
|
|
1112
|
-
function _getDialectName(knex) {
|
|
1113
|
-
return knex.client.config.client;
|
|
1167
|
+
function _getOpILikeReal(having, db) {
|
|
1168
|
+
return db.dialect.capabilities.ilike ? having ? 'havingILike' : 'whereILike' : having ? 'havingLike' : 'whereLike';
|
|
1114
1169
|
}
|
|
1115
|
-
function _checkHavingColumn(
|
|
1170
|
+
function _checkHavingColumn(db, column) {
|
|
1116
1171
|
let [aggr, name] = cast(column).split('_');
|
|
1117
1172
|
if (!OpAggrs.includes(aggr) || !name) return column;
|
|
1118
1173
|
if (aggr === 'count' && name === 'all') name = '*';
|
|
1119
|
-
return
|
|
1174
|
+
return db.connection.raw(`${_safeOp(aggr)}(${_safeColumn(name)})`);
|
|
1120
1175
|
}
|
|
1121
1176
|
function _checkOpJoint(op) {
|
|
1122
1177
|
for (const item of OpJointValues) {
|
|
@@ -1589,7 +1644,7 @@ class BeanModelUtils extends BeanModelMeta {
|
|
|
1589
1644
|
|
|
1590
1645
|
buildWhere(builder, wheres) {
|
|
1591
1646
|
if (!wheres) return;
|
|
1592
|
-
return buildWhere(this.
|
|
1647
|
+
return buildWhere(this.db, builder, wheres);
|
|
1593
1648
|
}
|
|
1594
1649
|
buildJoin(builder, join) {
|
|
1595
1650
|
if (!join) return;
|
|
@@ -1677,7 +1732,7 @@ class BeanModelUtils extends BeanModelMeta {
|
|
|
1677
1732
|
this.buildHaving(builder, having);
|
|
1678
1733
|
}
|
|
1679
1734
|
buildHaving(builder, having) {
|
|
1680
|
-
return buildWhere(this.
|
|
1735
|
+
return buildWhere(this.db, builder, having, true);
|
|
1681
1736
|
}
|
|
1682
1737
|
prepareWhere(builder, table, where, options) {
|
|
1683
1738
|
// table
|
|
@@ -1958,7 +2013,9 @@ class BeanModelCrudInner extends BeanModelView {
|
|
|
1958
2013
|
builder = builder ?? this._select_buildParams(table, params, options);
|
|
1959
2014
|
// ready
|
|
1960
2015
|
this.$loggerChild('model').debug(() => `model.select: ${builder.toQuery()}`);
|
|
1961
|
-
|
|
2016
|
+
// datas
|
|
2017
|
+
const datas = await builder;
|
|
2018
|
+
return await this.dialect.select(builder, datas, () => this.columns(table));
|
|
1962
2019
|
}
|
|
1963
2020
|
_select_buildParams(table, params, options) {
|
|
1964
2021
|
// builder
|
|
@@ -3001,10 +3058,9 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
3001
3058
|
const cache = this.cacheEntity.getInstance(table);
|
|
3002
3059
|
let items = await cache.mget(ids, {
|
|
3003
3060
|
mget: async ids => {
|
|
3004
|
-
|
|
3061
|
+
return await super._mget_original(table, ids, {
|
|
3005
3062
|
disableDeleted: true
|
|
3006
3063
|
});
|
|
3007
|
-
return items.map(item => item === undefined ? null : item);
|
|
3008
3064
|
},
|
|
3009
3065
|
db: this.db
|
|
3010
3066
|
});
|
|
@@ -3331,14 +3387,13 @@ class BeanModelCache extends BeanModelCrud {
|
|
|
3331
3387
|
const item = await cache.get(id, {
|
|
3332
3388
|
get: async () => {
|
|
3333
3389
|
// where: maybe contain aux key
|
|
3334
|
-
|
|
3390
|
+
return await super._get(table, where, {
|
|
3335
3391
|
disableDeleted: true
|
|
3336
3392
|
});
|
|
3337
|
-
return item === undefined ? null : item;
|
|
3338
3393
|
},
|
|
3339
3394
|
db: this.db
|
|
3340
3395
|
});
|
|
3341
|
-
if (!item || !this._checkIfEntityValidByDeleted(item, options)) return
|
|
3396
|
+
if (!item || !this._checkIfEntityValidByDeleted(item, options)) return undefined;
|
|
3342
3397
|
return item;
|
|
3343
3398
|
}
|
|
3344
3399
|
__filterMGetColumns(items, columns) {
|
|
@@ -3720,9 +3775,10 @@ function config(_app) {
|
|
|
3720
3775
|
expired: 14 * 24 * 3600 * 1000
|
|
3721
3776
|
},
|
|
3722
3777
|
dialects: {
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3778
|
+
'better-sqlite3': 'a-ormdialect:betterSqlite3',
|
|
3779
|
+
'mysql': 'a-ormdialect:mysql',
|
|
3780
|
+
'mysql2': 'a-ormdialect:mysql3',
|
|
3781
|
+
'pg': 'a-ormdialect:pg'
|
|
3726
3782
|
},
|
|
3727
3783
|
summer: {
|
|
3728
3784
|
enable: true,
|
|
@@ -3765,7 +3821,7 @@ function ExtendSchemaBuilder(app) {
|
|
|
3765
3821
|
['fetchDatabases', 'createDatabase', 'dropDatabase', 'fetchIndexes'].forEach(method => {
|
|
3766
3822
|
knex.SchemaBuilder.extend(method, async function (...args) {
|
|
3767
3823
|
const client = cast(cast(this).client).config.client;
|
|
3768
|
-
const dialect = app.
|
|
3824
|
+
const dialect = app.bean.database.getDialect(client);
|
|
3769
3825
|
return await dialect[method](this, ...args);
|
|
3770
3826
|
});
|
|
3771
3827
|
});
|
|
@@ -3913,8 +3969,8 @@ function $locale(key) {
|
|
|
3913
3969
|
}
|
|
3914
3970
|
/** scope: end */
|
|
3915
3971
|
|
|
3916
|
-
function DatabaseDialect() {
|
|
3917
|
-
return createBeanDecorator('databaseDialect');
|
|
3972
|
+
function DatabaseDialect(options) {
|
|
3973
|
+
return createBeanDecorator('databaseDialect', options);
|
|
3918
3974
|
}
|
|
3919
3975
|
|
|
3920
3976
|
function DtoAggregate(modelLike, aggrs) {
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { IDecoratorDatabaseDialectOptions } from '../types/index.ts';
|
|
2
|
+
export declare function DatabaseDialect<T extends IDecoratorDatabaseDialectOptions>(options?: T): ClassDecorator;
|
|
@@ -4,10 +4,9 @@ import type { IDatabaseClientDialectRecord, IDatabaseClientRecord, IDbInfo } fro
|
|
|
4
4
|
import { BeanBase } from 'vona';
|
|
5
5
|
export declare class ServiceDatabase extends BeanBase {
|
|
6
6
|
get configDatabase(): import("../types/config.ts").ConfigDatabase;
|
|
7
|
-
getDialect(client: keyof IDatabaseClientDialectRecord): BeanDatabaseDialectBase;
|
|
8
7
|
getClientConfig(clientName: keyof IDatabaseClientRecord, original?: boolean): ConfigDatabaseClient;
|
|
9
8
|
prepareDbInfo(dbInfoOrClientName?: Partial<IDbInfo> | keyof IDatabaseClientRecord): IDbInfo;
|
|
10
|
-
prepareClientNameSelector(dbInfo: IDbInfo): string;
|
|
9
|
+
prepareClientNameSelector(dbInfo: IDbInfo, dialect: BeanDatabaseDialectBase | keyof IDatabaseClientDialectRecord): string;
|
|
11
10
|
parseClientNameSelector(clientNameSelector: string): IDbInfo;
|
|
12
11
|
prepareClientName(clientName?: keyof IDatabaseClientRecord): keyof IDatabaseClientRecord;
|
|
13
12
|
getDefaultClientName(): keyof IDatabaseClientRecord;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type knex from 'knex';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ServiceDb } from './db_.ts';
|
|
3
3
|
import { BeanBase } from 'vona';
|
|
4
4
|
import { ServiceTransactionFiber } from './transactionFiber_.ts';
|
|
5
5
|
export declare class ServiceTransactionState extends BeanBase {
|
|
6
6
|
private _fibers;
|
|
7
7
|
private get serviceDatabase();
|
|
8
|
-
get(
|
|
9
|
-
add(
|
|
10
|
-
remove(
|
|
8
|
+
get(db: ServiceDb): ServiceTransactionFiber | undefined;
|
|
9
|
+
add(db: ServiceDb, connection: knex.Knex.Transaction): ServiceTransactionFiber;
|
|
10
|
+
remove(db: ServiceDb): void;
|
|
11
11
|
}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
2
|
import type { VonaContext } from 'vona';
|
|
3
3
|
import type { IDatabaseClientDialectRecord, IDatabaseClientRecord } from './database.ts';
|
|
4
|
+
import type { IDatabaseDialectRecord } from './onion/databaseDialect.ts';
|
|
4
5
|
export type TypeDefaultClientNameFn = (ctx?: VonaContext) => keyof IDatabaseClientRecord;
|
|
5
6
|
export type TypeDefaultClientName = TypeDefaultClientNameFn | keyof IDatabaseClientRecord;
|
|
6
7
|
export interface ConfigDatabaseClient extends Omit<Knex.Config, 'client'> {
|
|
@@ -12,3 +13,6 @@ export interface ConfigDatabase {
|
|
|
12
13
|
clients: Record<keyof IDatabaseClientRecord, ConfigDatabaseClient>;
|
|
13
14
|
base: ConfigDatabaseClient;
|
|
14
15
|
}
|
|
16
|
+
export type IDataBaseConfigDialects = {
|
|
17
|
+
[KEY in keyof IDatabaseClientDialectRecord]: keyof IDatabaseDialectRecord;
|
|
18
|
+
};
|
package/dist/types/database.d.ts
CHANGED
|
@@ -8,13 +8,15 @@ export interface IDbInfo {
|
|
|
8
8
|
}
|
|
9
9
|
export interface IDatabaseClientRecord {
|
|
10
10
|
default: never;
|
|
11
|
+
sqlite3: never;
|
|
11
12
|
pg: never;
|
|
12
13
|
mysql: never;
|
|
13
14
|
}
|
|
14
15
|
export interface IDatabaseClientDialectRecord {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
'better-sqlite3': never;
|
|
17
|
+
'pg': never;
|
|
18
|
+
'mysql': never;
|
|
19
|
+
'mysql2': never;
|
|
18
20
|
}
|
|
19
21
|
export interface IDatabaseSwitchOptions {
|
|
20
22
|
clientName?: keyof IDatabaseClientRecord;
|
|
@@ -33,6 +35,8 @@ declare module 'vona' {
|
|
|
33
35
|
}
|
|
34
36
|
interface VonaConfigEnv {
|
|
35
37
|
DATABASE_DEFAULT_CLIENT: string | undefined;
|
|
38
|
+
DATABASE_CLIENT_SQLITE3_FILENAME: string | undefined;
|
|
39
|
+
DATABASE_CLIENT_SQLITE3_NATIVEBINDING: string | undefined;
|
|
36
40
|
DATABASE_CLIENT_PG_HOST: string | undefined;
|
|
37
41
|
DATABASE_CLIENT_PG_PORT: string | undefined;
|
|
38
42
|
DATABASE_CLIENT_PG_USER: string | undefined;
|
package/dist/types/dialect.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import type { ITableColumns } from './columns.ts';
|
|
1
2
|
export interface IFetchDatabasesResultItem {
|
|
2
3
|
name: string;
|
|
3
4
|
}
|
|
4
5
|
export interface IFetchIndexesResultItem {
|
|
5
6
|
indexName: string;
|
|
6
7
|
}
|
|
8
|
+
export type TypeDatabaseDialectTableColumnsFn = () => Promise<ITableColumns>;
|
|
9
|
+
export interface IDatabaseDialectCapabilities {
|
|
10
|
+
ilike: boolean;
|
|
11
|
+
level: boolean;
|
|
12
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { OmitNever } from 'vona';
|
|
1
2
|
import type { ServiceOnion } from 'vona-module-a-onion';
|
|
2
3
|
export interface IDatabaseDialectRecord {
|
|
3
4
|
}
|
|
@@ -10,6 +11,7 @@ declare module 'vona-module-a-onion' {
|
|
|
10
11
|
}
|
|
11
12
|
declare module 'vona' {
|
|
12
13
|
interface ConfigOnions {
|
|
14
|
+
databaseDialect: OmitNever<IDatabaseDialectRecord>;
|
|
13
15
|
}
|
|
14
16
|
interface IBeanSceneRecord {
|
|
15
17
|
databaseDialect: never;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vona-module-a-orm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.85",
|
|
5
5
|
"title": "a-orm",
|
|
6
6
|
"vonaModule": {
|
|
7
7
|
"capabilities": {
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"databaseDialect": {
|
|
35
35
|
"beanGeneral": true,
|
|
36
|
+
"optionsGlobalInterfaceName": "IDecoratorDatabaseDialectOptions",
|
|
37
|
+
"optionsGlobalInterfaceFrom": "vona-module-a-orm",
|
|
36
38
|
"boilerplate": "cli/databaseDialect/boilerplate"
|
|
37
39
|
}
|
|
38
40
|
}
|