Comparing version
@@ -1,3 +0,2 @@ | ||
export { Repository } from './repository'; | ||
export { Transaction } from './transaction'; | ||
export { LilORMModule } from './module'; | ||
export * from "./core"; | ||
export * from "./api"; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.LilORMModule = exports.Transaction = exports.Repository = void 0; | ||
var repository_1 = require("./repository"); | ||
Object.defineProperty(exports, "Repository", { enumerable: true, get: function () { return repository_1.Repository; } }); | ||
var transaction_1 = require("./transaction"); | ||
Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_1.Transaction; } }); | ||
var module_1 = require("./module"); | ||
Object.defineProperty(exports, "LilORMModule", { enumerable: true, get: function () { return module_1.LilORMModule; } }); | ||
__exportStar(require("./core"), exports); | ||
__exportStar(require("./api"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "lil-orm", | ||
"version": "0.1.0", | ||
"description": "A sqlite3 ORM for Node.js", | ||
"version": "0.1.1", | ||
"description": "Lil ORM is a super lightweight SQLite ORM for Node.js. With its clear API, you can easily interact with SQLite databases.", | ||
"main": "dist/index.js", | ||
@@ -6,0 +6,0 @@ "types": "dist/index.d.ts", |
138
README.md
@@ -1,2 +0,136 @@ | ||
# lil-orm | ||
A lightweight sqlite3 ORM | ||
# Lil ORM | ||
Lil ORM is a super lightweight SQLite ORM for Node.js. With its clear API, you can easily interact with SQLite databases | ||
# Install | ||
``` | ||
npm i lil-orm | ||
``` | ||
# Define Entity | ||
``` | ||
@Entity('user') | ||
class UserEntity { | ||
@PrimaryKey({ | ||
autoIncrement: true, | ||
}) | ||
@Column({ | ||
type: 'INTEGER', | ||
name: 'id', | ||
}) | ||
id: number; | ||
@Column({ | ||
type: 'TEXT', | ||
name: 'name', | ||
}) | ||
name: string; | ||
@Column({ | ||
type: 'TEXT', | ||
name: 'email', | ||
}) | ||
email: string; | ||
@Column({ | ||
type: 'JSON', | ||
name: 'config', | ||
}) | ||
config: any; | ||
@Column({ | ||
type: 'BOOLEAN', | ||
name: 'is_active', | ||
}) | ||
isActive: boolean; | ||
@Column({ | ||
type: 'DATE', | ||
name: 'created_at', | ||
}) | ||
createdAt: Date; | ||
} | ||
``` | ||
supported types: | ||
- TEXT | ||
- INTEGER | ||
- REAL | ||
- BOOLEAN | ||
- DATE (ISO Format) | ||
- JSON | ||
# Module Setup | ||
``` | ||
import { LilORMModule } from 'lil-orm'; | ||
const databaseConnectionString = ':memory:'; | ||
const module = new LilORM(databaseConnectionString); | ||
``` | ||
# Create Table | ||
(experimental API name) | ||
``` | ||
module.createTable(UserEntity) //to create a table from an entity | ||
``` | ||
# CRUD Operations | ||
``` | ||
//get repository for DAO | ||
const repository = module.getRepository<UserEntity>(UserEntity); | ||
//Create | ||
await repository.create({ | ||
id: 1, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
config: { | ||
test: true, | ||
}, | ||
isActive: true, | ||
createdAt: new Date(), | ||
}); | ||
//Find one | ||
await repository.findOne({ id: 1 }); | ||
//Find all | ||
await repository.findAll(); | ||
//Update | ||
const updatedUser = { | ||
id: 1, | ||
email: 'updated@gmail.com', | ||
name: 'updated', | ||
}; | ||
await repository.update(updatedUser); | ||
//Delete | ||
await repository.delete({ id: 69 }); | ||
``` | ||
# Transactions | ||
``` | ||
import { Transaction } from 'lil-orm'; | ||
const repository = module.getRepository<UserEntity>(UserEntity); | ||
const transaction = new Transaction(repository.dbInstance); | ||
transaction.transaction(async (transaction) => { | ||
repository.create( | ||
{ | ||
id: 1, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
config: { | ||
test: true, | ||
}, | ||
isActive: true, | ||
createdAt: new Date(), | ||
}, | ||
transaction, | ||
); | ||
}); | ||
``` | ||
@@ -1,7 +0,7 @@ | ||
import 'reflect-metadata'; | ||
import { Column, Entity, PrimaryKey } from '../core/decorators'; | ||
import { LilORMModule } from '../core/module'; | ||
import { Transaction } from '../core/transaction'; | ||
import "reflect-metadata"; | ||
import { Column, Entity, PrimaryKey } from "../core/decorators"; | ||
import { LilORM } from "../"; | ||
import { Transaction } from "../core/transaction"; | ||
@Entity('user') | ||
@Entity("user") | ||
class UserEntity { | ||
@@ -12,4 +12,4 @@ @PrimaryKey({ | ||
@Column({ | ||
type: 'INTEGER', | ||
name: 'id', | ||
type: "INTEGER", | ||
name: "id", | ||
}) | ||
@@ -19,4 +19,4 @@ id: number; | ||
@Column({ | ||
type: 'TEXT', | ||
name: 'name', | ||
type: "TEXT", | ||
name: "name", | ||
}) | ||
@@ -26,4 +26,4 @@ name: string; | ||
@Column({ | ||
type: 'TEXT', | ||
name: 'email', | ||
type: "TEXT", | ||
name: "email", | ||
}) | ||
@@ -33,4 +33,4 @@ email: string; | ||
@Column({ | ||
type: 'JSON', | ||
name: 'config', | ||
type: "JSON", | ||
name: "config", | ||
}) | ||
@@ -40,4 +40,4 @@ config: any; | ||
@Column({ | ||
type: 'BOOLEAN', | ||
name: 'is_active', | ||
type: "BOOLEAN", | ||
name: "is_active", | ||
}) | ||
@@ -47,4 +47,4 @@ isActive: boolean; | ||
@Column({ | ||
type: 'DATE', | ||
name: 'created_at', | ||
type: "DATE", | ||
name: "created_at", | ||
}) | ||
@@ -54,10 +54,7 @@ createdAt: Date; | ||
describe('LilORMModule', () => { | ||
const databaseConnectionString = ':memory:'; | ||
describe("LilORM", () => { | ||
const databaseConnectionString = ":memory:"; | ||
it('should instantiate LilORMModule', () => { | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [], | ||
}); | ||
it("should instantiate LilORM", () => { | ||
const module = new LilORM(databaseConnectionString); | ||
@@ -67,25 +64,19 @@ expect(module).toBeDefined(); | ||
it('should migrate the database schema', async () => { | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [UserEntity], | ||
}); | ||
it("should migrate the database schema", async () => { | ||
const module = new LilORM(databaseConnectionString); | ||
await module.migrate(); | ||
await module.createTable(UserEntity); | ||
// Assert that the migration was successful by checking if the table exists in the database | ||
const tableExists = await module.tableExists('user'); | ||
const tableExists = await module.tableExists("user"); | ||
expect(tableExists).toBeTruthy(); | ||
}); | ||
it('should create a new user in the database', async () => { | ||
it("should create a new user in the database", async () => { | ||
// Arrange | ||
// ... (Same code as in the original test) | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [UserEntity], | ||
}); | ||
const module = new LilORM(databaseConnectionString); | ||
await module.migrate(); | ||
await module.createTable(UserEntity); | ||
@@ -97,4 +88,4 @@ const repository = module.getRepository<UserEntity>(UserEntity); | ||
id: 1, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
email: "test@gmail.com", | ||
name: "test", | ||
config: { | ||
@@ -110,4 +101,4 @@ test: true, | ||
expect(user).toBeDefined(); | ||
expect(user?.email).toBe('test@gmail.com'); | ||
expect(user?.name).toBe('test'); | ||
expect(user?.email).toBe("test@gmail.com"); | ||
expect(user?.name).toBe("test"); | ||
expect(user?.createdAt).toBeInstanceOf(Date); | ||
@@ -118,12 +109,9 @@ expect(user?.isActive).toBe(true); | ||
it('should retrieve all users from the database', async () => { | ||
it("should retrieve all users from the database", async () => { | ||
// Arrange | ||
// ... (Same code as in the original test) | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [UserEntity], | ||
}); | ||
const module = new LilORM(databaseConnectionString); | ||
await module.migrate(); | ||
await module.createTable(UserEntity); | ||
@@ -134,4 +122,4 @@ const repository = module.getRepository<UserEntity>(UserEntity); | ||
id: 1, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
email: "test@gmail.com", | ||
name: "test", | ||
config: { | ||
@@ -149,16 +137,13 @@ test: true, | ||
expect(users.length).toBe(1); | ||
expect(users[0].email).toBe('test@gmail.com'); | ||
expect(users[0].name).toBe('test'); | ||
expect(users[0].email).toBe("test@gmail.com"); | ||
expect(users[0].name).toBe("test"); | ||
}); | ||
it('should update a user in the database', async () => { | ||
it("should update a user in the database", async () => { | ||
// Arrange | ||
// ... (Same code as in the original test) | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [UserEntity], | ||
}); | ||
const module = new LilORM(databaseConnectionString); | ||
await module.migrate(); | ||
await module.createTable(UserEntity); | ||
@@ -169,4 +154,4 @@ const repository = module.getRepository<UserEntity>(UserEntity); | ||
id: 1, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
email: "test@gmail.com", | ||
name: "test", | ||
config: { | ||
@@ -182,4 +167,4 @@ test: true, | ||
id: 1, | ||
email: 'updated@gmail.com', | ||
name: 'updated', | ||
email: "updated@gmail.com", | ||
name: "updated", | ||
}; | ||
@@ -190,16 +175,13 @@ await repository.update(updatedUser); | ||
const user = await repository.findOne({ id: 1 }); | ||
expect(user?.email).toBe('updated@gmail.com'); | ||
expect(user?.name).toBe('updated'); | ||
expect(user?.email).toBe("updated@gmail.com"); | ||
expect(user?.name).toBe("updated"); | ||
}); | ||
it('should delete a user from the database', async () => { | ||
it("should delete a user from the database", async () => { | ||
// Arrange | ||
// ... (Same code as in the original test) | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [UserEntity], | ||
}); | ||
const module = new LilORM(databaseConnectionString); | ||
await module.migrate(); | ||
await module.createTable(UserEntity); | ||
@@ -210,4 +192,4 @@ const repository = module.getRepository<UserEntity>(UserEntity); | ||
id: 69, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
email: "test@gmail.com", | ||
name: "test", | ||
config: { | ||
@@ -229,9 +211,6 @@ test: true, | ||
it('should begin a transaction', async () => { | ||
const module = new LilORMModule({ | ||
database: databaseConnectionString, | ||
entities: [UserEntity], | ||
}); | ||
it("should begin a transaction", async () => { | ||
const module = new LilORM(databaseConnectionString); | ||
await module.migrate(); | ||
await module.createTable(UserEntity); | ||
@@ -246,4 +225,4 @@ const repository = module.getRepository<UserEntity>(UserEntity); | ||
id: 1, | ||
email: 'test@gmail.com', | ||
name: 'test', | ||
email: "test@gmail.com", | ||
name: "test", | ||
config: { | ||
@@ -255,3 +234,3 @@ test: true, | ||
}, | ||
transaction, | ||
transaction | ||
); | ||
@@ -258,0 +237,0 @@ //throw new Error('test'); |
@@ -1,5 +0,5 @@ | ||
export const ENTITY_METADATA_KEY = 'entity'; | ||
export const COLUMN_METADATA_KEY = 'column'; | ||
export const PRIMARY_KEY_METADATA_KEY = 'primary-key'; | ||
export const ENTITY_METADATA_KEY = "entity"; | ||
export const COLUMN_METADATA_KEY = "column"; | ||
export const PRIMARY_KEY_METADATA_KEY = "primary-key"; | ||
export const RADIX = 10; | ||
export const RADIX = 10; |
@@ -1,3 +0,7 @@ | ||
import { COLUMN_METADATA_KEY, ENTITY_METADATA_KEY, PRIMARY_KEY_METADATA_KEY } from './constants'; | ||
import { LilORMType, SQLiteType } from './types'; | ||
import { | ||
COLUMN_METADATA_KEY, | ||
ENTITY_METADATA_KEY, | ||
PRIMARY_KEY_METADATA_KEY, | ||
} from "./constants"; | ||
import { LilORMType } from "./types"; | ||
@@ -17,3 +21,7 @@ export interface ColumnOtps { | ||
return (target: object) => { | ||
Reflect.defineMetadata(ENTITY_METADATA_KEY, { name: tableName || target.constructor.name }, target); | ||
Reflect.defineMetadata( | ||
ENTITY_METADATA_KEY, | ||
{ name: tableName || target.constructor.name }, | ||
target | ||
); | ||
}; | ||
@@ -24,3 +32,8 @@ } | ||
return (target: object, propertyKey: string | symbol) => { | ||
Reflect.defineMetadata(PRIMARY_KEY_METADATA_KEY, { ...opts }, target, propertyKey); | ||
Reflect.defineMetadata( | ||
PRIMARY_KEY_METADATA_KEY, | ||
{ ...opts }, | ||
target, | ||
propertyKey | ||
); | ||
}; | ||
@@ -31,4 +44,9 @@ } | ||
return (target: object, propertyKey: string | symbol) => { | ||
Reflect.defineMetadata(COLUMN_METADATA_KEY, { name: opts?.name, type: opts.type }, target, propertyKey); | ||
Reflect.defineMetadata( | ||
COLUMN_METADATA_KEY, | ||
{ name: opts?.name, type: opts.type }, | ||
target, | ||
propertyKey | ||
); | ||
}; | ||
} |
@@ -1,8 +0,10 @@ | ||
import { MetadataExtractor } from './metadata'; | ||
import { ColumnMetadata, LilORMType, MapTypes, SQLiteType } from './types'; | ||
import { TypesHelper } from './types-helper'; | ||
import { MetadataExtractor } from "./metadata"; | ||
import { ColumnMetadata, LilORMType, MapTypes, SQLiteType } from "./types"; | ||
import { TypesHelper } from "./types-helper"; | ||
export class EntityTransformer { | ||
static transformSQLEntityToObject<TEntity>(entityInstance: any, values: any): TEntity { | ||
static transformSQLEntityToObject<TEntity>( | ||
entityInstance: any, | ||
values: any | ||
): TEntity { | ||
const properties = Object.keys(entityInstance); | ||
@@ -12,6 +14,13 @@ const entity: any = {}; | ||
for (const propertyKey of properties) { | ||
const columnMetadata = Reflect.getMetadata('column', entityInstance, propertyKey); | ||
const columnMetadata = Reflect.getMetadata( | ||
"column", | ||
entityInstance, | ||
propertyKey | ||
); | ||
if (columnMetadata) { | ||
const columnName = columnMetadata.name || propertyKey.toString(); | ||
entity[propertyKey] = EntityTransformer.formatValue(values[columnName], columnMetadata.type); | ||
entity[propertyKey] = EntityTransformer.formatValue( | ||
values[columnName], | ||
columnMetadata.type | ||
); | ||
} | ||
@@ -23,8 +32,14 @@ } | ||
static transformClassInstanceToEntityColumns(entityInstance: any): ColumnMetadata[] { | ||
const columns = MetadataExtractor.getEnrichedEntityColumnsName(entityInstance); | ||
static transformClassInstanceToEntityColumns( | ||
entityInstance: any | ||
): ColumnMetadata[] { | ||
const columns = | ||
MetadataExtractor.getEnrichedEntityColumnsName(entityInstance); | ||
columns | ||
.filter((col) => col.value !== undefined) | ||
.map((column) => { | ||
column.value = this.formatValueToSQLiteType(column.value, column.type) as SQLiteType; | ||
column.value = this.formatValueToSQLiteType( | ||
column.value, | ||
column.type | ||
) as SQLiteType; | ||
column.type = MapTypes[column.type] as SQLiteType; | ||
@@ -39,10 +54,10 @@ return column; | ||
if (TypesHelper.isDate(value)) return `'${value.toISOString()}'`; | ||
if (TypesHelper.isBoolean(value)) return value ? '1' : '0'; | ||
if (TypesHelper.isBoolean(value)) return value ? "1" : "0"; | ||
if (TypesHelper.isNumber(value)) return value.toString(); | ||
if (TypesHelper.isJSONObject(value)) return `'${JSON.stringify(value)}'`; | ||
throw new Error('Not supported type'); | ||
throw new Error("Not supported type"); | ||
} | ||
static formatValue(value: any, type: LilORMType): any { | ||
if (type === 'TEXT' || type === 'UUID' || type === 'BLOB') { | ||
if (type === "TEXT" || type === "UUID" || type === "BLOB") { | ||
if (TypesHelper.isDate(value)) return value.toISOString(); | ||
@@ -53,3 +68,3 @@ if (TypesHelper.isJSONObject(value)) return JSON.stringify(value); | ||
} | ||
if (type === 'INTEGER') { | ||
if (type === "INTEGER") { | ||
if (TypesHelper.isBoolean(value)) return value ? 1 : 0; | ||
@@ -59,12 +74,12 @@ | ||
} | ||
if (type === 'REAL') { | ||
if (type === "REAL") { | ||
return TypesHelper.parseReal(value); | ||
} | ||
if (type === 'JSON') { | ||
if (type === "JSON") { | ||
return TypesHelper.parseJson(value); | ||
} | ||
if (type === 'BOOLEAN') { | ||
if (type === "BOOLEAN") { | ||
return TypesHelper.parseBoolean(value); | ||
} | ||
if (type === 'DATE') { | ||
if (type === "DATE") { | ||
return TypesHelper.parseDate(value); | ||
@@ -81,3 +96,2 @@ } | ||
} | ||
} |
export function escapeValue(value: any): string { | ||
if (typeof value === 'string') { | ||
if (typeof value === "string") { | ||
return `'${value}'`; | ||
@@ -4,0 +4,0 @@ } |
@@ -1,3 +0,3 @@ | ||
export { Repository } from './repository' | ||
export { Transaction } from './transaction' | ||
export { LilORMModule } from './module' | ||
export { Repository } from "./repository"; | ||
export { Transaction } from "./transaction"; | ||
export * from "./decorators"; |
@@ -1,5 +0,9 @@ | ||
import { COLUMN_METADATA_KEY, ENTITY_METADATA_KEY, PRIMARY_KEY_METADATA_KEY } from './constants'; | ||
import { EntityTransformer } from './entity-transformer'; | ||
import { ColumnMetadata, LilORMType, MapTypes, SQLiteType } from './types'; | ||
import { TypesHelper } from './types-helper'; | ||
import { | ||
COLUMN_METADATA_KEY, | ||
ENTITY_METADATA_KEY, | ||
PRIMARY_KEY_METADATA_KEY, | ||
} from "./constants"; | ||
import { EntityTransformer } from "./entity-transformer"; | ||
import { ColumnMetadata, LilORMType, MapTypes, SQLiteType } from "./types"; | ||
import { TypesHelper } from "./types-helper"; | ||
@@ -14,3 +18,6 @@ export class MetadataExtractor { | ||
static getEntityTableName(entityClass: any): string { | ||
const entityMetadata = Reflect.getMetadata(ENTITY_METADATA_KEY, entityClass); | ||
const entityMetadata = Reflect.getMetadata( | ||
ENTITY_METADATA_KEY, | ||
entityClass | ||
); | ||
const tableName = entityMetadata.name; | ||
@@ -26,7 +33,14 @@ return tableName; | ||
*/ | ||
static getEntityPrimaryKey(entityInstance: any): { propertyKey: string; columnName: string } { | ||
static getEntityPrimaryKey(entityInstance: any): { | ||
propertyKey: string; | ||
columnName: string; | ||
} { | ||
const properties = Object.keys(entityInstance); | ||
for (const propertyKey of properties) { | ||
const primaryKeyMetadata = Reflect.getMetadata(PRIMARY_KEY_METADATA_KEY, entityInstance, propertyKey); | ||
const primaryKeyMetadata = Reflect.getMetadata( | ||
PRIMARY_KEY_METADATA_KEY, | ||
entityInstance, | ||
propertyKey | ||
); | ||
if (primaryKeyMetadata) { | ||
@@ -38,3 +52,3 @@ const columnName = primaryKeyMetadata.name || propertyKey.toString(); | ||
throw new Error('Primary key not found'); | ||
throw new Error("Primary key not found"); | ||
} | ||
@@ -52,3 +66,7 @@ | ||
for (const propertyKey of properties) { | ||
const columnMetadata = Reflect.getMetadata(COLUMN_METADATA_KEY, entityInstance, propertyKey); | ||
const columnMetadata = Reflect.getMetadata( | ||
COLUMN_METADATA_KEY, | ||
entityInstance, | ||
propertyKey | ||
); | ||
if (columnMetadata) { | ||
@@ -68,3 +86,7 @@ const columnName = columnMetadata.name || propertyKey.toString(); | ||
for (const propertyKey of properties) { | ||
const columnMetadata = Reflect.getMetadata(COLUMN_METADATA_KEY, entityInstance, propertyKey); | ||
const columnMetadata = Reflect.getMetadata( | ||
COLUMN_METADATA_KEY, | ||
entityInstance, | ||
propertyKey | ||
); | ||
if (columnMetadata) { | ||
@@ -93,6 +115,13 @@ const columnName = columnMetadata.name || propertyKey.toString(); | ||
for (const propertyKey of properties) { | ||
const columnMetadata = Reflect.getMetadata(COLUMN_METADATA_KEY, entityInstance, propertyKey); | ||
const columnMetadata = Reflect.getMetadata( | ||
COLUMN_METADATA_KEY, | ||
entityInstance, | ||
propertyKey | ||
); | ||
if (columnMetadata) { | ||
const propertyValue = entityInstance[propertyKey]; | ||
const columnValue = EntityTransformer.formatValueToSQLiteType(propertyValue, columnMetadata.type); | ||
const columnValue = EntityTransformer.formatValueToSQLiteType( | ||
propertyValue, | ||
columnMetadata.type | ||
); | ||
values.push(columnValue); | ||
@@ -99,0 +128,0 @@ } |
@@ -1,14 +0,14 @@ | ||
import { COLUMN_METADATA_KEY, PRIMARY_KEY_METADATA_KEY } from './constants'; | ||
import { PrimaryKeyOpts, ColumnOtps } from './decorators'; | ||
import { EntityTransformer } from './entity-transformer'; | ||
import { escapeValue } from './helper'; | ||
import { MetadataExtractor } from './metadata'; | ||
import { EntityType, MapTypes, SQLiteType } from './types'; | ||
import 'reflect-metadata'; | ||
import { COLUMN_METADATA_KEY, PRIMARY_KEY_METADATA_KEY } from "./constants"; | ||
import { PrimaryKeyOpts, ColumnOtps } from "./decorators"; | ||
import { EntityTransformer } from "./entity-transformer"; | ||
import { escapeValue } from "./helper"; | ||
import { MetadataExtractor } from "./metadata"; | ||
import { EntityType, MapTypes, SQLiteType } from "./types"; | ||
import "reflect-metadata"; | ||
export class QueryBuilder { | ||
static createTableSql(entityClass: any): string { | ||
const entityMetadata = Reflect.getMetadata('entity', entityClass); | ||
const entityMetadata = Reflect.getMetadata("entity", entityClass); | ||
if (!entityMetadata) { | ||
throw new Error('Entity metadata not found'); | ||
throw new Error("Entity metadata not found"); | ||
} | ||
@@ -20,7 +20,13 @@ const tableName = entityMetadata.name || entityClass.constructor.name; | ||
const getColumnMetadata = (target: any, propertyKey: string | symbol): ColumnOtps => { | ||
const getColumnMetadata = ( | ||
target: any, | ||
propertyKey: string | symbol | ||
): ColumnOtps => { | ||
return Reflect.getMetadata(COLUMN_METADATA_KEY, target, propertyKey); | ||
}; | ||
const getPrimaryKeyMetadata = (target: any, propertyKey: string | symbol): PrimaryKeyOpts => { | ||
const getPrimaryKeyMetadata = ( | ||
target: any, | ||
propertyKey: string | symbol | ||
): PrimaryKeyOpts => { | ||
return Reflect.getMetadata(PRIMARY_KEY_METADATA_KEY, target, propertyKey); | ||
@@ -33,3 +39,6 @@ }; | ||
const propertyMetadata = getColumnMetadata(entityInstance, propertyKey); | ||
const primaryKeyMetadata = getPrimaryKeyMetadata(entityInstance, propertyKey); | ||
const primaryKeyMetadata = getPrimaryKeyMetadata( | ||
entityInstance, | ||
propertyKey | ||
); | ||
@@ -44,3 +53,3 @@ if (propertyMetadata) { | ||
if (primaryKeyOptions.autoIncrement) { | ||
columnDefinition += ' PRIMARY KEY AUTOINCREMENT'; | ||
columnDefinition += " PRIMARY KEY AUTOINCREMENT"; | ||
} | ||
@@ -52,3 +61,5 @@ | ||
const createTableQuery = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns.join(', ')});`; | ||
const createTableQuery = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns.join( | ||
", " | ||
)});`; | ||
@@ -58,18 +69,30 @@ return createTableQuery; | ||
static insertSql<TEntity>(entityObject: any, entityClass: EntityType<TEntity>): string { | ||
static insertSql<TEntity>( | ||
entityObject: any, | ||
entityClass: EntityType<TEntity> | ||
): string { | ||
const entityInstance = Object.assign(new entityClass(), entityObject); | ||
const tableName = MetadataExtractor.getEntityTableName(entityClass); | ||
const columns = EntityTransformer.transformClassInstanceToEntityColumns(entityInstance); | ||
const columns = | ||
EntityTransformer.transformClassInstanceToEntityColumns(entityInstance); | ||
const columnsNames = columns.map((column) => column.name); | ||
const values = columns.map((column) => EntityTransformer.valueQueryFormatter(column.value)); | ||
const values = columns.map((column) => | ||
EntityTransformer.valueQueryFormatter(column.value) | ||
); | ||
const insertQuery = `INSERT INTO ${tableName} (${columnsNames.join(', ')}) VALUES (${values.join(', ')});`; | ||
const insertQuery = `INSERT INTO ${tableName} (${columnsNames.join( | ||
", " | ||
)}) VALUES (${values.join(", ")});`; | ||
return insertQuery; | ||
} | ||
static updateSql<TEntity>(entityObject: any, entityClass: EntityType<TEntity>): string { | ||
static updateSql<TEntity>( | ||
entityObject: any, | ||
entityClass: EntityType<TEntity> | ||
): string { | ||
const entityInstance = Object.assign(new entityClass(), entityObject); | ||
const tableName = MetadataExtractor.getEntityTableName(entityClass); | ||
const columns = EntityTransformer.transformClassInstanceToEntityColumns(entityInstance); | ||
const columns = | ||
EntityTransformer.transformClassInstanceToEntityColumns(entityInstance); | ||
@@ -83,4 +106,4 @@ const setClause = columns | ||
}) | ||
.join(', '); | ||
.join(", "); | ||
const primaryKey = MetadataExtractor.getEntityPrimaryKey(new entityClass()); | ||
@@ -90,3 +113,3 @@ const id = (entityInstance as any)[primaryKey.propertyKey]; | ||
const updateQuery = `UPDATE ${tableName} SET ${setClause} WHERE ${primaryKey.columnName} = ${id};`; | ||
return updateQuery; | ||
@@ -104,3 +127,2 @@ } | ||
} | ||
} |
@@ -1,7 +0,7 @@ | ||
import { EntityTransformer } from './entity-transformer'; | ||
import { escapeValue } from './helper'; | ||
import { MetadataExtractor } from './metadata'; | ||
import { QueryBuilder } from './query-builder'; | ||
import { SQLiteDatabase } from './sqlite-database'; | ||
import { Transaction } from './transaction'; | ||
import { EntityTransformer } from "./entity-transformer"; | ||
import { escapeValue } from "./helper"; | ||
import { MetadataExtractor } from "./metadata"; | ||
import { QueryBuilder } from "./query-builder"; | ||
import { SQLiteDatabase } from "./sqlite-database"; | ||
import { Transaction } from "./transaction"; | ||
@@ -12,4 +12,6 @@ export class Repository<TEntity> { | ||
constructor( | ||
private readonly entityModel: new () => TEntity extends object ? TEntity : any, | ||
private readonly db: SQLiteDatabase, | ||
private readonly entityModel: new () => TEntity extends object | ||
? TEntity | ||
: any, | ||
private readonly db: SQLiteDatabase | ||
) { | ||
@@ -27,3 +29,3 @@ this.tableName = MetadataExtractor.getEntityTableName(entityModel); | ||
.map(([key, value]) => `${key} = ${escapeValue(value)}`) | ||
.join(' AND '); | ||
.join(" AND "); | ||
const query = `SELECT * FROM ${this.tableName} WHERE ${whereClause}`; | ||
@@ -39,3 +41,3 @@ const res = await this.db.query<TEntity>(query, this.entityModel); | ||
.map(([key, value]) => `${key} = ${escapeValue(value)}`) | ||
.join(' AND '); | ||
.join(" AND "); | ||
const query = `SELECT * FROM ${this.tableName} WHERE ${whereClause}`; | ||
@@ -57,3 +59,6 @@ const res = await this.db.query<TEntity>(query, this.entityModel); | ||
create(entity: TEntity extends {} ? TEntity : any, transaction?: Transaction): Promise<void> { | ||
create( | ||
entity: TEntity extends {} ? TEntity : any, | ||
transaction?: Transaction | ||
): Promise<void> { | ||
return new Promise((resolve, reject) => { | ||
@@ -60,0 +65,0 @@ const query = QueryBuilder.insertSql(entity as TEntity, this.entityModel); |
@@ -1,4 +0,4 @@ | ||
import * as sqlite3 from 'sqlite3'; | ||
import { EntityTransformer } from './entity-transformer'; | ||
import { EntityType } from './types'; | ||
import * as sqlite3 from "sqlite3"; | ||
import { EntityTransformer } from "./entity-transformer"; | ||
import { EntityType } from "./types"; | ||
@@ -42,3 +42,6 @@ export interface Result<T> { | ||
? rows.map((row) => { | ||
return EntityTransformer.transformSQLEntityToObject(new entityClass(), row); | ||
return EntityTransformer.transformSQLEntityToObject( | ||
new entityClass(), | ||
row | ||
); | ||
}) | ||
@@ -45,0 +48,0 @@ : rows.map((row) => { |
@@ -1,2 +0,2 @@ | ||
import { SQLiteDatabase } from './sqlite-database'; | ||
import { SQLiteDatabase } from "./sqlite-database"; | ||
@@ -10,3 +10,3 @@ export class Transaction { | ||
this.statemanets = []; | ||
this.statemanets.push('BEGIN TRANSACTION'); | ||
this.statemanets.push("BEGIN TRANSACTION"); | ||
return this; | ||
@@ -16,4 +16,4 @@ } | ||
commit(): void { | ||
this.statemanets.push('COMMIT'); | ||
this.db.sqliteInstance.exec(this.statemanets.join(';')); | ||
this.statemanets.push("COMMIT"); | ||
this.db.sqliteInstance.exec(this.statemanets.join(";")); | ||
} | ||
@@ -26,7 +26,9 @@ | ||
rollback(): void { | ||
this.statemanets.push('ROLLBACK'); | ||
this.db.sqliteInstance.exec(this.statemanets.join(';')); | ||
this.statemanets.push("ROLLBACK"); | ||
this.db.sqliteInstance.exec(this.statemanets.join(";")); | ||
} | ||
transaction<T>(callback: (transaction: Transaction) => Promise<T>): Promise<T> { | ||
transaction<T>( | ||
callback: (transaction: Transaction) => Promise<T> | ||
): Promise<T> { | ||
return new Promise(async (resolve, reject) => { | ||
@@ -33,0 +35,0 @@ this.begin(); |
@@ -5,3 +5,3 @@ import { RADIX } from "./constants"; | ||
static isJSONObject(value: any): boolean { | ||
return typeof value === 'object'; | ||
return typeof value === "object"; | ||
} | ||
@@ -14,15 +14,17 @@ | ||
static isString(value: any): boolean { | ||
return typeof value === 'string'; | ||
return typeof value === "string"; | ||
} | ||
static isNumber(value: any): boolean { | ||
return typeof value === 'number'; | ||
return typeof value === "number"; | ||
} | ||
static isBoolean(value: any): boolean { | ||
return typeof value === 'boolean'; | ||
return typeof value === "boolean"; | ||
} | ||
static isUUID(value: any): boolean { | ||
const regex = new RegExp('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'); | ||
const regex = new RegExp( | ||
"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" | ||
); | ||
return regex.test(value); | ||
@@ -40,3 +42,3 @@ } | ||
static parseBoolean(value: any): boolean { | ||
return value === 'true' || value === '1' || value === 1; | ||
return value === "true" || value === "1" || value === 1; | ||
} | ||
@@ -58,5 +60,5 @@ | ||
static generateUUIDv4(): string { | ||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { | ||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { | ||
const r = (Math.random() * 16) | 0; | ||
const v = c === 'x' ? r : (r & 0x3) | 0x8; | ||
const v = c === "x" ? r : (r & 0x3) | 0x8; | ||
return v.toString(16); | ||
@@ -63,0 +65,0 @@ }); |
@@ -12,4 +12,4 @@ export interface LilORMModuleOptions { | ||
export type SQLiteType = 'INTEGER' | 'TEXT' | 'REAL' | 'BLOB'; | ||
export type LilOrmTypeExtension = 'JSON' | 'BOOLEAN' | 'DATE' | 'UUID'; | ||
export type SQLiteType = "INTEGER" | "TEXT" | "REAL" | "BLOB"; | ||
export type LilOrmTypeExtension = "JSON" | "BOOLEAN" | "DATE" | "UUID"; | ||
@@ -19,12 +19,12 @@ export type LilORMType = SQLiteType | LilOrmTypeExtension; | ||
export const MapTypes = { | ||
INTEGER: 'INTEGER', | ||
TEXT: 'TEXT', | ||
REAL: 'REAL', | ||
BLOB: 'BLOB', | ||
JSON: 'TEXT', | ||
BOOLEAN: 'INTEGER', | ||
DATE: 'TEXT', | ||
UUID: 'TEXT', | ||
INTEGER: "INTEGER", | ||
TEXT: "TEXT", | ||
REAL: "REAL", | ||
BLOB: "BLOB", | ||
JSON: "TEXT", | ||
BOOLEAN: "INTEGER", | ||
DATE: "TEXT", | ||
UUID: "TEXT", | ||
}; | ||
export type EntityType<T> = new () => T extends object ? T : any; |
@@ -27,4 +27,5 @@ { | ||
"src/**/*.spec.ts", | ||
"src/**/*.test.ts" | ||
"src/**/*.test.ts", | ||
"./dist/**/*" | ||
] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
162135
51.96%101
65.57%2607
57.33%137
4466.67%