happy-sql 1.0.1 → 1.1.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/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ 2026.07.27, v1.1.0
2
+
3
+ feature:
4
+ - f6446c3 happy-sql: COUNT
5
+
1
6
  2026.07.27, v1.0.1
2
7
 
3
8
  feature:
package/README.md CHANGED
@@ -17,6 +17,17 @@ SQL to JS AST parser and printer.
17
17
  npm i happy-sql --save
18
18
  ```
19
19
 
20
+ ## API
21
+
22
+ ```js
23
+ const source = `select(count('*'), from(users))`;
24
+
25
+ convertJsToSql(source);
26
+ // returns
27
+ 'SELECT COUNT(*)\nFROM users\n');
28
+
29
+ ```
30
+
20
31
  ## License
21
32
 
22
33
  MIT
@@ -40,14 +40,12 @@ export const parseSqlNode = (source) => {
40
40
 
41
41
  const elements = [];
42
42
 
43
- for (let i = 0; i < cst.statements.length; i++) {
44
- const stmt = cst.statements[i];
45
-
46
- if (stmt.type === 'empty')
43
+ for (const [i, statement] of cst.statements.entries()) {
44
+ if (statement.type === 'empty')
47
45
  continue;
48
46
 
49
- const stmtNode = convertClause(stmt);
50
- const leading = !i ? cst.leading : stmt.leading;
47
+ const stmtNode = convertClause(statement);
48
+ const leading = i ? statement.leading : cst.leading;
51
49
 
52
50
  elements.push(wrapSection(stmtNode, getSectionName(leading)));
53
51
  }
@@ -0,0 +1,23 @@
1
+ import {types} from '@putout/babel';
2
+
3
+ const {
4
+ stringLiteral,
5
+ callExpression,
6
+ identifier,
7
+ } = types;
8
+
9
+ export const isCount = (column) => {
10
+ return column.type === 'func_call' && /count/i.test(column.name.name);
11
+ };
12
+
13
+ export const convertCount = (column) => {
14
+ const {items} = column.args.expr.args;
15
+ const args = [];
16
+
17
+ for (const item of items) {
18
+ if (item.type === 'all_columns')
19
+ args.push(stringLiteral('*'));
20
+ }
21
+
22
+ return callExpression(identifier('count'), args);
23
+ };
@@ -0,0 +1,3 @@
1
+ [
2
+ select(count('*'), from(users)),
3
+ ];
@@ -0,0 +1 @@
1
+ SELECT COUNT(*) FROM users
@@ -3,6 +3,7 @@ import {convertOperand} from '#parser/clause/operand';
3
3
  import {convertFrom} from '#parser/clause/from';
4
4
  import {convertWhere} from '#parser/clause/where';
5
5
  import {findClause} from '#parser/clause/find';
6
+ import {convertCount, isCount} from '#parser/clause/count';
6
7
 
7
8
  const {
8
9
  identifier,
@@ -11,11 +12,14 @@ const {
11
12
  callExpression,
12
13
  } = types;
13
14
 
14
- const convertColumn = (col) => {
15
- if (col.type === 'alias')
16
- return assignmentExpression('=', identifier(col.alias.name), convertOperand(col.expr));
15
+ const convertColumn = (column) => {
16
+ if (isCount(column))
17
+ return convertCount(column);
17
18
 
18
- return identifier(col.name);
19
+ if (column.type === 'alias')
20
+ return assignmentExpression('=', identifier(column.alias.name), convertOperand(column.expr));
21
+
22
+ return identifier(column.name);
19
23
  };
20
24
 
21
25
  const convertColumns = (columns) => {
@@ -2,9 +2,10 @@ import {clauses} from './clauses/clauses.js';
2
2
 
3
3
  export const CallExpression = (path, printer) => {
4
4
  const {name} = path.node.callee;
5
+ const visit = clauses[name];
5
6
 
6
- if (!clauses[name])
7
+ if (!visit)
7
8
  throw Error(`${name} not supported yet`);
8
9
 
9
- clauses[name](path, printer);
10
+ visit(path, printer);
10
11
  };
@@ -9,10 +9,12 @@ import {update} from './update/update.js';
9
9
  import {set} from './set/set.js';
10
10
  import {del} from './delete/delete.js';
11
11
  import {section} from './section/section.js';
12
+ import {count} from './count/count.js';
12
13
 
13
14
  export const clauses = {
14
- select,
15
+ count,
15
16
  from,
17
+ select,
16
18
  where,
17
19
  insert,
18
20
  into,
@@ -0,0 +1,7 @@
1
+ export const count = (path, {write, traverse}) => {
2
+ const [first] = path.get('arguments');
3
+ write('COUNT');
4
+ write('(');
5
+ traverse(first);
6
+ write(')');
7
+ };
@@ -0,0 +1,2 @@
1
+ SELECT COUNT(*)
2
+ FROM users
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-sql",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "sql to js ast parser and printer",
6
6
  "exports": {
@@ -18,6 +18,7 @@
18
18
  "#parser/test": "./test/create-parser-test.js",
19
19
  "#parser/clause": "./lib/parser/visitors/clause/index.js",
20
20
  "#parser/clause/select": "./lib/parser/visitors/clause/select/select.js",
21
+ "#parser/clause/count": "./lib/parser/visitors/clause/count/count.js",
21
22
  "#parser/clause/from": "./lib/parser/visitors/clause/from/from.js",
22
23
  "#parser/clause/where": "./lib/parser/visitors/clause/where/where.js",
23
24
  "#parser/clause/insert": "./lib/parser/visitors/clause/insert/insert.js",
@@ -79,6 +80,7 @@
79
80
  "@putout/babel": "^5.7.3",
80
81
  "@putout/operator-json": "^3.4.0",
81
82
  "@putout/printer": "^18.17.0",
83
+ "just-camel-case": "^6.2.0",
82
84
  "redstd": "^1.0.2",
83
85
  "sql-parser-cst": "^0.42.1"
84
86
  }