这是一个全新的大版本, 不向下兼容2.x, 使用typescript重构

master
宇天 2018-04-16 14:57:24 +08:00
parent 2db292bae3
commit f289d2f3c2
11 changed files with 753 additions and 292 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
.DS_Store
.AppleDouble
.LSOverride
Icon
/dist
/node_modules
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes

View File

@ -1,3 +1,14 @@
3.0.0 / 2018-04-16
==================
> 这是一个全新的大版本, 不向下兼容2.x, 使用typescript重构。
* 重构API, 使用链式操作, 逻辑更加清晰
* 支持完整的pool option
* 新增drop方法,支持删除数据库/数据表
* 新增tableCreate/dbCreate方法, 支持创建数据库/数据表
* 新增indexCreate/indexRename/indexDrop/indexList, 支持对索引的增删改查
2.2.2 / 2018-03-22
==================
* 增加时区和BIGINT配置

224
docs/2.x.md Normal file
View File

@ -0,0 +1,224 @@
![module info](https://nodei.co/npm/mysqli.png?downloads=true&downloadRank=true&stars=true)
# mysqli
> 本模块基于 node-mysql 模块二次封装将SQL语法转为类似MongoDB的API。对常用的增删改查提供了简单的API, 并且进行了SQL注入过滤, 对新手非常友好。
## 使用 npm 安装
```bash
npm install mysqli
```
## 实例化
> 实例化可以传入一个数组,或单个object配置。只有一个数据库时默认
> 是主库 ; 多于 1 个数据库服务时,自动以第 1 个为主库,其他的从库,故实例化时
> `注意顺序`。
```javascript
let Mysqli = require('mysqli')
//传入json
let conn = new Mysqli({
host: '', // IP/域名
post: 3306, //端口, 默认 3306
user: '', //用户名
passwd: '', //密码
charset: '', // 数据库编码,默认 utf8 【可选】
db: '' // 可指定数据库,也可以不指定 【可选】
})
// 传入数组
let conn = new Mysqli([
{
host: 'host1', // IP/域名
post: 3306, //端口, 默认 3306
user: '', //用户名
passwd: '', //密码
charset: '', // 数据库编码,默认 utf8 【可选】
db: '' // 可指定数据库,也可以不指定 【可选】
},
{
host: 'host2', // IP/域名
post: 3306, //端口, 默认 3306
user: '', //用户名
passwd: '', //密码
charset: '', // 数据库编码,默认 utf8 【可选】
db: '' // 可指定数据库,也可以不指定 【可选】
}
])
```
## API 方法
### 1. escape(val)
> 这是`node-mysql`的内部方法,用于进行 SQL 安全过滤,这里只是做了搬运工,把它暴
> 露出来给外部调用而已。 **这个是静态方法**
```javascript
const Mysqli = require('mysqli')
Mysqli.escape('这是文本')
```
### 2. emit(isSlave, dbName)
* isSlave `<Boolean>` 可选
* dbName `<String>` 可选。 如果在实例化连接时 , 已经传入 db, 则这里可不传值。
> 触发一个数据库实例 , 可接受 2 个参数 , 第 1 个为 " 是否从库 ", 第 2 个为 " 数
> 据库名称 "
> `这一步是必须要的, `
```javascript
const Mysqli = require('mysqli')
let conn = new Mysqli({
/*...*/
})
let db = conn.emit(true, 'test')
```
### 3. listDb()
> 顾名思义,该方法即用于列举当前账号权限范围内的所有的数据库名称,返回值是一个数
> 组 ;
>
> **注:**`方法返回的是一个 Promise 对象`
```javascript
db.listDb().then(list => {
console.log(list)
})
```
### 4. listTable()
> 该方法用于列举当前数据库数据表的集合
```javascript
db.listTable().then(list => {
console.log(list)
})
```
### 5. query(sql)
* sql `<String>`
> 该方法用于当内置的方法满足不了需求时,可以自行编写`sql 语句`执行 ; 但要注意防
> 止`sql 注入`,因为该方法是最基础的方法,模块不对传入的`sql 语句`进行任何的安全
> 过滤。
```javascript
// 不使用await指令时返回的是Promise对象
db.query(`select * from users limit 10`).then(row => {
console.log(row)
})
```
### 6. find(condition, select)
* condition `<Object>`, 查询条件
* select `<Array>`, 要返回字段 , 默认全部返回
> 该方法用于查询多条数据。无论结果是多少条,返回的都是`数组格式`; 详细请看下面代
> 码示例:
```javascript
db
.find(
{
table: '', // 要查询的表
where: {foo: 'bar', goo: {$like: 'hello%'}}, //条件, 语法类似mongodb
sort: {
//排序, key是要排序的字段,value是排序方式, 1顺序,-1逆序 【可选】
a: 1,
b: -1
},
limit: [0, 1] // 查询范围,可用于分页 【可选】
},
['id', 'name'] //要select的字段
)
.then(row => {
console.log(row)
})
```
### 7. findOne(condition)
* condition `<Object>`
> 该方法与上面的`filter`方法的使用一致,区别只是该方法只返回一条数据,且为`json
> 格式`。
### 8. count(condition)
* condition `<Object>`
> 该方法与上面的`filter`方法的使用一致,不过返回的是条目总数 (`<Number>`)
### 9. insert(condition, doc)
* condition `<Object>`, 插入的条件
* doc `<Object>`, 插入的数据
> 该方法与上面的`filter`方法的使用类似,手于插入一条数据,具体请看下面代码 ;
>
> **注:**`该方法一次只能插入一条数据`
```javascript
// 如果主键是自增ID则结果返回的是 刚插入的数据的自增ID
db
.insert(
{
table: 'xx'
},
{ xx: 1234 } //要插入的数据
)
.then(id => {
console.log(id)
})
```
### 10. update(condition, doc)
* condition `<Object>`, 条件
* doc `<Object>`, 数据
> 该方法与上面的`filter`方法的使用类似,用于更新数据,具体请看下面代码 ; `该方法返
> 回的是被修改的条目数量`
```javascript
// 如果修改成功,则返回被修改的数量
db
.update(
{
table: 'xx'
},
{ xx: 1234 } //要插入的数据
)
.then(num => {
console.log(num)
})
```
### 11. remove(condition)
* condition `<Object>`
> 该方法与上面的`update`方法的使用类似,用于删除指定条件的数据 ; 具体请看下面代码
> ; `该方法返回的是被删除的条目数量`
```javascript
// 如果修改成功,返回的是被删除的条目数量
db
.remove(
{
table: 'xx'
}
)
.then(num => {
console.log(num)
})
```

0
docs/3.x.md Normal file
View File

View File

@ -1,255 +0,0 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2017-12-14 14:01:03
* @version $Id$
*/
const { escape } = require('mysql')
const parser = require('./parser')
class SqlErr extends Error {
constructor(msg, sql) {
super(msg)
this.sql = sql || ''
}
}
class Method {
constructor(pool, slave, db) {
this.pool = pool
this.slave = slave
this.db = db
}
connect() {
const defer = Promise.defer()
this.pool.getConnection(this.slave, (err, conn) => {
if (err) {
return defer.reject(new SqlErr(`MySQL connect ${err}`))
}
if (this.db) {
conn.query('USE ' + this.db, err => {
if (err) {
return defer.reject(new SqlErr('Select DB ' + err))
}
defer.resolve(conn)
})
} else {
defer.resolve(conn)
}
})
return defer.promise
}
listDb() {
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query('SHOW DATABASES', (err, row) => {
conn.release()
if (err) {
return defer.reject(new SqlErr('SHOW DATABASES ' + err))
}
defer.resolve(row.map(it => it.Database))
})
return defer.promise
})
}
//返回数据表
listTable() {
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query('SHOW TABLES', (err, row) => {
conn.release()
if (err) {
return defer.reject(new SqlErr('SHOW TABLES ' + err))
}
defer.resolve(row.map(it => Object.values(it)[0]))
})
return defer.promise
})
}
/**
* [query sql语句执行]
* @param {[type]} sql [sql语句]
*/
query(sql) {
if (typeof sql !== 'string') {
return Promise.reject(
new SqlErr(
`Query error, argument sql must be string. ${typeof sql} given`,
sql
)
)
}
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query(sql, (err, result) => {
conn.release()
if (err) {
return defer.reject(new SqlErr(`Query ${err}`, sql))
}
defer.resolve(result)
})
return defer.promise
})
}
find(condition, select) {
const { table, leftJoin, rightJoin, join, where, sort, limit } = condition
if (!table) {
return Promise.reject(new SqlErr('Find Error: empty table'))
}
let sql = parser.select(select)
sql += `FROM ${table} `
if (leftJoin) {
sql += parser.leftJoin(leftJoin)
}
if (rightJoin) {
sql += parser.rightJoin(rightJoin)
}
if (join) {
sql += parser.join(join)
}
if (where) {
sql += parser.where(where)
}
if (sort) {
sql += parser.sort(sort)
}
if (limit) {
sql += parser.limit(limit)
}
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query(sql, (err, result) => {
conn.release()
if (err) {
return defer.reject(new SqlErr(`Find ${err}`, sql))
}
defer.resolve(result)
})
return defer.promise
})
}
findOne(condition, select) {
condition.limit = [1]
return this.find(condition, select).then(row => {
return row[0] || null
})
}
count(condition) {
delete condition.limit
return this.find(condition, ['count(*) AS total']).then(row => {
return (row[0] && row[0].total) || 0
})
}
insert({ table }, doc) {
if (!table) {
return Promise.reject(new SqlErr('Insert Error: empty table'))
}
let sql = `INSERT INTO ${table} `
let keys = []
let vals = []
for (let i in doc) {
keys.push(i)
vals.push(escape(doc[i]))
}
sql += `(${keys.join(',')}) VALUES (${vals.join(',')})`
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query(sql, (err, result) => {
conn.release()
if (err) {
return defer.reject(new SqlErr(`Insert ${err}`, sql))
}
defer.resolve(result.insertId)
})
return defer.promise
})
}
update({ table, where }, doc) {
if (!table) {
return Promise.reject(new SqlErr('Update Error: empty table'))
}
let sql = `UPDATE ${table} SET `
let fields = [] //要更新的字段
for (let i in doc) {
let val = doc[i]
if (typeof val === 'object' && val.$sql) {
val = `(${val.$sql})`
} else {
val = escape(val)
}
fields.push(i + ' = ' + val)
}
sql += fields.join(',')
sql += parser.where(where)
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query(sql, (err, res) => {
conn.release()
if (err) {
return defer.reject(new SqlErr(`Update ${err}`, sql))
}
defer.resolve(res.affectedRows)
})
return defer.promise
})
}
remove({ table, where }) {
if (!table) {
return Promise.reject(new SqlErr('Remove Error: empty table'))
}
let sql = `DELETE FROM \`${table}\` `
if (where) {
sql += parser.where(where)
}
return this.connect().then(conn => {
const defer = Promise.defer()
conn.query(sql, (err, res) => {
conn.release()
if (err) {
return defer.reject(new SqlErr(`Remove ${err}`, sql))
}
defer.resolve(res.affectedRows)
})
return defer.promise
})
}
}
module.exports = Method

