Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# v1.2.0

- Feat: 'Select' and 'Find' methods can now receive an orderBy parameter to order return the results from the database

- BREAKING: 'Select' and 'Find' now receive an object as parameter instead of separated params

- Chore: Updated dev dependencies

# v1.1.1

- Fix: Select with filter doesn't work if the value of the field 'value' is falsy
Expand Down
192 changes: 104 additions & 88 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "promiseorm",
"version": "1.1.1",
"version": "1.2.0",
"description": "A Typescript ORM for automatic creation and management of models and entries from simple objects",
"main": "build/index.js",
"files": [
Expand Down Expand Up @@ -34,10 +34,10 @@
"mariadb": "3.4.5"
},
"devDependencies": {
"@types/node": "^24.7.2",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.46.0",
"eslint": "^9.37.0",
"@types/node": "^24.9.2",
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/parser": "^8.46.2",
"eslint": "^9.38.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^7.2.1",
Expand Down
4 changes: 2 additions & 2 deletions src/main/connection/DatabaseConnection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IDatabaseField, IDatabaseQueryFilterExpression } from '../interfaces';
import { IDatabaseConnectionRead, IDatabaseField, IDatabaseQueryFilterExpression } from '../interfaces';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { DatabaseException } from '../errors';
import { BaseModel } from '../models';
Expand Down Expand Up @@ -64,7 +64,7 @@ export abstract class DatabaseConnection {
* @throws [{@link DatabaseException}]
* @abstract
*/
public abstract read(keys: ('*' | string[]), database: string, filter?: IDatabaseQueryFilterExpression, limit?: number): Promise<Record<string, any>[]>
public abstract read({ keys, database, filter, limit, orderBy }: IDatabaseConnectionRead): Promise<Record<string, any>[]>

/**
* Inserts data on database, if it already exists, updates the selected fields
Expand Down
30 changes: 25 additions & 5 deletions src/main/connection/MariaDBConnection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EDatabaseQueryFilterOperator,
EDatabaseTypes, EMariaDBFieldTypes,
IDatabaseConnectionRead,
IDatabaseField, IDatabaseQueryFilter,
IDatabaseQueryFilterExpression,
IMariaDBDescribeField,
Expand Down Expand Up @@ -83,7 +84,12 @@ export class MariaDBConnection extends DatabaseConnection {
} else {
await conn.execute(instructions.join(' '));
// selects just inserted data
result = (await this.read('*', database, { type: 'AND', filters: keys.map((key, index) => ({ tableKey: key, operator: EDatabaseQueryFilterOperator.EQUALS, value: values[index] })) }, 1))[0];
result = (await this.read({
keys: '*',
database,
filter: { type: 'AND', filters: keys.map((key, index) => ({ tableKey: key, operator: EDatabaseQueryFilterOperator.EQUALS, value: values[index] })) },
limit: 1,
}))[0];
}
return result;
}
Expand All @@ -107,14 +113,21 @@ export class MariaDBConnection extends DatabaseConnection {
/**
* @private
*/
override async read(keys: ('*' | string[]), database: string, filter?: IDatabaseQueryFilterExpression, limit?: number): Promise<Record<string, any>[]> {
override async read({ keys, database, filter, limit, orderBy }: IDatabaseConnectionRead): Promise<Record<string, any>[]> {
const conn = await this.getConnection();
const operators: string[] = [];
operators.push(typeof keys === 'string' ? '*' : keys.map(key => conn.escapeId(key)).join(', '));
operators.push(`FROM ${conn.escapeId(database)}`);
if (filter) operators.push(`WHERE ${this.filterBuilder(conn, filter)}`);
if (orderBy) {
operators.push(`ORDER BY ${
Array.isArray(orderBy) ?
orderBy.map((items) => `${conn.escapeId(items.field)} ${items.direction}`).join(', ') :
`${conn.escapeId(orderBy.field)} ${orderBy.direction}`
}`);
}
if (limit) {
if (limit < 1) throw new DatabaseException('Limit must be a positive number greater than ');
if (limit < 1) throw new DatabaseException('Limit must be a positive number greater than 1');
operators.push(`LIMIT ${limit}`);
}

Expand All @@ -135,8 +148,15 @@ export class MariaDBConnection extends DatabaseConnection {
instructions.push('WHERE');
instructions.push(this.filterBuilder(conn, filter));
await conn.execute(instructions.join(' '));
const result = (await this.read('*', database, { type: 'AND', filters:
fields.map((key, index) => ({ tableKey: key, operator: EDatabaseQueryFilterOperator.EQUALS, value: newData[index] })) }, 1))[0];
const result = (await this.read({
keys: '*',
database,
filter: {
type: 'AND',
filters: fields.map((key, index) => ({ tableKey: key, operator: EDatabaseQueryFilterOperator.EQUALS, value: newData[index] })),
},
limit: 1,
}))[0];
await conn.release();
return result;
}
Expand Down
9 changes: 9 additions & 0 deletions src/main/interfaces/connection/IDatabaseConnectionRead.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IDatabaseOrderBy, IDatabaseQueryFilterExpression } from '../..';

export interface IDatabaseConnectionRead {
keys: ('*' | string[]),
database: string,
filter?: IDatabaseQueryFilterExpression,
limit?: number,
orderBy?: IDatabaseOrderBy | IDatabaseOrderBy[]
}
1 change: 1 addition & 0 deletions src/main/interfaces/connection/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './mariadb';
export * from './IDatabaseConnectionRead';
4 changes: 4 additions & 0 deletions src/main/interfaces/database/IDatabaseOrderBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IDatabaseOrderBy {
field: string;
direction: 'ASC' | 'DESC';
}
1 change: 1 addition & 0 deletions src/main/interfaces/database/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './IDatabaseQueryFilterExpression';
export * from './EDatabaseQueryFilterOperator';
export * from './IDatabaseQueryFilter';
export * from './IDatabaseOrderBy';
export * from './IDatabaseField';
export * from './EDatabaseTypes';
25 changes: 15 additions & 10 deletions src/main/models/BaseModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EDatabaseQueryFilterOperator, EDatabaseTypes, IDatabaseField, IDatabaseQueryFilter, IDatabaseQueryFilterExpression } from '../interfaces';
import { EDatabaseQueryFilterOperator, EDatabaseTypes, IDatabaseField, IDatabaseOrderBy, IDatabaseQueryFilter, IDatabaseQueryFilterExpression } from '../interfaces';
import { DatabaseConnection } from '../connection';
import { DatabaseException } from '../errors';

Expand Down Expand Up @@ -157,10 +157,11 @@ export class BaseModel {
* @returns The data found
* @throws [{@link DatabaseException}]
*/
public async find(query?: Record<string, any>, limit?: number): Promise<Record<string, unknown>[]> {
public async find(params: { query?: Record<string, any>, limit?: number, orderBy?: IDatabaseOrderBy }): Promise<Record<string, unknown>[]> {
const { query, limit, orderBy } = params || {};
this.checkIsReady();
return this.connection!.read('*', this.name!,
query
return this.connection!.read({ keys: '*', database: this.name!,
filter: (query
? {
type: 'AND',
filters: Object.keys(query).map((fieldKey) => ({
Expand All @@ -169,9 +170,10 @@ export class BaseModel {
value: query[fieldKey],
})),
}
: undefined,
: undefined),
limit,
);
orderBy,
});
}

/**
Expand All @@ -181,7 +183,7 @@ export class BaseModel {
* @throws [{@link DatabaseException}]
*/
public async findOne(query?: Record<string, any>): Promise<Record<string, unknown> | undefined> {
return Promise.resolve((await this.find(query, 1))[0]);
return Promise.resolve((await this.find({ query, limit: 1 }))[0]);
}

/**
Expand All @@ -203,11 +205,14 @@ export class BaseModel {
* @returns The data found
* @throws [{@link DatabaseException}]
*/
public async select(fields: string[], filter?: IDatabaseQueryFilterExpression, limit?: number): Promise<Record<string, unknown>[]> {
public async select(params: { fields: string[], query?: Record<string, any>, filter?: IDatabaseQueryFilterExpression, limit?: number, orderBy?: IDatabaseOrderBy },
): Promise<Record<string, unknown>[]> {
this.checkIsReady();
if (!params) throw new DatabaseException('Missing params for \'select\' method call, if you want to retrieve all data on this table call \'find\' instead.');
const { fields, filter, limit, orderBy } = params;
this.fieldsCheck(fields);
this.filterCheck(filter);
return this.connection!.read(fields, this.name!, filter ?? undefined, limit);
return this.connection!.read({ keys: fields, database: this.name!, filter, limit, orderBy });
}

/**
Expand All @@ -218,7 +223,7 @@ export class BaseModel {
* @throws [{@link DatabaseException}]
*/
public async selectOne(fields: string[], filter?: IDatabaseQueryFilterExpression): Promise<Record<string, unknown> | undefined> {
return (await this.select(fields, filter, 1))[0];
return (await this.select({ fields, filter, limit: 1 }))[0];
}

/**
Expand Down