pg-query-sdk 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.
Files changed (62) hide show
  1. package/README.md +553 -0
  2. package/dist/cjs/builders/ConditionBuilder.d.ts +11 -0
  3. package/dist/cjs/builders/ConditionBuilder.js +43 -0
  4. package/dist/cjs/builders/QueryBuilder.d.ts +31 -0
  5. package/dist/cjs/builders/QueryBuilder.js +88 -0
  6. package/dist/cjs/core/Database.d.ts +20 -0
  7. package/dist/cjs/core/Database.js +39 -0
  8. package/dist/cjs/core/ParamContext.d.ts +8 -0
  9. package/dist/cjs/core/ParamContext.js +16 -0
  10. package/dist/cjs/core/QueryExecutor.d.ts +14 -0
  11. package/dist/cjs/core/QueryExecutor.js +39 -0
  12. package/dist/cjs/core/TransactionManager.d.ts +6 -0
  13. package/dist/cjs/core/TransactionManager.js +24 -0
  14. package/dist/cjs/core/UnitOfWork.d.ts +10 -0
  15. package/dist/cjs/core/UnitOfWork.js +27 -0
  16. package/dist/cjs/dialects/Dialect.d.ts +4 -0
  17. package/dist/cjs/dialects/Dialect.js +2 -0
  18. package/dist/cjs/dialects/MysqlDialect.d.ts +5 -0
  19. package/dist/cjs/dialects/MysqlDialect.js +11 -0
  20. package/dist/cjs/dialects/PostgresDialect.d.ts +5 -0
  21. package/dist/cjs/dialects/PostgresDialect.js +11 -0
  22. package/dist/cjs/index.d.ts +7 -0
  23. package/dist/cjs/index.js +20 -0
  24. package/dist/cjs/orm/EntityManager.d.ts +0 -0
  25. package/dist/cjs/orm/EntityManager.js +1 -0
  26. package/dist/cjs/orm/Repository.d.ts +13 -0
  27. package/dist/cjs/orm/Repository.js +30 -0
  28. package/dist/cjs/query/ConditionBuilder.d.ts +11 -0
  29. package/dist/cjs/query/ConditionBuilder.js +67 -0
  30. package/dist/cjs/query/QueryBuilder.d.ts +43 -0
  31. package/dist/cjs/query/QueryBuilder.js +152 -0
  32. package/dist/esm/builders/ConditionBuilder.d.ts +11 -0
  33. package/dist/esm/builders/ConditionBuilder.js +40 -0
  34. package/dist/esm/builders/QueryBuilder.d.ts +31 -0
  35. package/dist/esm/builders/QueryBuilder.js +82 -0
  36. package/dist/esm/core/Database.d.ts +20 -0
  37. package/dist/esm/core/Database.js +33 -0
  38. package/dist/esm/core/ParamContext.d.ts +8 -0
  39. package/dist/esm/core/ParamContext.js +13 -0
  40. package/dist/esm/core/QueryExecutor.d.ts +14 -0
  41. package/dist/esm/core/QueryExecutor.js +36 -0
  42. package/dist/esm/core/TransactionManager.d.ts +6 -0
  43. package/dist/esm/core/TransactionManager.js +21 -0
  44. package/dist/esm/core/UnitOfWork.d.ts +10 -0
  45. package/dist/esm/core/UnitOfWork.js +24 -0
  46. package/dist/esm/dialects/Dialect.d.ts +4 -0
  47. package/dist/esm/dialects/Dialect.js +1 -0
  48. package/dist/esm/dialects/MysqlDialect.d.ts +5 -0
  49. package/dist/esm/dialects/MysqlDialect.js +8 -0
  50. package/dist/esm/dialects/PostgresDialect.d.ts +5 -0
  51. package/dist/esm/dialects/PostgresDialect.js +8 -0
  52. package/dist/esm/index.d.ts +7 -0
  53. package/dist/esm/index.js +7 -0
  54. package/dist/esm/orm/EntityManager.d.ts +0 -0
  55. package/dist/esm/orm/EntityManager.js +1 -0
  56. package/dist/esm/orm/Repository.d.ts +13 -0
  57. package/dist/esm/orm/Repository.js +27 -0
  58. package/dist/esm/query/ConditionBuilder.d.ts +11 -0
  59. package/dist/esm/query/ConditionBuilder.js +64 -0
  60. package/dist/esm/query/QueryBuilder.d.ts +43 -0
  61. package/dist/esm/query/QueryBuilder.js +146 -0
  62. package/package.json +45 -0
