Comparing version 0.0.6 to 0.0.7
@@ -1,7 +0,13 @@ | ||
import Sqlite from 'better-sqlite3'; | ||
export default class Database { | ||
static instance: any; | ||
readonly db: Sqlite.Database; | ||
constructor(file: string, options: Sqlite.Options); | ||
static getInstance(file: string, options?: Sqlite.Options): Database; | ||
import { Database, ISqlite } from 'sqlite'; | ||
export default class DB { | ||
static instances: { | ||
[key: string]: DB; | ||
}; | ||
db: Database; | ||
connecting: any; | ||
private constructor(); | ||
connect(): Promise<Database>; | ||
static getInstance(filename: string, options: Partial<ISqlite.Config>): DB; | ||
exec(sql: string): Promise<void>; | ||
call(method: string, sql: any, params: any): Promise<any>; | ||
} |
120
dist/db.js
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -6,18 +53,67 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var better_sqlite3_1 = __importDefault(require("better-sqlite3")); | ||
var Database = /** @class */ (function () { | ||
function Database(file, options) { | ||
this.db = (0, better_sqlite3_1.default)(file, options); | ||
var sqlite3_1 = __importDefault(require("sqlite3")); | ||
var sqlite_1 = require("sqlite"); | ||
var DB = /** @class */ (function () { | ||
function DB(connection) { | ||
this.db = null; | ||
this.connecting = connection; | ||
} | ||
Database.getInstance = function (file, options) { | ||
if (options === void 0) { options = {}; } | ||
if (Database.instance) { | ||
return Database.instance; | ||
DB.prototype.connect = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
if (!this.connecting) return [3 /*break*/, 2]; | ||
_a = this; | ||
return [4 /*yield*/, this.connecting]; | ||
case 1: | ||
_a.db = _b.sent(); | ||
this.connecting = null; | ||
_b.label = 2; | ||
case 2: return [2 /*return*/, this.db]; | ||
} | ||
}); | ||
}); | ||
}; | ||
DB.getInstance = function (filename, options) { | ||
if (DB.instances[filename]) { | ||
return DB.instances[filename]; | ||
} | ||
return new Database(file, options); | ||
var db = (0, sqlite_1.open)(__assign({ filename: filename, driver: sqlite3_1.default.cached.Database }, options)); | ||
DB.instances[filename] = new DB(db); | ||
return DB.instances[filename]; | ||
}; | ||
Database.instance = null; | ||
return Database; | ||
DB.prototype.exec = function (sql) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.connect()]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/, this.db.exec(sql)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
DB.prototype.call = function (method, sql, params) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var stmt; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.connect()]; | ||
case 1: | ||
_a.sent(); | ||
return [4 /*yield*/, this.db.prepare(sql)]; | ||
case 2: | ||
stmt = _a.sent(); | ||
return [2 /*return*/, stmt[method](params)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
DB.instances = {}; | ||
return DB; | ||
}()); | ||
exports.default = Database; | ||
exports.default = DB; | ||
//# sourceMappingURL=db.js.map |
@@ -1,2 +0,1 @@ | ||
import { Options } from 'better-sqlite3'; | ||
export declare type Dict = { | ||
@@ -15,7 +14,11 @@ [key: string]: any; | ||
} | ||
export interface Connection { | ||
filename: string; | ||
mode?: number; | ||
driver?: any; | ||
} | ||
export interface ModelOpts { | ||
dbFile?: string; | ||
table?: string; | ||
dbOptions?: Options; | ||
connection?: Connection; | ||
schema?: Schema; | ||
} |
@@ -1,3 +0,4 @@ | ||
import Sqlite from 'better-sqlite3'; | ||
import { Dict, Schema, ModelOpts } from './interface'; | ||
import DB from './db'; | ||
import { ISqlite } from 'sqlite'; | ||
export declare class Model { | ||
@@ -11,7 +12,10 @@ private _db; | ||
readonly _options: ModelOpts; | ||
_attributes: Dict; | ||
private _attributes; | ||
[key: string]: any; | ||
constructor(options: ModelOpts); | ||
get db(): Sqlite.Database; | ||
get db(): DB | null; | ||
initialize(config: ModelOpts): void; | ||
attr(name: string, value: any): void; | ||
getAttr(name: string): any; | ||
change(name: string, value: any): void; | ||
clone(): Model; | ||
@@ -21,18 +25,18 @@ instance(data: Dict): Model; | ||
toJSON(): Dict; | ||
exec(sql: string): any; | ||
find(where: Dict, options?: Dict): Model[]; | ||
count(where: Dict): number; | ||
findOne(where: Dict, options?: Dict): Model | null; | ||
findAll(where: Dict, options?: Dict): Model[]; | ||
findById(id: bigint | number): Model | null; | ||
findByIds(ids: number[]): Model[]; | ||
create(data: Dict): Model; | ||
insert(data: Dict): Model; | ||
update(where: Dict, data: Dict): Model[]; | ||
updateAttributes(data: Dict): Model; | ||
upsert(data: Dict): Model; | ||
save(): Model; | ||
remove(): Sqlite.RunResult; | ||
deleteById(id: number): boolean; | ||
delete(where: Dict): Sqlite.RunResult; | ||
exec(sql: string): Promise<void>; | ||
find(where: Dict, options?: Dict): Promise<Model[]>; | ||
count(where: Dict): Promise<number>; | ||
findOne(where: Dict, options?: Dict): Promise<Model | null>; | ||
findAll(where: Dict, options?: Dict): Promise<Model[]>; | ||
findById(id: bigint | number): Promise<Model | null>; | ||
findByIds(ids: number[]): Promise<Model[]>; | ||
create(data: Dict): Promise<Model>; | ||
insert(data: Dict): Promise<Model>; | ||
update(where: Dict, data: Dict): Promise<ISqlite.RunResult>; | ||
updateAttributes(data: Dict): Promise<Model>; | ||
upsert(data: Dict): Promise<Model>; | ||
save(): Promise<Model>; | ||
remove(): Promise<ISqlite.RunResult>; | ||
deleteById(id: number): Promise<boolean>; | ||
delete(where: Dict): Promise<ISqlite.RunResult>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -17,2 +53,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
this._options = options; | ||
this._connected = false; | ||
this.initialize(options); | ||
@@ -22,3 +59,3 @@ } | ||
get: function () { | ||
return this._db.db; | ||
return this._db; | ||
}, | ||
@@ -32,5 +69,2 @@ enumerable: false, | ||
} | ||
if (config.dbFile) { | ||
this._dbFile = config.dbFile; | ||
} | ||
if (config.schema) { | ||
@@ -42,3 +76,2 @@ this._schema = config.schema; | ||
} | ||
this._db = db_1.default.getInstance(this._dbFile, config.dbOptions); | ||
for (var key in this._schema) { | ||
@@ -49,7 +82,17 @@ if (this._schema[key].pk) { | ||
} | ||
this._db = db_1.default.getInstance(this._dbFile, this._options.connection); | ||
return; | ||
}; | ||
Model.prototype.attr = function (name, value) { | ||
this._attributes[name] = value; | ||
if (this._attributes[name] !== value) { | ||
this._attributes[name] = value; | ||
} | ||
}; | ||
Model.prototype.getAttr = function (name) { | ||
return this._attributes[name]; | ||
}; | ||
Model.prototype.change = function (name, value) { | ||
this.attr(name, value); | ||
this._changed[name] = value; | ||
}; | ||
Model.prototype.clone = function () { | ||
@@ -64,6 +107,6 @@ return new this.constructor(this._options); | ||
set: function (value) { | ||
instance.attr(key, value); | ||
instance.change(key, value); | ||
}, | ||
get: function () { | ||
return instance._attributes[key]; | ||
return instance.getAttr(key); | ||
} | ||
@@ -87,35 +130,63 @@ }); | ||
Model.prototype.find = function (where, options) { | ||
var _this = this; | ||
if (options === void 0) { options = {}; } | ||
var limit = options.limit, offset = options.offset, order = options.order, fields = options.fields, group = options.group; | ||
var builder = new builder_1.Builder({}); | ||
var _a = builder.table(this._table) | ||
.where(where) | ||
.fields(fields) | ||
.order(order) | ||
.group(group) | ||
.limit(limit) | ||
.offset(offset) | ||
.select(), sql = _a.sql, params = _a.params; | ||
var stmt = this.db.prepare(sql); | ||
var res = stmt.all.apply(stmt, params); | ||
if (options.rows) { | ||
return res; | ||
} | ||
return res.map(function (item) { | ||
return _this.instance(item); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var limit, offset, order, fields, group, builder, _a, sql, params, res; | ||
var _this = this; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
limit = options.limit, offset = options.offset, order = options.order, fields = options.fields, group = options.group; | ||
builder = new builder_1.Builder({}); | ||
_a = builder.table(this._table) | ||
.where(where) | ||
.fields(fields) | ||
.order(order) | ||
.group(group) | ||
.limit(limit) | ||
.offset(offset) | ||
.select(), sql = _a.sql, params = _a.params; | ||
return [4 /*yield*/, this.db.call('all', sql, params)]; | ||
case 1: | ||
res = _b.sent(); | ||
if (options.rows) { | ||
return [2 /*return*/, res]; | ||
} | ||
return [2 /*return*/, res.map(function (item) { | ||
return _this.instance(item); | ||
})]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Model.prototype.count = function (where) { | ||
var res = this.findOne(where, { fields: ['count(*) as count'] }); | ||
return Number(res.count); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var res; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.findOne(where, { fields: ['count(*) as count'] })]; | ||
case 1: | ||
res = _a.sent(); | ||
return [2 /*return*/, Number(res.count)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Model.prototype.findOne = function (where, options) { | ||
if (options === void 0) { options = {}; } | ||
options.limit = 1; | ||
var res = this.find(where, options); | ||
if (res.length) { | ||
return res[0]; | ||
} | ||
return null; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var res; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
options.limit = 1; | ||
return [4 /*yield*/, this.find(where, options)]; | ||
case 1: | ||
res = _a.sent(); | ||
if (res.length) { | ||
return [2 /*return*/, res[0]]; | ||
} | ||
return [2 /*return*/, null]; | ||
} | ||
}); | ||
}); | ||
}; | ||
@@ -133,20 +204,39 @@ Model.prototype.findAll = function (where, options) { | ||
Model.prototype.create = function (data) { | ||
return this.insert(data); | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.insert(data)]; | ||
}); | ||
}); | ||
}; | ||
Model.prototype.insert = function (data) { | ||
var _a; | ||
var builder = new builder_1.Builder({}); | ||
var _b = builder.table(this._table).insert(data), sql = _b.sql, params = _b.params; | ||
console.log(sql, params); | ||
var lastInsertRowid = (_a = this.db.prepare(sql)).run.apply(_a, params).lastInsertRowid; | ||
return this.findById(lastInsertRowid); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var builder, _a, sql, params, lastID; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
builder = new builder_1.Builder({}); | ||
_a = builder.table(this._table).insert(data), sql = _a.sql, params = _a.params; | ||
return [4 /*yield*/, this.db.call('run', sql, params)]; | ||
case 1: | ||
lastID = (_b.sent()).lastID; | ||
return [2 /*return*/, this.findById(lastID)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Model.prototype.update = function (where, data) { | ||
var _a; | ||
var builder = new builder_1.Builder({}); | ||
var _b = builder.table(this._table) | ||
.where(where) | ||
.update(data), sql = _b.sql, params = _b.params; | ||
(_a = this.db.prepare(sql)).run.apply(_a, params); | ||
return this.find(where); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var builder, _a, sql, params; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
builder = new builder_1.Builder({}); | ||
_a = builder.table(this._table) | ||
.where(where) | ||
.update(data), sql = _a.sql, params = _a.params; | ||
return [4 /*yield*/, this.db.call('run', sql, params)]; | ||
case 1: return [2 /*return*/, _b.sent()]; | ||
} | ||
}); | ||
}); | ||
}; | ||
@@ -168,20 +258,40 @@ Model.prototype.updateAttributes = function (data) { | ||
Model.prototype.upsert = function (data) { | ||
if (data.id) { | ||
var record = this.findById(data.id); | ||
if (record) { | ||
return record.updateAttributes(data); | ||
} | ||
} | ||
return this.insert(data); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var record; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!data.id) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, this.findById(data.id)]; | ||
case 1: | ||
record = _a.sent(); | ||
if (record) { | ||
return [2 /*return*/, record.updateAttributes(data)]; | ||
} | ||
_a.label = 2; | ||
case 2: return [2 /*return*/, this.insert(data)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Model.prototype.save = function () { | ||
var pk = (0, ramda_1.pick)(this._pk, this._attributes); | ||
if (!this._pk || (0, ramda_1.isEmpty)(pk)) { | ||
throw new Error('save must be called on instance'); | ||
} | ||
if (!Object.keys(this._changed).length) { | ||
return this; | ||
} | ||
var instance = this.update(pk, this._changed)[0]; | ||
return instance; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var pk; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
pk = (0, ramda_1.pick)(this._pk, this._attributes); | ||
if (!this._pk || (0, ramda_1.isEmpty)(pk)) { | ||
throw new Error('save must be called on instance'); | ||
} | ||
if (!Object.keys(this._changed).length) { | ||
return [2 /*return*/, this]; | ||
} | ||
return [4 /*yield*/, this.update(pk, this._changed)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/, this.findOne(pk)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
@@ -196,21 +306,38 @@ Model.prototype.remove = function () { | ||
Model.prototype.deleteById = function (id) { | ||
var _a; | ||
var record = this.findById(id); | ||
if (!record) { | ||
return false; | ||
} | ||
var builder = new builder_1.Builder({}); | ||
var _b = builder.table(this._table) | ||
.where({ id: id }) | ||
.delete(), sql = _b.sql, params = _b.params; | ||
(_a = this.db.prepare(sql)).run.apply(_a, params); | ||
return true; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var record, builder, _a, sql, params; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
record = this.findById(id); | ||
if (!record) { | ||
return [2 /*return*/, false]; | ||
} | ||
builder = new builder_1.Builder({}); | ||
_a = builder.table(this._table) | ||
.where({ id: id }) | ||
.delete(), sql = _a.sql, params = _a.params; | ||
return [4 /*yield*/, this.db.call('run', sql, params)]; | ||
case 1: | ||
_b.sent(); | ||
return [2 /*return*/, true]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Model.prototype.delete = function (where) { | ||
var _a; | ||
var builder = new builder_1.Builder({}); | ||
var _b = builder.table(this._table) | ||
.where(where) | ||
.delete(), sql = _b.sql, params = _b.params; | ||
return (_a = this.db.prepare(sql)).run.apply(_a, params); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var builder, _a, sql, params; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
builder = new builder_1.Builder({}); | ||
_a = builder.table(this._table) | ||
.where(where) | ||
.delete(), sql = _a.sql, params = _a.params; | ||
return [4 /*yield*/, this.db.call('run', sql, params)]; | ||
case 1: return [2 /*return*/, _b.sent()]; | ||
} | ||
}); | ||
}); | ||
}; | ||
@@ -217,0 +344,0 @@ return Model; |
@@ -1,16 +0,45 @@ | ||
import Sqlite from 'better-sqlite3'; | ||
import sqlite3 from 'sqlite3' | ||
import { open, Database, ISqlite } from 'sqlite'; | ||
import { Connection } from './interface'; | ||
export default class Database { | ||
static instance = null; | ||
readonly db: Sqlite.Database; | ||
constructor(file: string, options: Sqlite.Options) { | ||
this.db = Sqlite(file, options); | ||
export default class DB { | ||
static instances: { [key: string]: DB } = {}; | ||
db: Database; | ||
connecting: any; | ||
private constructor(connection: Promise<Database>) { | ||
this.db = null; | ||
this.connecting = connection; | ||
} | ||
static getInstance(file: string, options: Sqlite.Options = {}): Database { | ||
if (Database.instance) { | ||
return Database.instance; | ||
async connect(): Promise<Database> { | ||
if (this.connecting) { | ||
this.db = await this.connecting; | ||
this.connecting = null; | ||
} | ||
return new Database(file, options); | ||
return this.db; | ||
} | ||
static getInstance(filename: string, options: Partial<ISqlite.Config>): DB { | ||
if (DB.instances[filename]) { | ||
return DB.instances[filename]; | ||
} | ||
const db = open({ | ||
filename, | ||
driver: sqlite3.cached.Database, | ||
...options, | ||
}); | ||
DB.instances[filename] = new DB(db); | ||
return DB.instances[filename]; | ||
} | ||
async exec(sql: string): Promise<void> { | ||
await this.connect(); | ||
return this.db.exec(sql); | ||
} | ||
async call(method: string, sql, params): Promise<any> { | ||
await this.connect(); | ||
const stmt = await this.db.prepare(sql); | ||
return stmt[method](params); | ||
} | ||
} |
@@ -1,2 +0,1 @@ | ||
import { Options } from 'better-sqlite3'; | ||
export type Dict = { | ||
@@ -18,7 +17,12 @@ [key: string]: any | ||
export interface Connection { | ||
filename: string; | ||
mode?: number; | ||
driver?: any; | ||
} | ||
export interface ModelOpts { | ||
dbFile?: string; | ||
table?: string; | ||
dbOptions?: Options; | ||
connection?: Connection; | ||
schema?: Schema; | ||
} | ||
} |
@@ -1,2 +0,1 @@ | ||
import Sqlite from 'better-sqlite3'; | ||
import { Builder } from './builder'; | ||
@@ -6,3 +5,5 @@ import { Dict, Schema, ModelOpts } from './interface'; | ||
import { isEmpty, pick, has } from 'ramda'; | ||
import { ISqlite } from 'sqlite'; | ||
export class Model { | ||
@@ -16,3 +17,4 @@ private _db: DB; | ||
readonly _options: ModelOpts; | ||
public _attributes: Dict; | ||
private _attributes: Dict; | ||
[key: string]: any; | ||
constructor(options: ModelOpts) { | ||
@@ -23,10 +25,12 @@ this._attributes = {}; | ||
this._options = options; | ||
this._connected = false; | ||
this.initialize(options); | ||
} | ||
get db(): Sqlite.Database { | ||
return this._db.db; | ||
get db(): DB | null { | ||
return this._db; | ||
} | ||
initialize(config: ModelOpts): void { | ||
@@ -36,5 +40,2 @@ if (this._db) { | ||
} | ||
if (config.dbFile) { | ||
this._dbFile = config.dbFile; | ||
} | ||
if (config.schema) { | ||
@@ -46,3 +47,2 @@ this._schema = config.schema; | ||
} | ||
this._db = DB.getInstance(this._dbFile, config.dbOptions); | ||
for (const key in this._schema) { | ||
@@ -53,2 +53,3 @@ if (this._schema[key].pk) { | ||
} | ||
this._db = DB.getInstance(this._dbFile, this._options.connection as ISqlite.Config); | ||
return; | ||
@@ -100,7 +101,8 @@ } | ||
exec(sql: string): any { | ||
exec(sql: string): Promise<void> { | ||
return this.db.exec(sql); | ||
} | ||
find(where: Dict, options: Dict = {}): Model[] { | ||
async find(where: Dict, options: Dict = {}): Promise<Model[]> { | ||
const { limit, offset, order, fields, group } = options; | ||
@@ -116,8 +118,7 @@ const builder = new Builder({}); | ||
.select(); | ||
const stmt = this.db.prepare(sql); | ||
const res = stmt.all(...params); | ||
const res = await this.db.call('all', sql, params); | ||
if (options.rows) { | ||
return res; | ||
} | ||
return res.map(item => { | ||
return res.map((item) => { | ||
return this.instance(item); | ||
@@ -127,10 +128,10 @@ }) | ||
count(where: Dict): number { | ||
const res = this.findOne(where, { fields: ['count(*) as count'] }); | ||
async count(where: Dict): Promise<number> { | ||
const res = await this.findOne(where, { fields: ['count(*) as count'] }); | ||
return Number(res.count); | ||
} | ||
findOne(where: Dict, options: Dict = {}): Model | null { | ||
async findOne(where: Dict, options: Dict = {}): Promise<Model | null> { | ||
options.limit = 1; | ||
const res = this.find(where, options); | ||
const res = await this.find(where, options); | ||
if (res.length) { | ||
@@ -142,25 +143,26 @@ return res[0]; | ||
findAll(where: Dict, options: Dict = {}): Model[] { | ||
findAll(where: Dict, options: Dict = {}): Promise<Model[]> { | ||
return this.find(where, options); | ||
} | ||
findById(id: bigint | number): Model | null { | ||
findById(id: bigint | number): Promise<Model | null> { | ||
return this.findOne({ id }); | ||
} | ||
findByIds(ids: number[]): Model[] { | ||
findByIds(ids: number[]): Promise<Model[]> { | ||
return this.find({ id: { '$in': ids } }); | ||
} | ||
create(data: Dict): Model { | ||
async create(data: Dict): Promise<Model> { | ||
return this.insert(data); | ||
} | ||
insert(data: Dict): Model { | ||
async insert(data: Dict): Promise<Model> { | ||
const builder = new Builder({}); | ||
const { sql, params } = builder.table(this._table).insert(data); | ||
const { lastInsertRowid } = this.db.prepare(sql).run(...params); | ||
return this.findById(lastInsertRowid); | ||
const { lastID } = await this.db.call('run', sql, params); | ||
return this.findById(lastID); | ||
} | ||
update(where: Dict, data: Dict): Model[] { | ||
async update(where: Dict, data: Dict): Promise<ISqlite.RunResult> { | ||
const builder = new Builder({}); | ||
@@ -170,7 +172,6 @@ const { sql, params } = builder.table(this._table) | ||
.update(data); | ||
this.db.prepare(sql).run(...params); | ||
return this.find(where); | ||
return await this.db.call('run', sql, params); | ||
} | ||
updateAttributes(data: Dict): Model { | ||
updateAttributes(data: Dict): Promise<Model> { | ||
if (!this._pk) { | ||
@@ -190,5 +191,5 @@ throw new Error('updateAttributes must be called on instance'); | ||
upsert(data: Dict): Model { | ||
async upsert(data: Dict): Promise<Model> { | ||
if (data.id) { | ||
const record = this.findById(data.id); | ||
const record = await this.findById(data.id); | ||
if (record) { | ||
@@ -202,3 +203,3 @@ return record.updateAttributes(data); | ||
save(): Model { | ||
async save(): Promise<Model> { | ||
const pk = pick(this._pk, this._attributes); | ||
@@ -211,8 +212,8 @@ if (!this._pk || isEmpty(pk)) { | ||
} | ||
const [instance] = this.update(pk, this._changed); | ||
return instance; | ||
await this.update(pk, this._changed); | ||
return this.findOne(pk); | ||
} | ||
remove(): Sqlite.RunResult { | ||
remove(): Promise<ISqlite.RunResult> { | ||
const pk = pick(this._pk, this._attributes) | ||
@@ -225,3 +226,4 @@ if (!this._pk || isEmpty(pk)) { | ||
} | ||
deleteById(id: number): boolean { | ||
async deleteById(id: number): Promise<boolean> { | ||
const record = this.findById(id); | ||
@@ -235,7 +237,7 @@ if (!record) { | ||
.delete(); | ||
this.db.prepare(sql).run(...params); | ||
await this.db.call('run', sql, params); | ||
return true; | ||
} | ||
delete(where: Dict): Sqlite.RunResult { | ||
async delete(where: Dict): Promise<ISqlite.RunResult> { | ||
const builder = new Builder({}); | ||
@@ -245,5 +247,5 @@ const { sql, params } = builder.table(this._table) | ||
.delete(); | ||
return this.db.prepare(sql).run(...params); | ||
return await this.db.call('run', sql, params); | ||
} | ||
} | ||
{ | ||
"name": "lite-model", | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"main": "dist/index.js", | ||
@@ -15,9 +15,9 @@ "scripts": { | ||
"@typescript-eslint/parser": "^4.33.0", | ||
"better-sqlite3": "^7.4.4", | ||
"eslint": "^7.32.0", | ||
"printj": "^1.3.0", | ||
"ramda": "^0.27.1" | ||
"ramda": "^0.27.1", | ||
"sqlite": "^4.1.1", | ||
"sqlite3": "^5.0.6" | ||
}, | ||
"devDependencies": { | ||
"@types/better-sqlite3": "^7.4.0", | ||
"@types/node": "^16.10.2", | ||
@@ -24,0 +24,0 @@ "@types/ramda": "^0.27.45", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
75058
6
1586
7
32
+ Addedsqlite@^4.1.1
+ Addedsqlite3@^5.0.6
+ Added@gar/promisify@1.1.3(transitive)
+ Added@npmcli/fs@1.1.1(transitive)
+ Added@npmcli/move-file@1.1.2(transitive)
+ Added@tootallnate/once@1.1.2(transitive)
+ Addedabbrev@1.1.1(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedagentkeepalive@4.6.0(transitive)
+ Addedaggregate-error@3.1.0(transitive)
+ Addedaproba@2.0.0(transitive)
+ Addedare-we-there-yet@3.0.1(transitive)
+ Addedcacache@15.3.0(transitive)
+ Addedchownr@2.0.0(transitive)
+ Addedclean-stack@2.2.0(transitive)
+ Addedcolor-support@1.1.3(transitive)
+ Addedconsole-control-strings@1.1.0(transitive)
+ Addeddelegates@1.0.0(transitive)
+ Addedencoding@0.1.13(transitive)
+ Addedenv-paths@2.2.1(transitive)
+ Addederr-code@2.0.3(transitive)
+ Addedfs-minipass@2.1.0(transitive)
+ Addedgauge@4.0.4(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhas-unicode@2.0.1(transitive)
+ Addedhttp-cache-semantics@4.1.1(transitive)
+ Addedhttp-proxy-agent@4.0.1(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedhumanize-ms@1.2.1(transitive)
+ Addediconv-lite@0.6.3(transitive)
+ Addedindent-string@4.0.0(transitive)
+ Addedinfer-owner@1.0.4(transitive)
+ Addedip-address@9.0.5(transitive)
+ Addedis-lambda@1.0.1(transitive)
+ Addedjsbn@1.1.0(transitive)
+ Addedlru-cache@6.0.0(transitive)
+ Addedmake-fetch-happen@9.1.0(transitive)
+ Addedminipass@3.3.65.0.0(transitive)
+ Addedminipass-collect@1.0.2(transitive)
+ Addedminipass-fetch@1.4.1(transitive)
+ Addedminipass-flush@1.0.5(transitive)
+ Addedminipass-pipeline@1.2.4(transitive)
+ Addedminipass-sized@1.0.3(transitive)
+ Addedminizlib@2.1.2(transitive)
+ Addedmkdirp@1.0.4(transitive)
+ Addednegotiator@0.6.4(transitive)
+ Addednode-addon-api@7.1.1(transitive)
+ Addednode-gyp@8.4.1(transitive)
+ Addednopt@5.0.0(transitive)
+ Addednpmlog@6.0.2(transitive)
+ Addedp-map@4.0.0(transitive)
+ Addedpromise-inflight@1.0.1(transitive)
+ Addedpromise-retry@2.0.1(transitive)
+ Addedretry@0.12.0(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedsmart-buffer@4.2.0(transitive)
+ Addedsocks@2.8.4(transitive)
+ Addedsocks-proxy-agent@6.2.1(transitive)
+ Addedsprintf-js@1.1.3(transitive)
+ Addedsqlite@4.2.1(transitive)
+ Addedsqlite3@5.1.7(transitive)
+ Addedssri@8.0.1(transitive)
+ Addedtar@6.2.1(transitive)
+ Addedunique-filename@1.1.1(transitive)
+ Addedunique-slug@2.0.2(transitive)
+ Addedwide-align@1.1.5(transitive)
+ Addedyallist@4.0.0(transitive)
- Removedbetter-sqlite3@^7.4.4
- Removedbetter-sqlite3@7.6.2(transitive)