View File

@ -1,8 +1,8 @@
{
"name": "mysqli",
"version": "2.2.2",
"version": "3.0.0",
"description": "MySQL tool",
"main": "index.js",
"main": "dist/index.js",
"dependencies": {
"es.shim": "^0.0.3",
"mysql": "^2.13.0"

View File

@ -5,25 +5,17 @@
*
*/
'use strict'
require('es.shim')
import 'es.shim'
const mysql = require('mysql')
const Method = require('./lib/method')
import Api from './lib/api'
if (!Promise.defer) {
Promise.defer = function() {
let obj = {}
obj.promise = new this((yes, no) => {
obj.resolve = yes
obj.reject = no
})
return obj
}
}
class Mysqli {
useSlaveDB: boolean
pool: any
/**
* [constructor ]
*/
constructor(config) {
constructor(config: any) {
if (!Array.isArray(config)) {
config = [config]
}
@ -35,7 +27,7 @@ class Mysqli {
restoreNodeTimeout: 10000
})
config.forEach((item, i) => {
config.forEach((item: { [prop: string]: any }, i: number) => {
let {
host,
port,
@ -44,7 +36,8 @@ class Mysqli {
passwd: password,
db: database,
timezone,
supportBigNumbers
supportBigNumbers,
...others
} = item
let name = i < 1 ? 'MASTER' : 'SLAVE' + i
let collate
@ -65,20 +58,21 @@ class Mysqli {
password,
database,
timezone,
supportBigNumbers
supportBigNumbers,
...others
})
})
return this
}
//对外的escape方法
static escape(val) {
static escape(val: any) {
return mysql.escape(val)
}
emit(fromSlave = false, db) {
const slave = fromSlave && this.useSlaveDB ? 'SLAVE*' : 'MASTER'
return new Method(this.pool, slave, db)
emit(fromSlave = false, db: string = '') {
let slave = fromSlave && this.useSlaveDB ? 'SLAVE*' : 'MASTER'
return new Api(this.pool, slave, db)
}
}

123
src/lib/api.ts Normal file
View File

@ -0,0 +1,123 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2018-04-13 14:30:49
* @version $Id$
*/
import { defer, SqlErr } from './utils'
import Method from './method'
interface Conn {
query(sql: string, cb?: any): void
release(): void
}
class Api {
pool: any
slave: string
db: string
constructor(pool: object, slave: string = 'MASTER', db: string = '') {
this.pool = pool
this.slave = slave
this.db = db
}
connect() {
let out = defer()
this.pool.getConnection(this.slave, (err: Error, conn: Conn) => {
if (err) {
return out.reject(new SqlErr(`MySQL connect ${err}`))
}
if (this.db) {
conn.query('USE ' + this.db, (err: Error) => {
if (err) {
return out.reject(new SqlErr('Select DB ' + err))
}
out.resolve(conn)
})
} else {
out.resolve(conn)
}
})
return out.promise
}
table(name: string) {
if (!name) {
throw new SqlErr('Query Error: empty table')
}
return new Method(this.pool, this.slave, this.db, name)
}
/**
* [query sql]
* @param {[type]} sql [sql]
*/
query(sql: string) {
if (typeof sql !== 'string') {
return Promise.reject(
new SqlErr(
`Query error, argument sql must be string. ${typeof sql} given`,
sql
)
)
}
return this.connect().then((conn: Conn) => {
let out = defer()
conn.query(sql, (err: Error, result: any) => {
conn.release()
if (err) {
return out.reject(new SqlErr(`Query ${err}`, sql))
}
out.resolve(result)
})
return out.promise
})
}
drop() {
if (!this.db) {
return Promise.reject('')
}
this.connect().then((conn: Conn) => {
conn.query('')
})
}
dbList() {
return this.connect().then((conn: Conn) => {
let out = defer()
conn.query('SHOW DATABASES', (err: Error, row: any) => {
conn.release()
if (err) {
return out.reject(new SqlErr('SHOW DATABASES ' + err))
}
out.resolve(row.map((it: any) => it.Database))
})
return out.promise
})
}
//返回数据表
tableList() {
return this.connect().then((conn: Conn) => {
const out = defer()
conn.query('SHOW TABLES', (err: Error, row: any) => {
conn.release()
if (err) {
return out.reject(new SqlErr('SHOW TABLES ' + err))
}
out.resolve(row.map((it: any) => it[Object.keys(it)[0]]))
})
return out.promise
})
}
}
export default Api

312
src/lib/method.ts Normal file
View File

@ -0,0 +1,312 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2017-12-14 14:01:03
* @version $Id$
*/
import { defer, SqlErr, parser, escape } from './utils'
console.log(escape(new Date()))
interface Conn {
query(sql: string, cb?: any): void
release(): void
}
class Method {
pool: any
slave: string
db: string
cache: { [prop: string]: any } = {}
constructor(pool: object, slave: string, db: string, table: string) {
this.pool = pool
this.slave = slave
this.db = db
this.cache = { table }
}
private connect() {
let out = defer()
this.pool.getConnection(this.slave, (err: Error, conn: Conn) => {
if (err) {
return out.reject(new SqlErr(`MySQL connect ${err}`))
}
if (this.db) {
conn.query('USE ' + this.db, (err: Error) => {
if (err) {
return out.reject(new SqlErr('Select DB ' + err))
}
out.resolve(conn)
})
} else {
out.resolve(conn)
}
})
return out.promise
}
leftJoin(tables: any[]) {
this.cache.leftJoin = tables
return this
}
rightJoin(tables: any[]) {
this.cache.rightJoin = tables
return this
}
join(tables: any[]) {
this.cache.join = tables
return this
}
/**
* [filter ]
* @param {any} val []
* sql: .filter('name like "foo%" and age > 18')
* func: .filter(function(){return 'name = "xiaoming"'})
* obj: .filter({
* name: {$like: 'foo%'}
* age: {$gt: 18}
* })
* obj, , Readme
*/
filter(val: any) {
this.cache.filter = val
return this
}
/**
* [sort ]
* @param {number }} keys []
* : {name: 1, age: -1} 1, -1
*/
sort(keys: { [prop: string]: number }) {
this.cache.sort = keys
return this
}
// 从第几条记录开始返回, 必须搭配limit使用,否则会被忽略
skip(skip: number) {
this.cache.skip = skip
return this
}
// 返回指定数量的记录
limit(size: number) {
this.cache.size = size
return this
}
// 截取指定范围内的记录
slice(start: number, end: number) {
this.cache.limit = [start, end - start]
return this
}
/**
* [withFields ]
* @param {string[]} fields []
*/
withFields(fields: string[]) {
this.cache.fields = fields
return this
}
// ================================================================
// ====================== 以下方法,才是sql执行 =======================
// ================================================================
/**
* [getAll ]
* @param {any[]} ids [description]
*/
getAll(ids?: any[]) {
if (!this.cache.filter && ids) {
this.cache.filter = { id: { $in: ids } }
}
let {
table,
leftJoin,
rightJoin,
join,
filter,
fields,
sort,
skip,
size,
limit
} = this.cache
// 没有使用 slice方法的前提下, 通过skip/limit补全
if (!limit) {
if (size && size > 0) {
limit = [size]
if (skip !== undefined) {
limit.unshift(skip)
}
}
}
let sql: string
sql = parser.select(fields)
sql += `FROM ${table} `
if (leftJoin) {
sql += parser.leftJoin(leftJoin)
}
if (rightJoin) {
sql += parser.rightJoin(rightJoin)
}
if (join) {
sql += parser.join(join)
}
if (filter) {
sql += parser.filter(filter)
}
if (sort) {
sql += parser.sort(sort)
}
if (limit) {
sql += parser.limit(limit)
}
return this.connect().then((conn: Conn) => {
let out = defer()
conn.query(sql, (err: Error, result: any[]) => {
conn.release()
if (err) {
return out.reject(new SqlErr(`Find ${err}`, sql))
}
out.resolve(result)
})
return out.promise
})
}
/**
* [get ]
* @param {any} id [id, ]
*/
get(id?: any) {
return this.getAll(id ? [id] : null).then((list: any[]) => {
return list[0]
})
}
/**
* [count ]
* @return {number} [description]
*/
count(): number {
return this.getAll().then((list: any[]) => {
return list.length
})
}
/**
* [insert , ID()]
* @param {any }} doc [object]
*/
insert(doc: { [prop: string]: any }) {
if (!doc) {
return Promise.reject(new SqlErr('Insert Error: empty document'))
}
let { table } = this.cache
let sql = `INSERT INTO ${table} `
let keys = []
let vals = []
for (let i in doc) {
keys.push(i)
vals.push(escape(doc[i]))
}
sql += `(${keys.join(',')}) VALUES (${vals.join(',')})`
return this.connect().then((conn: Conn) => {
const out = defer()
conn.query(sql, (err: Error, result: any) => {
conn.release()
if (err) {
return out.reject(new SqlErr(`Insert ${err}`, sql))
}
out.resolve(result.insertId)
})
return out.promise
})
}
/**
* [update , ]
* 使filter
* @param {any }} doc []
*/
update(doc: { [prop: string]: any }) {
if (!doc) {
return Promise.reject(new SqlErr('Update Error: empty document'))
}
let { table, filter } = this.cache
let sql = `UPDATE ${table} SET `
let fields = [] //要更新的字段
for (let i in doc) {
let val = doc[i]
if (typeof val === 'object' && val.$sql) {
val = `(${val.$sql})`
} else {
val = escape(val)
}
fields.push(i + ' = ' + val)
}
sql += fields.join(',')
sql += parser.filter(filter)
return this.connect().then((conn: Conn) => {
const out = defer()
conn.query(sql, (err: Error, result: any) => {
conn.release()
if (err) {
return out.reject(new SqlErr(`Update ${err}`, sql))
}
out.resolve(result.affectedRows)
})
return out.promise
})
}
/**
* [remove , ]
* 使filter
*/
remove() {
let { table, filter } = this.cache
let sql = `DELETE FROM ${table} `
sql += parser.filter(filter)
return this.connect().then((conn: Conn) => {
const out = defer()
conn.query(sql, (err: Error, result: any) => {
conn.release()
if (err) {
return out.reject(new SqlErr(`Remove ${err}`, sql))
}
out.resolve(result.affectedRows)
})
return out.promise
})
}
}
export default Method

View File

@ -6,7 +6,7 @@
*/
const { escape } = require('mysql')
function getType(val) {
function getType(val: any): string {
if (val === null) {
return String(val)
}
@ -15,7 +15,7 @@ function getType(val) {
.slice(8, -1)
.toLowerCase()
}
function parse$or(arr) {
function parse$or(arr: any[]) {
let sql = ''
for (let it of arr) {
sql += '('
@ -29,7 +29,7 @@ function parse$or(arr) {
sql = sql.slice(0, -3)
return sql
}
function parse$and(arr) {
function parse$and(arr: any[]) {
let sql = ''
for (let it of arr) {
sql += '('
@ -44,7 +44,7 @@ function parse$and(arr) {
return sql
}
function parse$opt(opt) {
function parse$opt(opt: { [prop: string]: any }) {
let sql = ''
for (let k in opt) {
let tmp = opt[k]
@ -60,7 +60,7 @@ function parse$opt(opt) {
}
if (tmp.$in) {
let list = tmp.$in.map(it => {
let list = tmp.$in.map((it: any) => {
return escape(it)
})
sql += ` ${k} IN (${list.join(',')}) `
@ -70,7 +70,7 @@ function parse$opt(opt) {
if (tmp.$between.length < 2) {
throw new Error(`Array $between's length must be 2.`)
}
let list = tmp.$between.map(it => {
let list = tmp.$between.map((it: any) => {
return escape(it)
})
sql += ` ${k} BETWEEN ${list[0]} AND ${list[1]} `
@ -102,8 +102,8 @@ function parse$opt(opt) {
return sql
}
const Parser = {
leftJoin(tables) {
export const parser = {
leftJoin(tables: any[]) {
let sql = ''
for (let it of tables) {
sql += ` LEFT JOIN ${it.table} ON ${it.on} `
@ -111,7 +111,7 @@ const Parser = {
return sql
},
rightJoin(tables) {
rightJoin(tables: any[]) {
let sql = ''
for (let it of tables) {
sql += ` RIGHT JOIN ${it.table} ON ${it.on} `
@ -119,7 +119,7 @@ const Parser = {
return sql
},
join(tables) {
join(tables: any[]) {
let sql = ''
for (let it of tables) {
sql += ` JOIN ${it[0]} ON ${it.on} `
@ -127,7 +127,7 @@ const Parser = {
return sql
},
where(opt) {
filter(opt: any) {
if (typeof opt === 'string') {
return ` WHERE ${opt} `
}
@ -146,12 +146,12 @@ const Parser = {
return ' '
},
select(arr = ['*']) {
select(arr: string[] = ['*']) {
return `SELECT ${arr.join(',')} `
},
// 排序 ----------------------------------
sort(obj = {}) {
sort(obj: { [propName: string]: number } = {}) {
let sort = ''
for (let i in obj) {
let c = ''
@ -167,9 +167,28 @@ const Parser = {
}
},
limit(...args) {
limit(...args: number[]) {
return ` LIMIT ${args.join(',')} `
}
}
module.exports = Parser
export class SqlErr extends Error {
sql: string
constructor(msg: string = '', sql: string = '') {
super(msg)
this.sql = sql
}
}
export const defer = () => {
let obj: { [prop: string]: any } = {}
obj.promise = new Promise((yes, no) => {
obj.resolve = yes
obj.reject = no
})
return obj
}
export { escape }
export default escape

19
tsconfig.json Normal file
View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es2015",
"lib": ["es2015"],
"module": "commonjs",
"outDir": "dist/",
"noImplicitAny": true,
"removeComments": false,
"preserveConstEnums": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"pretty": true,
"types" : ["node"],
"noEmitOnError": true,
},
"include": ["src/**/*"],
}