@@ -0,0 +1,64 @@
1
+ export default class ConditionBuilder {
2
+ constructor(ctx) {
3
+ this.ctx = ctx;
4
+ this.parts = [];
5
+ }
6
+ where(obj) {
7
+ Object.entries(obj).forEach(([key, value]) => {
8
+ if (value === null) {
9
+ this.parts.push(`${key} IS NULL`);
10
+ return;
11
+ }
12
+ if (typeof value === 'object' && value !== null && 'op' in value) {
13
+ const { op, value: v } = value;
14
+ const placeholder = this.ctx.add(v);
15
+ this.parts.push(`${key} ${op} ${placeholder}`);
16
+ return;
17
+ }
18
+ const placeholder = this.ctx.add(value);
19
+ this.parts.push(`${key} = ${placeholder}`);
20
+ });
21
+ return this;
22
+ }
23
+ raw(expression) {
24
+ this.parts.push(expression);
25
+ return this;
26
+ }
27
+ andGroup(cb) {
28
+ const nested = new ConditionBuilder(this.ctx);
29
+ cb(nested);
30
+ const built = nested.build();
31
+ if (built) {
32
+ this.parts.push(`(${built.replace(/^WHERE\s/, '')})`);
33
+ }
34
+ return this;
35
+ }
36
+ orGroup(cb) {
37
+ const nested = new ConditionBuilder(this.ctx);
38
+ cb(nested);
39
+ const built = nested.build();
40
+ if (built) {
41
+ const clean = built.replace(/^WHERE\s/, '');
42
+ this.parts.push(`OR (${clean})`);
43
+ }
44
+ return this;
45
+ }
46
+ build(prefix = 'WHERE') {
47
+ if (!this.parts.length)
48
+ return '';
49
+ const normalized = [];
50
+ this.parts.forEach((part, index) => {
51
+ if (index === 0) {
52
+ normalized.push(part);
53
+ return;
54
+ }
55
+ if (part.startsWith('OR ')) {
56
+ normalized.push(part);
57
+ }
58
+ else {
59
+ normalized.push(`AND ${part}`);
60
+ }
61
+ });
62
+ return `${prefix} ${normalized.join(' ')}`;
63
+ }
64
+ }
@@ -0,0 +1,43 @@
1
+ import ConditionBuilder from './ConditionBuilder';
2
+ import QueryExecutor from '../core/QueryExecutor';
3
+ import { Dialect } from '../dialects/Dialect';
4
+ export default class QueryBuilder<T = any> {
5
+ private executor;
6
+ private dialect;
7
+ private cacheTTL?;
8
+ private fields;
9
+ private joins;
10
+ private groupByFields;
11
+ private orderByFields;
12
+ private limitCount?;
13
+ private offsetCount?;
14
+ private ctes;
15
+ private fromClause;
16
+ private ctx;
17
+ private condition;
18
+ private havingCondition;
19
+ constructor(table: string, executor: QueryExecutor, dialect: Dialect, cacheTTL?: number | 0 | undefined);
20
+ select(fields: (keyof T | string)[]): this;
21
+ private addJoin;
22
+ join(table: string, localKey: string, foreignKey: string): this;
23
+ leftJoin(table: string, localKey: string, foreignKey: string): this;
24
+ rightJoin(table: string, localKey: string, foreignKey: string): this;
25
+ where(obj: Partial<T>): this;
26
+ whereRaw(expression: string): this;
27
+ andGroup(cb: (qb: ConditionBuilder) => void): this;
28
+ orGroup(cb: (qb: ConditionBuilder) => void): this;
29
+ groupBy(fields: string | string[]): this;
30
+ having(obj: Record<string, any>): this;
31
+ havingRaw(expr: string): this;
32
+ orderBy(column: string, direction?: 'ASC' | 'DESC'): this;
33
+ limit(value: number): this;
34
+ offset(value: number): this;
35
+ with(name: string, subQuery: QueryBuilder<any>, recursive?: boolean): this;
36
+ fromSubquery(sub: QueryBuilder<any>, alias: string): this;
37
+ clone(): QueryBuilder<T>;
38
+ build(): {
39
+ query: string;
40
+ params: any[];
41
+ };
42
+ execute(): Promise<T[]>;
43
+ }
@@ -0,0 +1,146 @@
1
+ import ParamContext from '../core/ParamContext';
2
+ import ConditionBuilder from './ConditionBuilder';
3
+ export default class QueryBuilder {
4
+ constructor(table, executor, dialect, cacheTTL) {
5
+ this.executor = executor;
6
+ this.dialect = dialect;
7
+ this.cacheTTL = cacheTTL;
8
+ this.fields = [];
9
+ this.joins = [];
10
+ this.groupByFields = [];
11
+ this.orderByFields = [];
12
+ this.ctes = [];
13
+ this.fromClause = table;
14
+ this.ctx = new ParamContext(this.dialect);
15
+ this.condition = new ConditionBuilder(this.ctx);
16
+ this.havingCondition = new ConditionBuilder(this.ctx);
17
+ }
18
+ select(fields) {
19
+ this.fields = fields.map(String);
20
+ return this;
21
+ }
22
+ addJoin(type, table, localKey, foreignKey) {
23
+ this.joins.push(`${type} JOIN ${table} ON ${localKey} = ${foreignKey}`);
24
+ return this;
25
+ }
26
+ join(table, localKey, foreignKey) {
27
+ return this.addJoin('INNER', table, localKey, foreignKey);
28
+ }
29
+ leftJoin(table, localKey, foreignKey) {
30
+ return this.addJoin('LEFT', table, localKey, foreignKey);
31
+ }
32
+ rightJoin(table, localKey, foreignKey) {
33
+ return this.addJoin('RIGHT', table, localKey, foreignKey);
34
+ }
35
+ where(obj) {
36
+ this.condition.where(obj);
37
+ return this;
38
+ }
39
+ whereRaw(expression) {
40
+ this.condition.raw(expression);
41
+ return this;
42
+ }
43
+ andGroup(cb) {
44
+ this.condition.andGroup(cb);
45
+ return this;
46
+ }
47
+ orGroup(cb) {
48
+ this.condition.orGroup(cb);
49
+ return this;
50
+ }
51
+ groupBy(fields) {
52
+ if (Array.isArray(fields)) {
53
+ this.groupByFields.push(...fields);
54
+ }
55
+ else {
56
+ this.groupByFields.push(fields);
57
+ }
58
+ return this;
59
+ }
60
+ having(obj) {
61
+ this.havingCondition.where(obj);
62
+ return this;
63
+ }
64
+ havingRaw(expr) {
65
+ this.havingCondition.raw(expr);
66
+ return this;
67
+ }
68
+ orderBy(column, direction = 'ASC') {
69
+ this.orderByFields.push(`${column} ${direction}`);
70
+ return this;
71
+ }
72
+ limit(value) {
73
+ this.limitCount = value;
74
+ return this;
75
+ }
76
+ offset(value) {
77
+ this.offsetCount = value;
78
+ return this;
79
+ }
80
+ with(name, subQuery, recursive = false) {
81
+ this.ctes.push({ name, query: subQuery, recursive });
82
+ return this;
83
+ }
84
+ fromSubquery(sub, alias) {
85
+ const { query, params } = sub.build();
86
+ params.forEach(p => this.ctx.add(p));
87
+ this.fromClause = `(${query}) AS ${alias}`;
88
+ return this;
89
+ }
90
+ clone() {
91
+ const qb = new QueryBuilder(this.fromClause, this.executor, this.dialect, this.cacheTTL);
92
+ qb.fields = [...this.fields];
93
+ qb.joins = [...this.joins];
94
+ qb.groupByFields = [...this.groupByFields];
95
+ qb.orderByFields = [...this.orderByFields];
96
+ qb.limitCount = this.limitCount;
97
+ qb.offsetCount = this.offsetCount;
98
+ qb.ctes = [...this.ctes];
99
+ return qb;
100
+ }
101
+ build() {
102
+ let query = '';
103
+ if (this.ctes.length) {
104
+ const recursive = this.ctes.some(c => c.recursive);
105
+ query += `WITH ${recursive ? 'RECURSIVE ' : ''}`;
106
+ const parts = this.ctes.map(cte => {
107
+ const { query: q, params } = cte.query.build();
108
+ params.forEach(p => this.ctx.add(p));
109
+ return `${cte.name} AS (${q})`;
110
+ });
111
+ query += parts.join(', ') + ' ';
112
+ }
113
+ const select = this.fields.length ? this.fields.join(', ') : '*';
114
+ query += `SELECT ${select} FROM ${this.fromClause}`;
115
+ if (this.joins.length) {
116
+ query += ' ' + this.joins.join(' ');
117
+ }
118
+ const where = this.condition.build();
119
+ if (where)
120
+ query += ' ' + where;
121
+ if (this.groupByFields.length) {
122
+ query += ` GROUP BY ${this.groupByFields.join(', ')}`;
123
+ }
124
+ const having = this.havingCondition.build('HAVING');
125
+ if (having)
126
+ query += ' ' + having;
127
+ if (this.orderByFields.length) {
128
+ query += ` ORDER BY ${this.orderByFields.join(', ')}`;
129
+ }
130
+ if (this.limitCount) {
131
+ query += ` LIMIT ${this.limitCount}`;
132
+ }
133
+ if (this.offsetCount) {
134
+ query += ` OFFSET ${this.offsetCount}`;
135
+ }
136
+ return {
137
+ query,
138
+ params: this.ctx.getParams()
139
+ };
140
+ }
141
+ async execute() {
142
+ const { query, params } = this.build();
143
+ const result = await this.executor.execute(query, params, this.cacheTTL);
144
+ return result.rows;
145
+ }
146
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "pg-query-sdk",
3
+ "version": "1.0.0",
4
+ "description": "PostgreSQL SDK with Query Builder and Executor",
5
+ "main": "dist/cjs/index.js",
6
+ "types": "dist/esm/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/cjs/index.js",
10
+ "import": "./dist/esm/index.js",
11
+ "types": "./dist/esm/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build:cjs": "tsc -p tsconfig.cjs.json",
16
+ "build:esm": "tsc -p tsconfig.esm.json",
17
+ "build": "npm run build:cjs && npm run build:esm",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "author": {
24
+ "name": "Guilherme",
25
+ "email": "sguii5147@gmail.com",
26
+ "url": "https://github.com/guio11221"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/guio11221/pg-query-sdk.git"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/guio11221/pg-query-sdk/issues"
34
+ },
35
+ "homepage": "https://github.com/guio11221/pg-query-sdk#readme",
36
+ "license": "MIT",
37
+ "dependencies": {
38
+ "pg": "^8.18.0"
39
+ },
40
+ "devDependencies": {
41
+ "typescript": "^5.3.3",
42
+ "@types/node": "^20.10.5",
43
+ "@types/pg": "^8.16.0"
44
+ }
45
+ }