af-db-ts 1.0.2
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/README.md +3 -0
- package/dist/cjs/db.js +199 -0
- package/dist/cjs/db.js.map +1 -0
- package/dist/cjs/get-value-for-sql.js +256 -0
- package/dist/cjs/get-value-for-sql.js.map +1 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/interfaces.js +3 -0
- package/dist/cjs/interfaces.js.map +1 -0
- package/dist/cjs/sql.js +375 -0
- package/dist/cjs/sql.js.map +1 -0
- package/dist/cjs/utils.js +36 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/db.js +185 -0
- package/dist/esm/db.js.map +1 -0
- package/dist/esm/get-value-for-sql.js +251 -0
- package/dist/esm/get-value-for-sql.js.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interfaces.js +2 -0
- package/dist/esm/interfaces.js.map +1 -0
- package/dist/esm/sql.js +361 -0
- package/dist/esm/sql.js.map +1 -0
- package/dist/esm/utils.js +31 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/types/db.d.ts +39 -0
- package/dist/types/db.d.ts.map +1 -0
- package/dist/types/get-value-for-sql.d.ts +7 -0
- package/dist/types/get-value-for-sql.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/interfaces.d.ts +181 -0
- package/dist/types/interfaces.d.ts.map +1 -0
- package/dist/types/sql.d.ts +56 -0
- package/dist/types/sql.d.ts.map +1 -0
- package/dist/types/utils.d.ts +10 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +75 -0
- package/src/db.ts +195 -0
- package/src/get-value-for-sql.ts +271 -0
- package/src/index.ts +47 -0
- package/src/interfaces.ts +232 -0
- package/src/sql.ts +403 -0
- package/src/utils.ts +31 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Оборачивает строку в одинарные кавычки, если второй аргумент не true
|
|
3
|
+
*/
|
|
4
|
+
export const q = (val, noQuotes) => (noQuotes ? val : `'${val}'`);
|
|
5
|
+
/**
|
|
6
|
+
* Экранирование одинарной кавычки и символа % для использования строки в SQL запросе
|
|
7
|
+
* onlySingleQuotes - true - не экранировать %
|
|
8
|
+
*/
|
|
9
|
+
export const mssqlEscape = (str, onlySingleQuotes = false) => {
|
|
10
|
+
if (str == null) {
|
|
11
|
+
str = '';
|
|
12
|
+
}
|
|
13
|
+
switch (typeof str) {
|
|
14
|
+
case 'number':
|
|
15
|
+
str = String(str);
|
|
16
|
+
break;
|
|
17
|
+
case 'string':
|
|
18
|
+
break;
|
|
19
|
+
case 'boolean':
|
|
20
|
+
str = str ? '1' : '0';
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
str = String(str || '');
|
|
24
|
+
}
|
|
25
|
+
str = str.replace(/'/g, `''`);
|
|
26
|
+
if (onlySingleQuotes) {
|
|
27
|
+
return str;
|
|
28
|
+
}
|
|
29
|
+
return str.replace(/%/g, '%%');
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,QAAkB,EAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AAE5F;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAQ,EAAE,mBAA4B,KAAK,EAAU,EAAE;IACjF,IAAI,GAAG,IAAI,IAAI,EAAE;QACf,GAAG,GAAG,EAAE,CAAC;KACV;IACD,QAAQ,OAAO,GAAG,EAAE;QAClB,KAAK,QAAQ;YACX,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAClB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM;QACR,KAAK,SAAS;YACZ,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACtB,MAAM;QACR;YACE,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;KAC3B;IACD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,IAAI,gBAAgB,EAAE;QACpB,OAAO,GAAG,CAAC;KACZ;IACD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as sql from 'mssql';
|
|
2
|
+
import { ConnectionPool, IResult } from 'mssql';
|
|
3
|
+
import { IConnectionPools, TGetPoolConnectionOptions } from './interfaces';
|
|
4
|
+
export declare const getFirstConfigId: () => string;
|
|
5
|
+
export declare const getDbConfig: (connectionId: string) => any;
|
|
6
|
+
export declare const pools: IConnectionPools;
|
|
7
|
+
/**
|
|
8
|
+
* Возвращает пул соединений для БД, соответствующей преданному ID соединения (borf|cep|hr|global)
|
|
9
|
+
* В случае, если не удается создать пул или открыть соединение, прерывает работу скрипта
|
|
10
|
+
*/
|
|
11
|
+
export declare const getPoolConnection: (connectionId: string, options?: TGetPoolConnectionOptions) => Promise<ConnectionPool | undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* Закрывает указанные соединения с БД
|
|
14
|
+
*
|
|
15
|
+
* poolsToClose - пул или массив пулов
|
|
16
|
+
* prefix - Префикс в сообщении о закрытии пула (название синхронизации)
|
|
17
|
+
* noEcho - подавление сообщений о закрытии соединения
|
|
18
|
+
*/
|
|
19
|
+
export declare const closeDbConnections: (poolsToClose: ConnectionPool | ConnectionPool[] | string | string[], prefix?: string, noEcho?: boolean) => Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Закрывает все соединения с БД
|
|
22
|
+
*
|
|
23
|
+
* prefix - Префикс в сообщении о закрытии пула (название синхронизации)
|
|
24
|
+
* noEcho - подавление сообщений о закрытии соединения
|
|
25
|
+
*/
|
|
26
|
+
export declare const closeAllDbConnections: (prefix?: string, noEcho?: boolean) => Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Закрывает указанные соединения с БД и прерывает работу скрипта
|
|
29
|
+
*
|
|
30
|
+
* poolsToClose - пул или массив пулов
|
|
31
|
+
* prefix - Префикс в сообщении о закрытии пула (название синхронизации)
|
|
32
|
+
*/
|
|
33
|
+
export declare const closeDbConnectionsAndExit: (poolsToClose: ConnectionPool | ConnectionPool[], prefix?: string) => Promise<never>;
|
|
34
|
+
export declare const Request: (connectionId: string, strSQL: string) => Promise<any>;
|
|
35
|
+
export declare const setLogger: (logger_: any) => void;
|
|
36
|
+
export declare const logSqlError: (err: Error | any, noThrow?: boolean, textSQL?: string, prefix?: string) => void;
|
|
37
|
+
export declare const getPool: (dbId: string, noThrow?: boolean) => Promise<sql.ConnectionPool | undefined>;
|
|
38
|
+
export declare const query: (dbId: string, textSQL: string, noThrow?: boolean, prefix?: string) => Promise<IResult<any> | undefined>;
|
|
39
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAE3E,eAAO,MAAM,gBAAgB,cAA8G,CAAC;AAC5I,eAAO,MAAM,WAAW,iBAAkB,MAAM,QAAgD,CAAC;AAEjG,eAAO,MAAM,KAAK,EAAE,gBAAqB,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,iBAAiB,iBAAwB,MAAM,YAAW,yBAAyB,KAAQ,QAAQ,cAAc,GAAG,SAAS,CAmDzI,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,iBAAwB,cAAc,GAAG,cAAc,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,WAAW,MAAM,WAAW,OAAO,kBAsC9I,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,YAAmB,MAAM,WAAW,OAAO,kBAG5E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,iBAAwB,cAAc,GAAG,cAAc,EAAE,WAAW,MAAM,mBAG/G,CAAC;AAEF,eAAO,MAAM,OAAO,iBAAwB,MAAM,UAAU,MAAM,KAAG,QAAQ,GAAG,CAO/E,CAAC;AAQF,eAAO,MAAM,SAAS,YAAa,GAAG,SAErC,CAAC;AAEF,eAAO,MAAM,WAAW,QAAS,KAAK,GAAG,GAAG,YAAY,OAAO,YAAY,MAAM,WAAW,MAAM,SAWjG,CAAC;AAEF,eAAO,MAAM,OAAO,SAAgB,MAAM,YAAW,OAAO,4CAM3D,CAAC;AAEF,eAAO,MAAM,KAAK,SAAgB,MAAM,WAAW,MAAM,YAAY,OAAO,WAAW,MAAM,KAAG,QAAQ,QAAQ,GAAG,CAAC,GAAG,SAAS,CAc/H,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IGetValueForSQLArgs } from './interfaces';
|
|
2
|
+
export declare const binToHexString: (value: any) => string | null;
|
|
3
|
+
/**
|
|
4
|
+
* Возвращает значение, готовое для использования в строке SQL запроса
|
|
5
|
+
*/
|
|
6
|
+
export declare const getValueForSQL: (args: IGetValueForSQLArgs) => string | number | null;
|
|
7
|
+
//# sourceMappingURL=get-value-for-sql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-value-for-sql.d.ts","sourceRoot":"","sources":["../../src/get-value-for-sql.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAyB,MAAM,cAAc,CAAC;AAI1E,eAAO,MAAM,cAAc,UAAW,GAAG,kBAA6D,CAAC;AAwBvG;;GAEG;AACH,eAAO,MAAM,cAAc,SAAU,mBAAmB,KAAG,MAAM,GAAG,MAAM,GAAG,IA6O5E,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * as db from './db';
|
|
2
|
+
export { prepareSqlString, correctRecordSchema, getRecordSchema, wrapTransaction, serialize, getRecordValuesForSQL, getSqlSetExpression, getSqlValuesExpression, prepareRecordForSQL, prepareDataForSQL, getRowsAffected, } from './sql';
|
|
3
|
+
export { binToHexString, getValueForSQL, } from './get-value-for-sql';
|
|
4
|
+
export { IDBConfig, IFieldSchema, IGetMergeSQLOptions, TDBRecord, TFieldName, TFieldTypeCorrection, TGetRecordSchemaOptions, TRecordSchema, TRecordSchemaAssoc, TRecordSet, TRecordSetAssoc, TMergeRules, TMergeResult, TRecordKey, TGetPoolConnectionOptions, TGetRecordSchemaResult, IPrepareSqlStringArgs, IGetValueForSQLArgs, IDialect, DateTimeOptionsEx, IPrepareArgs, IPrepareRecordParams, ISchemaItem, IValueForSQLPartialArgs, } from './interfaces';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAE3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,SAAS,EACT,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAChB,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,cAAc,EACd,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,oBAAoB,EACpB,uBAAuB,EACvB,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,WAAW,EACX,YAAY,EACZ,UAAU,EACV,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACX,uBAAuB,GACxB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { ConnectionPool, IColumnMetadata, ISqlType } from 'mssql';
|
|
2
|
+
import { DateTimeOptions } from 'luxon';
|
|
3
|
+
/**
|
|
4
|
+
* Имя поля БД
|
|
5
|
+
*/
|
|
6
|
+
export type TFieldName = string;
|
|
7
|
+
/**
|
|
8
|
+
* Значение ключевого поля записи БД
|
|
9
|
+
*/
|
|
10
|
+
export type TRecordKey = string | number;
|
|
11
|
+
/**
|
|
12
|
+
* Метаинформация о поле БД
|
|
13
|
+
*/
|
|
14
|
+
export interface IFieldSchema {
|
|
15
|
+
index?: number;
|
|
16
|
+
name?: string;
|
|
17
|
+
length?: number;
|
|
18
|
+
type?: any;
|
|
19
|
+
arrayType?: any;
|
|
20
|
+
scale?: number;
|
|
21
|
+
precision?: number;
|
|
22
|
+
nullable?: boolean;
|
|
23
|
+
caseSensitive?: boolean;
|
|
24
|
+
identity?: boolean;
|
|
25
|
+
excludeFromInsert?: boolean;
|
|
26
|
+
readOnly?: boolean;
|
|
27
|
+
inputDateFormat?: string;
|
|
28
|
+
defaultValue?: any;
|
|
29
|
+
noQuotes?: boolean;
|
|
30
|
+
escapeOnlySingleQuotes?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Массив объектов с метаинформацией о полях
|
|
34
|
+
*/
|
|
35
|
+
export type TRecordSchema = IFieldSchema[];
|
|
36
|
+
/**
|
|
37
|
+
* Метаинформацией о полях, проиндексированная именами полей. (sql.recordset.columns)
|
|
38
|
+
*/
|
|
39
|
+
export interface TRecordSchemaAssoc {
|
|
40
|
+
[fieldName: TFieldName]: IFieldSchema;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Объект корректировки типов полей. Наименованию поля соответствует новый тип.
|
|
44
|
+
*
|
|
45
|
+
* В частности, используется для полей, хранящих знаяения типа json в поле типа varchar(max)
|
|
46
|
+
* тогда необходимо явно задать тип поля "json". Если имя поля заканчивается на _json, коррекция типа произойдет автоматически.
|
|
47
|
+
* Также используется для указания входного формата для преобразования строки в тип datetime (свойство inputDateFormat в схеме поля)
|
|
48
|
+
*/
|
|
49
|
+
export interface TFieldTypeCorrection {
|
|
50
|
+
[fieldName: TFieldName]: IFieldSchema;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Запись БД. Объект, проиндексированный именами полей. Значения - значения полей
|
|
54
|
+
*/
|
|
55
|
+
export interface TDBRecord {
|
|
56
|
+
[fieldName: TFieldName]: any;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Массив записей БД
|
|
60
|
+
*
|
|
61
|
+
* _isPreparedForSQL - Признак того, что значения полей подготовлены для использования в строке SQL
|
|
62
|
+
*/
|
|
63
|
+
export type TRecordSet = TDBRecord[] & {
|
|
64
|
+
_isPreparedForSQL?: boolean;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Пакет записей БД.
|
|
68
|
+
* Объект, проиндексированный алиасами. Каждый подобъект содержит TDBRecord.
|
|
69
|
+
*/
|
|
70
|
+
export interface TRecordSetAssoc {
|
|
71
|
+
[recordKey: TRecordKey]: TDBRecord;
|
|
72
|
+
}
|
|
73
|
+
export interface TMergeResult {
|
|
74
|
+
total: number;
|
|
75
|
+
inserted: number;
|
|
76
|
+
updated: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Метаинформация для формирования инструкции SQL MERGE
|
|
80
|
+
*/
|
|
81
|
+
export interface TMergeRules {
|
|
82
|
+
mergeIdentity?: TFieldName[];
|
|
83
|
+
excludeFromInsert?: TFieldName[];
|
|
84
|
+
noUpdateIfNull?: boolean;
|
|
85
|
+
correction?: Function;
|
|
86
|
+
withClause?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface TGetRecordSchemaOptions {
|
|
89
|
+
omitFields?: string[];
|
|
90
|
+
pickFields?: string[];
|
|
91
|
+
fieldTypeCorrection?: TFieldTypeCorrection;
|
|
92
|
+
mergeRules?: TMergeRules;
|
|
93
|
+
noReturnMergeResult?: boolean;
|
|
94
|
+
}
|
|
95
|
+
export interface TGetPoolConnectionOptions {
|
|
96
|
+
prefix?: string;
|
|
97
|
+
onError?: 'exit' | 'throw';
|
|
98
|
+
errorCode?: number;
|
|
99
|
+
}
|
|
100
|
+
export type IDialect = 'mssql' | 'pg';
|
|
101
|
+
interface IDBConfigCommon {
|
|
102
|
+
dialect: IDialect;
|
|
103
|
+
port: string | number | null;
|
|
104
|
+
database: string;
|
|
105
|
+
user: string;
|
|
106
|
+
password: string;
|
|
107
|
+
}
|
|
108
|
+
interface IDBConfigMSSQL extends IDBConfigCommon {
|
|
109
|
+
server: string;
|
|
110
|
+
}
|
|
111
|
+
interface IDBConfigPG extends IDBConfigCommon {
|
|
112
|
+
host: string;
|
|
113
|
+
}
|
|
114
|
+
export type IDBConfig = IDBConfigMSSQL | IDBConfigPG;
|
|
115
|
+
export interface ISchemaItem {
|
|
116
|
+
index: number;
|
|
117
|
+
name: string;
|
|
118
|
+
length: number;
|
|
119
|
+
type: (() => ISqlType) | ISqlType;
|
|
120
|
+
udt?: any;
|
|
121
|
+
scale?: number | undefined;
|
|
122
|
+
precision?: number | undefined;
|
|
123
|
+
nullable: boolean;
|
|
124
|
+
caseSensitive: boolean;
|
|
125
|
+
identity: boolean;
|
|
126
|
+
readOnly: boolean;
|
|
127
|
+
}
|
|
128
|
+
export interface IPrepareSqlStringArgs {
|
|
129
|
+
value: string | number | null;
|
|
130
|
+
defaultValue?: string | null | undefined;
|
|
131
|
+
length?: number;
|
|
132
|
+
nullable?: boolean | number;
|
|
133
|
+
noQuotes?: boolean;
|
|
134
|
+
escapeOnlySingleQuotes?: boolean;
|
|
135
|
+
}
|
|
136
|
+
export interface DateTimeOptionsEx extends DateTimeOptions {
|
|
137
|
+
correctionMillis: number;
|
|
138
|
+
}
|
|
139
|
+
export interface IValueForSQLPartialArgs {
|
|
140
|
+
dateTimeOptions?: DateTimeOptionsEx;
|
|
141
|
+
dialect?: IDialect;
|
|
142
|
+
escapeOnlySingleQuotes?: boolean;
|
|
143
|
+
needValidate?: boolean;
|
|
144
|
+
}
|
|
145
|
+
export interface IPrepareRecordParams {
|
|
146
|
+
addMissingFields?: boolean;
|
|
147
|
+
addValues4NotNullableFields?: boolean;
|
|
148
|
+
}
|
|
149
|
+
export interface IGetValueForSQLArgs extends IValueForSQLPartialArgs {
|
|
150
|
+
value: any;
|
|
151
|
+
fieldSchema: IFieldSchema | string;
|
|
152
|
+
}
|
|
153
|
+
export interface IPrepareArgs extends IValueForSQLPartialArgs, IPrepareRecordParams {
|
|
154
|
+
recordSchema: TRecordSchema;
|
|
155
|
+
}
|
|
156
|
+
export interface IGetMergeSQLOptions extends IValueForSQLPartialArgs, IPrepareRecordParams {
|
|
157
|
+
isPrepareForSQL?: boolean;
|
|
158
|
+
}
|
|
159
|
+
export interface TGetRecordSchemaResult {
|
|
160
|
+
connectionId: string;
|
|
161
|
+
dbConfig: IDBConfig;
|
|
162
|
+
schemaAndTable: string;
|
|
163
|
+
dbSchemaAndTable: string;
|
|
164
|
+
columns: IColumnMetadata;
|
|
165
|
+
schemaAssoc: Partial<IColumnMetadata>;
|
|
166
|
+
schema: ISchemaItem[];
|
|
167
|
+
fields: string[];
|
|
168
|
+
insertFields: string[];
|
|
169
|
+
insertFieldsList: string;
|
|
170
|
+
withClause: string | undefined;
|
|
171
|
+
updateFields: string[];
|
|
172
|
+
mergeIdentity: string[];
|
|
173
|
+
getMergeSQL: (_packet: TRecordSet, _prepareOptions?: IGetMergeSQLOptions) => string;
|
|
174
|
+
getInsertSQL: (_packet: TRecordSet, _addOutputInserted?: boolean) => string;
|
|
175
|
+
getUpdateSQL: (_record: TRecordSet) => string;
|
|
176
|
+
}
|
|
177
|
+
export interface IConnectionPools {
|
|
178
|
+
[poolId: string]: ConnectionPool;
|
|
179
|
+
}
|
|
180
|
+
export {};
|
|
181
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as sql from 'mssql';
|
|
2
|
+
import { IFieldSchema, IPrepareArgs, IPrepareSqlStringArgs, TDBRecord, TFieldTypeCorrection, TGetRecordSchemaResult, TGetRecordSchemaOptions, TRecordSchema, TRecordSchemaAssoc, TRecordSet } from './interfaces';
|
|
3
|
+
export { sql };
|
|
4
|
+
/**
|
|
5
|
+
* Подготовка строки для передачи в SQL
|
|
6
|
+
*/
|
|
7
|
+
export declare const prepareSqlString: (args: IPrepareSqlStringArgs) => string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Корректировка схемы таблицы
|
|
10
|
+
* Поля с суффиксом _json получают тип "json". Остальные корректировки берутся из fieldTypeCorrection
|
|
11
|
+
* Например, для полей типа datetime можно передавать свойство inputDateFormat
|
|
12
|
+
*/
|
|
13
|
+
export declare const correctRecordSchema: (recordSchemaAssoc: TRecordSchemaAssoc, fieldTypeCorrection?: TFieldTypeCorrection) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Подготовка значений записи для использования в SQL
|
|
16
|
+
*
|
|
17
|
+
* Все поля записи обрабатываются функцией getValueForSQL
|
|
18
|
+
*/
|
|
19
|
+
export declare const prepareRecordForSQL: (record: TDBRecord, args: IPrepareArgs) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Подготовка данных для SQL
|
|
22
|
+
*
|
|
23
|
+
* Все поля всех записей обрабатываются функцией getValueForSQL
|
|
24
|
+
*/
|
|
25
|
+
export declare const prepareDataForSQL: (recordSet: TRecordSet, args: IPrepareArgs) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Возвращает рекорд, в котором все значения преобразованы в строки и подготовлены для прямой вставки в SQL
|
|
28
|
+
* В частности, если значение типа строка, то оно уже заключено в одинарные кавычки
|
|
29
|
+
*/
|
|
30
|
+
export declare const getRecordValuesForSQL: (record: TDBRecord, recordSchema: TRecordSchema) => TDBRecord;
|
|
31
|
+
/**
|
|
32
|
+
* Возвращает схему полей таблицы БД. Либо в виде объекта, либо в виде массива
|
|
33
|
+
* Если asArray = true, то вернет TRecordSchema, при этом удалит поля, указанные в omitFields
|
|
34
|
+
* Иначе вернет TRecordSchemaAssoc
|
|
35
|
+
*/
|
|
36
|
+
export declare const getRecordSchema: (connectionId: string, schemaAndTable: string, options?: TGetRecordSchemaOptions) => Promise<TGetRecordSchemaResult | undefined>;
|
|
37
|
+
/**
|
|
38
|
+
* Оборачивает инструкции SQL в транзакцию
|
|
39
|
+
*/
|
|
40
|
+
export declare const wrapTransaction: (strSQL: string) => string;
|
|
41
|
+
/**
|
|
42
|
+
* Возвращает проверенное и серилизованное значение
|
|
43
|
+
*/
|
|
44
|
+
export declare const serialize: (value: any, fieldSchema: IFieldSchema) => string | number | null;
|
|
45
|
+
/**
|
|
46
|
+
* Возвращает подготовленное выражение SET для использования в UPDATE
|
|
47
|
+
*/
|
|
48
|
+
export declare const getSqlSetExpression: (record: TDBRecord, recordSchema: TRecordSchema) => string;
|
|
49
|
+
/**
|
|
50
|
+
* Возвращает подготовленное выражение (...поля...) VALUES (...значения...) для использования в INSERT
|
|
51
|
+
*
|
|
52
|
+
* addOutputInserted - Если true, добавляется выражение OUTPUT inserted.* перед VALUES
|
|
53
|
+
*/
|
|
54
|
+
export declare const getSqlValuesExpression: (record: TDBRecord, recordSchema: TRecordSchema, addOutputInserted?: boolean) => string;
|
|
55
|
+
export declare const getRowsAffected: (qResult: any) => any;
|
|
56
|
+
//# sourceMappingURL=sql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAQ7B,OAAO,EACL,YAAY,EAES,YAAY,EACjC,qBAAqB,EAErB,SAAS,EAET,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,aAAa,EACb,kBAAkB,EAClB,UAAU,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,GAAG,EAAE,CAAC;AAEf;;GAEG;AACH,eAAO,MAAM,gBAAgB,SAAU,qBAAqB,KAAG,MAAM,GAAG,IAsBvE,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,sBACX,kBAAkB,wBAEf,oBAAoB,SAgC3C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,WAAY,SAAS,QAAQ,YAAY,SAiBxE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,cAAe,UAAU,QAAQ,YAAY,SAQ1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,WAAY,SAAS,kCAAgC,SAYtF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,iBAEZ,MAAM,kBAEJ,MAAM,YAEb,uBAAuB,KAC/B,QAAQ,sBAAsB,GAAG,SAAS,CA+J5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,WAAY,MAAM,KAAG,MAuBtC,CAAC;AAEZ;;GAEG;AACH,eAAO,MAAM,SAAS,UAAW,GAAG,eAAe,YAAY,KAAG,MAAM,GAAG,MAAM,GAAG,IASnF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,WAAY,SAAS,kCAAgC,MASpF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,WAAY,SAAS,mDAAkD,OAAO,KAAW,MAW3H,CAAC;AAEF,eAAO,MAAM,eAAe,YAAa,GAAG,QAAmG,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Оборачивает строку в одинарные кавычки, если второй аргумент не true
|
|
3
|
+
*/
|
|
4
|
+
export declare const q: (val: string, noQuotes?: boolean) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Экранирование одинарной кавычки и символа % для использования строки в SQL запросе
|
|
7
|
+
* onlySingleQuotes - true - не экранировать %
|
|
8
|
+
*/
|
|
9
|
+
export declare const mssqlEscape: (str: any, onlySingleQuotes?: boolean) => string;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,CAAC,QAAS,MAAM,aAAa,OAAO,KAAG,MAAuC,CAAC;AAE5F;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAS,GAAG,qBAAoB,OAAO,KAAW,MAqBzE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "af-db-ts",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "A highly specialized function library",
|
|
5
|
+
"main": "./dist/cjs/index.js",
|
|
6
|
+
"module": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"author": "Viacheslav Makarov <npmjs@bazilio.ru>",
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test_": "mocha --require @babel/register 'test/**/**spec.js'",
|
|
12
|
+
"clean": "shx rm -rf dist/*",
|
|
13
|
+
"build": "tsc -b tsconfig.json tsconfig.esm.json tsconfig.types.json",
|
|
14
|
+
"lint": "eslint . --ext .ts ",
|
|
15
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
16
|
+
"test": "jest --config jest.config.js",
|
|
17
|
+
"release": "npm run lint:fix && npm run clean && npm run build && npm run test",
|
|
18
|
+
"cb": "npm run clean && npm run build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"af-color": "^0.0.8",
|
|
22
|
+
"af-echo-ts": "^1.0.9",
|
|
23
|
+
"af-tools-ts": "^1.0.53",
|
|
24
|
+
"config": "^3.3.9",
|
|
25
|
+
"lodash": "^4.17.21",
|
|
26
|
+
"luxon": "^3.4.2",
|
|
27
|
+
"memory-cache": "^0.2.0",
|
|
28
|
+
"moment": "^2.29.4",
|
|
29
|
+
"moment-timezone": "^0.5.43",
|
|
30
|
+
"mssql": "^9.2.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@babel/register": "^7.22.15",
|
|
34
|
+
"@jest/test-sequencer": "^29.6.4",
|
|
35
|
+
"@types/config": "^3.3.0",
|
|
36
|
+
"@types/jest": "^29.5.4",
|
|
37
|
+
"@types/lodash": "^4.14.197",
|
|
38
|
+
"@types/luxon": "^3.3.2",
|
|
39
|
+
"@types/memory-cache": "^0.2.3",
|
|
40
|
+
"@types/mssql": "^8.1.2",
|
|
41
|
+
"@types/node": "^20.5.9",
|
|
42
|
+
"@types/supertest": "^2.0.12",
|
|
43
|
+
"chai": "^4.3.8",
|
|
44
|
+
"eslint-config-af-22": "^1.0.13",
|
|
45
|
+
"jest": "^29.6.4",
|
|
46
|
+
"mocha": "^10.2.0",
|
|
47
|
+
"shx": "^0.3.4",
|
|
48
|
+
"supertest": "^6.3.3",
|
|
49
|
+
"ts-jest": "^29.1.1",
|
|
50
|
+
"ts-node": "^10.9.1",
|
|
51
|
+
"typescript": "^5.2.2"
|
|
52
|
+
},
|
|
53
|
+
"np": {
|
|
54
|
+
"yarn": false,
|
|
55
|
+
"contents": "."
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"files": [
|
|
61
|
+
"dist/cjs",
|
|
62
|
+
"dist/esm",
|
|
63
|
+
"dist/types",
|
|
64
|
+
"src"
|
|
65
|
+
],
|
|
66
|
+
"repository": {
|
|
67
|
+
"type": "git",
|
|
68
|
+
"url": "git+https://github.com/Bazilio-san/af-db-ts.git"
|
|
69
|
+
},
|
|
70
|
+
"engines": {
|
|
71
|
+
"node": ">= 14",
|
|
72
|
+
"npm": ">= 6.13.4",
|
|
73
|
+
"yarn": ">= 1.21.1"
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/db.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import * as config from 'config';
|
|
2
|
+
import { magenta } from 'af-color';
|
|
3
|
+
import { echo } from 'af-echo-ts';
|
|
4
|
+
import * as sql from 'mssql';
|
|
5
|
+
import { ConnectionPool, IResult } from 'mssql';
|
|
6
|
+
import * as _ from 'lodash';
|
|
7
|
+
import { sleep } from 'af-tools-ts';
|
|
8
|
+
import { IConnectionPools, TGetPoolConnectionOptions } from './interfaces';
|
|
9
|
+
|
|
10
|
+
export const getFirstConfigId = () => Object.keys(config.get<any>('database') || {}).filter((v) => !['dialect', '_common_'].includes(v))[0];
|
|
11
|
+
export const getDbConfig = (connectionId: string) => config.get<any>(`database.${connectionId}`);
|
|
12
|
+
|
|
13
|
+
export const pools: IConnectionPools = {};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Возвращает пул соединений для БД, соответствующей преданному ID соединения (borf|cep|hr|global)
|
|
17
|
+
* В случае, если не удается создать пул или открыть соединение, прерывает работу скрипта
|
|
18
|
+
*/
|
|
19
|
+
export const getPoolConnection = async (connectionId: string, options: TGetPoolConnectionOptions = {}): Promise<ConnectionPool | undefined> => {
|
|
20
|
+
const { prefix = '', errorCode = 0 } = options;
|
|
21
|
+
let pool = pools[connectionId];
|
|
22
|
+
if (pool?.connected) {
|
|
23
|
+
return pool;
|
|
24
|
+
}
|
|
25
|
+
const resume = (errMsg: string) => {
|
|
26
|
+
if (options.onError === 'exit') {
|
|
27
|
+
echo.error(prefix, `${errMsg}\nEXIT PROCESS`);
|
|
28
|
+
process.exit(errorCode);
|
|
29
|
+
} else {
|
|
30
|
+
throw new Error(errMsg);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
try {
|
|
34
|
+
const cfg: any = config.get<any>('database');
|
|
35
|
+
const namedDbConfig = cfg[connectionId];
|
|
36
|
+
if (!namedDbConfig) {
|
|
37
|
+
resume(`Missing configuration for DB id "${connectionId}"`);
|
|
38
|
+
}
|
|
39
|
+
const dbConfig = config.util.extendDeep({}, cfg._common_ || {}, cfg[connectionId]);
|
|
40
|
+
if (pool?.connecting) {
|
|
41
|
+
const startTs = Date.now();
|
|
42
|
+
while (pool?.connecting && (Date.now() - startTs < dbConfig.connectionTimeout)) {
|
|
43
|
+
// eslint-disable-next-line no-await-in-loop
|
|
44
|
+
await sleep(100);
|
|
45
|
+
}
|
|
46
|
+
if (pool?.connected) {
|
|
47
|
+
return pool;
|
|
48
|
+
}
|
|
49
|
+
echo.error(prefix, `Can't connect connectionId "${connectionId}"`);
|
|
50
|
+
}
|
|
51
|
+
pool = new sql.ConnectionPool(dbConfig);
|
|
52
|
+
if (typeof pool !== 'object') {
|
|
53
|
+
resume(`Can't create connection pool "${connectionId}"`);
|
|
54
|
+
}
|
|
55
|
+
pools[connectionId] = pool;
|
|
56
|
+
// @ts-ignore
|
|
57
|
+
pool._connectionId = connectionId;
|
|
58
|
+
pool.on('close', () => {
|
|
59
|
+
delete pools[connectionId];
|
|
60
|
+
});
|
|
61
|
+
pool.on('error', (err) => {
|
|
62
|
+
echo.error('POOL-ERROR', err);
|
|
63
|
+
});
|
|
64
|
+
await pool.connect();
|
|
65
|
+
return pool;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
echo.error(err);
|
|
68
|
+
resume(`Cant connect to "${connectionId}" db`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Закрывает указанные соединения с БД
|
|
74
|
+
*
|
|
75
|
+
* poolsToClose - пул или массив пулов
|
|
76
|
+
* prefix - Префикс в сообщении о закрытии пула (название синхронизации)
|
|
77
|
+
* noEcho - подавление сообщений о закрытии соединения
|
|
78
|
+
*/
|
|
79
|
+
export const closeDbConnections = async (poolsToClose: ConnectionPool | ConnectionPool[] | string | string[], prefix?: string, noEcho?: boolean) => {
|
|
80
|
+
if (!Array.isArray(poolsToClose)) {
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
poolsToClose = [poolsToClose];
|
|
83
|
+
}
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
for (let i = 0; i < poolsToClose.length; i++) {
|
|
86
|
+
let pool = poolsToClose[i];
|
|
87
|
+
let connectionId: string = '';
|
|
88
|
+
if (pool) {
|
|
89
|
+
if (typeof pool === 'string') {
|
|
90
|
+
connectionId = pool;
|
|
91
|
+
pool = pools[connectionId];
|
|
92
|
+
} else if (typeof pool === 'object') {
|
|
93
|
+
// @ts-ignore
|
|
94
|
+
connectionId = pool._connectionId;
|
|
95
|
+
}
|
|
96
|
+
if (connectionId) {
|
|
97
|
+
delete pools[connectionId];
|
|
98
|
+
}
|
|
99
|
+
if (pool && pool.close) {
|
|
100
|
+
try {
|
|
101
|
+
// eslint-disable-next-line no-await-in-loop
|
|
102
|
+
await pool.close();
|
|
103
|
+
if (!noEcho && connectionId) {
|
|
104
|
+
const msg = `pool "${connectionId}" closed`;
|
|
105
|
+
if (prefix) {
|
|
106
|
+
echo.info(prefix, msg);
|
|
107
|
+
} else {
|
|
108
|
+
echo.info(msg);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
//
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Закрывает все соединения с БД
|
|
121
|
+
*
|
|
122
|
+
* prefix - Префикс в сообщении о закрытии пула (название синхронизации)
|
|
123
|
+
* noEcho - подавление сообщений о закрытии соединения
|
|
124
|
+
*/
|
|
125
|
+
export const closeAllDbConnections = async (prefix?: string, noEcho?: boolean) => {
|
|
126
|
+
const poolsToClose = _.map(pools, (p) => p);
|
|
127
|
+
await closeDbConnections(poolsToClose, prefix, noEcho);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Закрывает указанные соединения с БД и прерывает работу скрипта
|
|
132
|
+
*
|
|
133
|
+
* poolsToClose - пул или массив пулов
|
|
134
|
+
* prefix - Префикс в сообщении о закрытии пула (название синхронизации)
|
|
135
|
+
*/
|
|
136
|
+
export const closeDbConnectionsAndExit = async (poolsToClose: ConnectionPool | ConnectionPool[], prefix?: string) => {
|
|
137
|
+
await closeDbConnections(poolsToClose, prefix);
|
|
138
|
+
process.exit(0);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const Request = async (connectionId: string, strSQL: string): Promise<any> => {
|
|
142
|
+
const pool = await getPoolConnection(connectionId, { onError: 'throw' });
|
|
143
|
+
const request = new sql.Request(pool);
|
|
144
|
+
if (strSQL) {
|
|
145
|
+
return request.query(strSQL);
|
|
146
|
+
}
|
|
147
|
+
return request;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
interface IAsLogger {
|
|
151
|
+
error: Function,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let logger: IAsLogger = echo as IAsLogger;
|
|
155
|
+
|
|
156
|
+
export const setLogger = (logger_: any) => {
|
|
157
|
+
logger = logger_ as IAsLogger;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export const logSqlError = (err: Error | any, noThrow?: boolean, textSQL?: string, prefix?: string) => {
|
|
161
|
+
if (prefix) {
|
|
162
|
+
logger.error(prefix);
|
|
163
|
+
}
|
|
164
|
+
if (textSQL) {
|
|
165
|
+
logger.error(`SQL Error:\n${magenta}${textSQL}`);
|
|
166
|
+
}
|
|
167
|
+
logger.error(err);
|
|
168
|
+
if (!noThrow) {
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export const getPool = async (dbId: string, noThrow: boolean = false) => {
|
|
174
|
+
try {
|
|
175
|
+
return getPoolConnection(dbId);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
logSqlError(err, noThrow, `Error while open connection to DB ${dbId}`);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export const query = async (dbId: string, textSQL: string, noThrow?: boolean, prefix?: string): Promise<IResult<any> | undefined> => {
|
|
182
|
+
const pool = await getPool(dbId, noThrow);
|
|
183
|
+
if (!pool?.connected && !pool?.connecting) {
|
|
184
|
+
await closeDbConnections(dbId);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const request = new sql.Request(pool);
|
|
188
|
+
let res: IResult<any>;
|
|
189
|
+
try {
|
|
190
|
+
res = await request.query(textSQL);
|
|
191
|
+
return res;
|
|
192
|
+
} catch (err) {
|
|
193
|
+
logSqlError(err, noThrow, textSQL, prefix);
|
|
194
|
+
}
|
|
195
|
+
};
|