mrepo-sql 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README ADDED
@@ -0,0 +1,22 @@
1
+ # m-sql
2
+
3
+
4
+ ## Install
5
+ npm install m-sql
6
+
7
+ ## Usage
8
+ ```ts
9
+ import { BaseRepository } from "mariadb-sp-repository";
10
+
11
+ const repo = new BaseRepository({
12
+ host: "localhost",
13
+ user: "root",
14
+ password: "123",
15
+ database: "test"
16
+ });
17
+
18
+ const result = await repo.execSP("SP_Product_List", {
19
+ params: [1]
20
+ });
21
+
22
+
@@ -0,0 +1,44 @@
1
+ import mariadb, { type PoolConfig } from "mariadb";
2
+ import { ExecSPOptions } from "../interfaces/db.interface.js";
3
+ export declare class BaseRepository {
4
+ private pool;
5
+ constructor(config: PoolConfig);
6
+ /**
7
+ * Executes a stored procedure with the given parameters and handling options.
8
+ * @OPTIONS {params: any[] | Record<string, any>, out: OutVariable[], plain: boolean, extract: boolean, order: string[], deleteExtra: boolean, fillWithNulls: boolean}
9
+ * @param spName The name of the stored procedure to call.
10
+ * @param options The options for the stored procedure execution.
11
+ * @returns The result of the stored procedure execution, typed as T.
12
+ */
13
+ execSP<T = any>(spName: string, { params, out, plain, extract, order, deleteExtra, fillWithNulls, }: ExecSPOptions): Promise<T>;
14
+ /**
15
+ * Retrieves all records from a view.
16
+ *
17
+ * @param viewName - The name of the view to query.
18
+ * @returns The result of the query.
19
+ */
20
+ view<T = any>(viewName: string): Promise<T[]>;
21
+ /**
22
+ * Executes a query with the given parameters.
23
+ *
24
+ * @param query - The SQL query to execute.
25
+ * @param params - The parameters to pass to the query.
26
+ * @returns The result of the query.
27
+ */
28
+ query<T = any>(query: string, params?: any[]): Promise<T[]>;
29
+ /**
30
+ * Connects to the database.
31
+ *
32
+ * @param onSuccess - Callback function to execute on success.
33
+ * @param onError - Callback function to execute on error.
34
+ */
35
+ connectDB(onSuccess?: () => void, onError?: (error: Error) => void): Promise<void>;
36
+ /**
37
+ * Closes the connection pool.
38
+ *
39
+ * @param onSuccess - Callback function to execute on success.
40
+ * @param onError - Callback function to execute on error.
41
+ */
42
+ closeDB(onSuccess?: () => void, onError?: (error: Error) => void): Promise<void>;
43
+ getOriginalPool(): Promise<mariadb.Pool>;
44
+ }
@@ -0,0 +1,133 @@
1
+ import mariadb from "mariadb";
2
+ import { extractParams, flattenToObject, generateParams } from "../helpers/hepers.js";
3
+ const defaultConfig = {
4
+ multipleStatements: true,
5
+ };
6
+ export class BaseRepository {
7
+ constructor(config) {
8
+ this.pool = mariadb.createPool({
9
+ ...defaultConfig,
10
+ ...config
11
+ });
12
+ }
13
+ /**
14
+ * Executes a stored procedure with the given parameters and handling options.
15
+ * @OPTIONS {params: any[] | Record<string, any>, out: OutVariable[], plain: boolean, extract: boolean, order: string[], deleteExtra: boolean, fillWithNulls: boolean}
16
+ * @param spName The name of the stored procedure to call.
17
+ * @param options The options for the stored procedure execution.
18
+ * @returns The result of the stored procedure execution, typed as T.
19
+ */
20
+ async execSP(spName, { params = [], out = [], plain = true, extract = false, order = [], deleteExtra = false, fillWithNulls = false, }) {
21
+ const endParams = extract && !Array.isArray(params) && params !== null
22
+ ? extractParams({ params: params, order, deleteExtra, fillWithNulls })
23
+ : (Array.isArray(params) ? params : []);
24
+ const placeholders = generateParams(endParams.length);
25
+ const callParams = [
26
+ ...(placeholders ? [placeholders] : []),
27
+ ...(out.length ? out.map(({ name }) => `@${name}`) : [])
28
+ ].join(',');
29
+ let conn;
30
+ try {
31
+ conn = await this.pool.getConnection();
32
+ const declareOutVars = out.length
33
+ ? out.map(({ name, type }) => `SET @${name} = CAST(NULL AS ${type ?? 'VARCHAR(255)'});`).join('\n')
34
+ : '';
35
+ const selectOuts = out.length
36
+ ? 'SELECT ' + out
37
+ .map(({ name }) => `@${name}`)
38
+ .join(',')
39
+ : '';
40
+ const query = `
41
+ ${declareOutVars}
42
+ CALL ${spName}(${callParams});
43
+ ${selectOuts}
44
+ `;
45
+ const res = await conn.query(query, endParams);
46
+ return (plain ? flattenToObject(res) : (res[0] ?? []));
47
+ }
48
+ catch (error) {
49
+ throw error;
50
+ }
51
+ finally {
52
+ if (conn)
53
+ conn.release();
54
+ }
55
+ }
56
+ /**
57
+ * Retrieves all records from a view.
58
+ *
59
+ * @param viewName - The name of the view to query.
60
+ * @returns The result of the query.
61
+ */
62
+ async view(viewName) {
63
+ let conn;
64
+ try {
65
+ conn = await this.pool.getConnection();
66
+ const result = await conn.query(`SELECT * FROM ${viewName}`);
67
+ return result;
68
+ }
69
+ catch (error) {
70
+ throw error;
71
+ }
72
+ finally {
73
+ if (conn)
74
+ conn.release();
75
+ }
76
+ }
77
+ /**
78
+ * Executes a query with the given parameters.
79
+ *
80
+ * @param query - The SQL query to execute.
81
+ * @param params - The parameters to pass to the query.
82
+ * @returns The result of the query.
83
+ */
84
+ async query(query, params) {
85
+ let conn;
86
+ try {
87
+ conn = await this.pool.getConnection();
88
+ const result = await conn.query(query, params);
89
+ return result;
90
+ }
91
+ catch (error) {
92
+ throw error;
93
+ }
94
+ finally {
95
+ if (conn)
96
+ conn.release();
97
+ }
98
+ }
99
+ /**
100
+ * Connects to the database.
101
+ *
102
+ * @param onSuccess - Callback function to execute on success.
103
+ * @param onError - Callback function to execute on error.
104
+ */
105
+ async connectDB(onSuccess, onError) {
106
+ try {
107
+ const conn = await this.pool.getConnection();
108
+ conn.release();
109
+ onSuccess?.();
110
+ }
111
+ catch (error) {
112
+ onError?.(error);
113
+ throw error;
114
+ }
115
+ }
116
+ /**
117
+ * Closes the connection pool.
118
+ *
119
+ * @param onSuccess - Callback function to execute on success.
120
+ * @param onError - Callback function to execute on error.
121
+ */
122
+ async closeDB(onSuccess, onError) {
123
+ return this.pool.end().then(() => {
124
+ onSuccess?.();
125
+ }).catch(error => {
126
+ onError?.(error);
127
+ throw error;
128
+ });
129
+ }
130
+ async getOriginalPool() {
131
+ return this.pool;
132
+ }
133
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Generates a string of comma-separated placeholders.
3
+ */
4
+ export declare const generateParams: (n: number) => string;
5
+ /**
6
+ * Flattens MariaDB query results into a single object.
7
+ */
8
+ export declare const flattenToObject: (input: unknown) => Record<string, any>;
9
+ interface ExtractParamsArgs {
10
+ params: Record<string, any>;
11
+ order: string[];
12
+ deleteExtra?: boolean;
13
+ fillWithNulls?: boolean;
14
+ }
15
+ /**
16
+ * Extracts and orders parameters from an object.
17
+ */
18
+ export declare const extractParams: ({ params, order, deleteExtra, fillWithNulls }: ExtractParamsArgs) => any[];
19
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Generates a string of comma-separated placeholders.
3
+ */
4
+ export const generateParams = (n) => Array.from({ length: n }, (_, i) => `?`).join(',');
5
+ /**
6
+ * Flattens MariaDB query results into a single object.
7
+ */
8
+ export const flattenToObject = (input) => {
9
+ const result = {};
10
+ function helper(item) {
11
+ if (Array.isArray(item)) {
12
+ item.forEach(inner => helper(inner));
13
+ }
14
+ else if (item !== null && typeof item === 'object') {
15
+ Object.entries(item).forEach(([key, value]) => {
16
+ result[key] = value;
17
+ });
18
+ }
19
+ }
20
+ helper(input);
21
+ delete result.affectedRows;
22
+ delete result.insertId;
23
+ delete result.warningStatus;
24
+ return result;
25
+ };
26
+ /**
27
+ * Extracts and orders parameters from an object.
28
+ */
29
+ export const extractParams = ({ params, order, deleteExtra = false, fillWithNulls = false }) => {
30
+ const ordered = [];
31
+ order.forEach(key => {
32
+ if (params[key] === undefined) {
33
+ if (fillWithNulls) {
34
+ ordered.push(null);
35
+ }
36
+ return;
37
+ }
38
+ ordered.push(params[key]);
39
+ });
40
+ if (deleteExtra) {
41
+ return ordered;
42
+ }
43
+ const remaining = Object.keys(params)
44
+ .filter(key => !order.includes(key))
45
+ .map(key => params[key]);
46
+ return [...ordered, ...remaining];
47
+ };
@@ -0,0 +1,2 @@
1
+ import { BaseRepository } from "./db/repo.js";
2
+ export { BaseRepository };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { BaseRepository } from "./db/repo.js";
2
+ export { BaseRepository };
@@ -0,0 +1,20 @@
1
+ export interface OutVariable {
2
+ name: string;
3
+ type?: string;
4
+ }
5
+ export interface ExecSPOptions {
6
+ /** Parameters to pass to the SP. Can be an array or an object if `extract` is true. */
7
+ params?: any[] | Record<string, any>;
8
+ /** Definition of output variables. */
9
+ out?: OutVariable[];
10
+ /** If true, flattens the result into a single object. */
11
+ plain?: boolean;
12
+ /** If true, extracts parameters from an object based on the `order` array. */
13
+ extract?: boolean;
14
+ /** The order of keys to extract from `params`. */
15
+ order?: string[];
16
+ /** If true, deletes extra parameters not specified in `order`. */
17
+ deleteExtra?: boolean;
18
+ /** If true, fills missing ordered parameters with null. */
19
+ fillWithNulls?: boolean;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "mrepo-sql",
3
+ "version": "1.0.0",
4
+ "description": "With mrepo-sql, the ability to create repositories with features that improve code readability and project scalability is added.",
5
+ "license": "MIT",
6
+ "author": "daniel_hz",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "scripts": {
10
+ "dev": "node src/index.ts",
11
+ "build": "tsc",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "dependencies": {
15
+ "mariadb": "^3.4.5"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^25.0.3",
19
+ "typescript": "^5.9.3"
20
+ }
21
+ }
package/src/db/repo.ts ADDED
@@ -0,0 +1,152 @@
1
+ import mariadb, { type PoolConfig } from "mariadb";
2
+
3
+ import { extractParams, flattenToObject, generateParams } from "../helpers/hepers.js";
4
+ import { ExecSPOptions } from "../interfaces/db.interface.js";
5
+
6
+ const defaultConfig = {
7
+ multipleStatements: true,
8
+ }
9
+
10
+ export class BaseRepository {
11
+ private pool: mariadb.Pool;
12
+ constructor(config: PoolConfig) {
13
+ this.pool = mariadb.createPool(
14
+ {
15
+ ...defaultConfig,
16
+ ...config
17
+ }
18
+ );
19
+ }
20
+
21
+ /**
22
+ * Executes a stored procedure with the given parameters and handling options.
23
+ * @OPTIONS {params: any[] | Record<string, any>, out: OutVariable[], plain: boolean, extract: boolean, order: string[], deleteExtra: boolean, fillWithNulls: boolean}
24
+ * @param spName The name of the stored procedure to call.
25
+ * @param options The options for the stored procedure execution.
26
+ * @returns The result of the stored procedure execution, typed as T.
27
+ */
28
+ async execSP<T = any>(spName: string, {
29
+ params = [],
30
+ out = [],
31
+ plain = true,
32
+ extract = false,
33
+ order = [],
34
+ deleteExtra = false,
35
+ fillWithNulls = false,
36
+ }: ExecSPOptions): Promise<T> {
37
+ const endParams = extract && !Array.isArray(params) && params !== null
38
+ ? extractParams({ params: params as Record<string, any>, order, deleteExtra, fillWithNulls })
39
+ : (Array.isArray(params) ? params : []);
40
+
41
+ const placeholders = generateParams(endParams.length);
42
+
43
+ const callParams = [
44
+ ...(placeholders ? [placeholders] : []),
45
+ ...(out.length ? out.map(({ name }) => `@${name}`) : [])
46
+ ].join(',');
47
+
48
+ let conn;
49
+ try {
50
+ conn = await this.pool.getConnection();
51
+
52
+ const declareOutVars = out.length
53
+ ? out.map(({ name, type }) => `SET @${name} = CAST(NULL AS ${type ?? 'VARCHAR(255)'});`).join('\n')
54
+ : '';
55
+
56
+ const selectOuts = out.length
57
+ ? 'SELECT ' + out
58
+ .map(({ name }) => `@${name}`)
59
+ .join(',')
60
+ : '';
61
+
62
+ const query = `
63
+ ${declareOutVars}
64
+ CALL ${spName}(${callParams});
65
+ ${selectOuts}
66
+ `;
67
+
68
+ const res = await conn.query(query, endParams);
69
+
70
+ return (plain ? flattenToObject(res) : (res[0] ?? [])) as T;
71
+ } catch (error) {
72
+ throw error;
73
+ } finally {
74
+ if (conn) conn.release();
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Retrieves all records from a view.
80
+ *
81
+ * @param viewName - The name of the view to query.
82
+ * @returns The result of the query.
83
+ */
84
+ async view<T = any>(viewName: string): Promise<T[]> {
85
+ let conn;
86
+ try {
87
+ conn = await this.pool.getConnection();
88
+ const result = await conn.query(`SELECT * FROM ${viewName}`);
89
+ return result as T[];
90
+ } catch (error) {
91
+ throw error;
92
+ } finally {
93
+ if (conn) conn.release();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Executes a query with the given parameters.
99
+ *
100
+ * @param query - The SQL query to execute.
101
+ * @param params - The parameters to pass to the query.
102
+ * @returns The result of the query.
103
+ */
104
+ async query<T = any>(query: string, params?: any[]): Promise<T[]> {
105
+ let conn;
106
+ try {
107
+ conn = await this.pool.getConnection();
108
+ const result = await conn.query(query, params);
109
+ return result as T[];
110
+ } catch (error) {
111
+ throw error;
112
+ } finally {
113
+ if (conn) conn.release();
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Connects to the database.
119
+ *
120
+ * @param onSuccess - Callback function to execute on success.
121
+ * @param onError - Callback function to execute on error.
122
+ */
123
+ async connectDB(onSuccess?: () => void, onError?: (error: Error) => void) {
124
+ try {
125
+ const conn = await this.pool.getConnection();
126
+ conn.release();
127
+ onSuccess?.();
128
+ } catch (error) {
129
+ onError?.(error as Error);
130
+ throw error;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Closes the connection pool.
136
+ *
137
+ * @param onSuccess - Callback function to execute on success.
138
+ * @param onError - Callback function to execute on error.
139
+ */
140
+ async closeDB(onSuccess?: () => void, onError?: (error: Error) => void) {
141
+ return this.pool.end().then(() => {
142
+ onSuccess?.();
143
+ }).catch(error => {
144
+ onError?.(error);
145
+ throw error;
146
+ });
147
+ }
148
+
149
+ async getOriginalPool() {
150
+ return this.pool;
151
+ }
152
+ }
@@ -0,0 +1,64 @@
1
+
2
+ /**
3
+ * Generates a string of comma-separated placeholders.
4
+ */
5
+ export const generateParams = (n: number): string => Array.from({ length: n }, (_, i) => `?`).join(',');
6
+
7
+ /**
8
+ * Flattens MariaDB query results into a single object.
9
+ */
10
+ export const flattenToObject = (input: unknown): Record<string, any> => {
11
+ const result: Record<string, any> = {};
12
+
13
+ function helper(item: unknown) {
14
+ if (Array.isArray(item)) {
15
+ item.forEach(inner => helper(inner));
16
+ } else if (item !== null && typeof item === 'object') {
17
+ Object.entries(item).forEach(([key, value]) => {
18
+ result[key] = value;
19
+ });
20
+ }
21
+ }
22
+
23
+ helper(input);
24
+ delete result.affectedRows;
25
+ delete result.insertId;
26
+ delete result.warningStatus;
27
+ return result;
28
+ };
29
+
30
+ interface ExtractParamsArgs {
31
+ params: Record<string, any>;
32
+ order: string[];
33
+ deleteExtra?: boolean;
34
+ fillWithNulls?: boolean;
35
+ }
36
+
37
+ /**
38
+ * Extracts and orders parameters from an object.
39
+ */
40
+ export const extractParams = ({ params, order, deleteExtra = false, fillWithNulls = false }: ExtractParamsArgs): any[] => {
41
+ const ordered: any[] = [];
42
+ order.forEach(key => {
43
+ if (params[key] === undefined) {
44
+ if (fillWithNulls) {
45
+ ordered.push(null);
46
+ }
47
+ return;
48
+ }
49
+ ordered.push(params[key]);
50
+ });
51
+
52
+ if (deleteExtra) {
53
+ return ordered;
54
+ }
55
+
56
+ const remaining = Object.keys(params)
57
+ .filter(key => !order.includes(key))
58
+ .map(key => params[key]);
59
+
60
+ return [...ordered, ...remaining];
61
+ };
62
+
63
+
64
+
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { BaseRepository } from "./db/repo.js";
2
+
3
+ export { BaseRepository };
@@ -0,0 +1,21 @@
1
+ export interface OutVariable {
2
+ name: string;
3
+ type?: string;
4
+ }
5
+
6
+ export interface ExecSPOptions {
7
+ /** Parameters to pass to the SP. Can be an array or an object if `extract` is true. */
8
+ params?: any[] | Record<string, any>;
9
+ /** Definition of output variables. */
10
+ out?: OutVariable[];
11
+ /** If true, flattens the result into a single object. */
12
+ plain?: boolean;
13
+ /** If true, extracts parameters from an object based on the `order` array. */
14
+ extract?: boolean;
15
+ /** The order of keys to extract from `params`. */
16
+ order?: string[];
17
+ /** If true, deletes extra parameters not specified in `order`. */
18
+ deleteExtra?: boolean;
19
+ /** If true, fills missing ordered parameters with null. */
20
+ fillWithNulls?: boolean;
21
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true
10
+ },
11
+ "include": [
12
+ "src"
13
+ ]
14
+ }