rawsql-ts 0.10.3-beta → 0.10.5-beta

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.md CHANGED
@@ -23,7 +23,9 @@ It is designed for extensibility and advanced SQL analysis, with initial focus o
23
23
  - High-speed SQL parsing and AST analysis (over 3x faster than major libraries)
24
24
  - Rich utilities for SQL structure transformation and analysis
25
25
  - Advanced SQL formatting capabilities, including multi-line formatting and customizable styles
26
- - Dynamic SQL parameter injection for building flexible search queries with `SqlParamInjector`
26
+ - Dynamic SQL parameter injection for building flexible search queries with `SqlParamInjector` (supports like, ilike, in, any, range queries, OR/AND conditions and more)
27
+ - Dynamic ORDER BY clause injection with `SqlSortInjector` for flexible sorting with support for ASC/DESC, NULLS positioning, and append mode
28
+ - Dynamic LIMIT/OFFSET pagination injection with `SqlPaginationInjector` for efficient data pagination with page-based and offset-based support
27
29
  - Type-safe schema management and JSON mapping conversion with full TypeScript support
28
30
  - Static query validation and regression testing against your database schema with `SqlSchemaValidator`, enabling early error detection and robust unit tests for schema changes.
29
31
 
@@ -64,43 +66,46 @@ npm install rawsql-ts
64
66
 
65
67
  ## Quick Start
66
68
 
67
- ---
68
-
69
69
  Kickstart your project by dynamically injecting parameters with `SqlParamInjector` for flexible query generation right from the start!
70
70
 
71
71
  ```typescript
72
72
  import { SqlParamInjector, SqlFormatter } from 'rawsql-ts';
73
73
 
74
- // Define a base SQL query with an alias, using TRUE for boolean conditions
75
- const baseSql = `SELECT u.user_id, u.user_name, u.email FROM users as u WHERE u.active = TRUE`;
74
+ // Define a base SQL query with an alias
75
+ const baseSql = `SELECT u.user_id, u.user_name, u.email, u.phone FROM users as u WHERE u.active = TRUE`;
76
76
 
77
- // Imagine you have search parameters from a user's input
77
+ // Search parameters with OR conditions and AND combination
78
78
  const searchParams = {
79
- user_name: { like: '%Alice%' }, // Find users whose name contains 'Alice'
80
- email: 'specific.email@example.com' // And have a specific email
79
+ name_or_email: {
80
+ or: [
81
+ { column: 'user_name', ilike: '%alice%' },
82
+ { column: 'email', ilike: '%alice%' }
83
+ ]
84
+ },
85
+ phone: { like: '%080%' } // AND condition
81
86
  };
82
87
 
83
88
  const injector = new SqlParamInjector();
84
89
  // Dynamically inject searchParams into the baseSql
85
90
  const query = injector.inject(baseSql, searchParams);
86
91
 
87
- // Format the dynamically generated query (e.g., using PostgreSQL preset)
92
+ // Format the dynamically generated query
88
93
  const formatter = new SqlFormatter({ preset: 'postgres' });
89
94
  const { formattedSql, params } = formatter.format(query);
90
95
 
91
- console.log('Dynamically Generated SQL:');
96
+ console.log('Generated SQL:');
92
97
  console.log(formattedSql);
93
- // Expected output (PostgreSQL style):
94
- // select "u"."user_id", "u"."user_name", "u"."email"
98
+ // Output:
99
+ // select "u"."user_id", "u"."user_name", "u"."email", "u"."phone"
95
100
  // from "users" as "u"
96
101
  // where "u"."active" = true
97
- // and "u"."user_name" like :user_name_like
98
- // and "u"."email" = :email
102
+ // and ("u"."user_name" ilike :name_or_email_or_0_ilike
103
+ // or "u"."email" ilike :name_or_email_or_1_ilike)
104
+ // and "u"."phone" like :phone_like
99
105
 
100
- console.log('\\nParameters:');
106
+ console.log('Parameters:');
101
107
  console.log(params);
102
- // Expected output:
103
- // { user_name_like: '%Alice%', email: 'specific.email@example.com' }
108
+ // Output: { name_or_email_or_0_ilike: '%alice%', name_or_email_or_1_ilike: '%alice%', phone_like: '%080%' }
104
109
  ```
105
110
 
106
111
  ---
@@ -177,6 +182,8 @@ Key benefits include:
177
182
  - **Performance-Oriented**: Conditions are intelligently inserted as close to the data source as possible, significantly improving query performance by filtering data early.
178
183
  - **Zero Conditional Logic in Code**: Forget writing complex IF statements in your application code to handle different filters.
179
184
  - **Enhanced SQL Reusability**: Your base SQL remains clean and can be reused across different scenarios with varying search criteria.
185
+ - **Rich Operator Support**: Supports various SQL operators including equality, comparison, range (min/max), pattern matching (like/ilike), IN clauses, and PostgreSQL array operators.
186
+ - **Advanced Condition Logic**: Supports OR/AND conditions, automatic parentheses grouping, and explicit column mapping for flexible query construction.
180
187
 
181
188
  ```typescript
182
189
  import { SqlParamInjector, SqlFormatter } from 'rawsql-ts';
@@ -199,6 +206,109 @@ For more details, see the [SqlParamInjector Usage Guide](./docs/usage-guides/cla
199
206
 
200
207
  ---
201
208
 
209
+ ## SqlSortInjector Features
210
+
211
+ The `SqlSortInjector` class enables dynamic ORDER BY clause injection into SQL queries, providing a clean and flexible way to handle sorting requirements. Instead of manually constructing different SQL statements for various sorting scenarios, you can inject sort conditions into your base SQL query, making your code more maintainable and reusable.
212
+
213
+ Key benefits include:
214
+ - **Dynamic Sort Injection**: Add ORDER BY conditions to existing queries without modifying the base SQL
215
+ - **Flexible Sort Options**: Support for ASC/DESC directions with NULLS FIRST/LAST positioning
216
+ - **Append Mode**: Preserves existing ORDER BY clauses and appends new conditions
217
+ - **Column Alias Support**: Works seamlessly with column aliases and calculated expressions
218
+ - **TableColumnResolver Integration**: Supports wildcard SELECT queries through schema resolution
219
+ - **Clean Separation**: Remove existing ORDER BY clauses when needed with `removeOrderBy()`
220
+
221
+ ```typescript
222
+ import { SqlSortInjector, SqlFormatter } from 'rawsql-ts';
223
+
224
+ // Basic sort injection
225
+ const baseSql = 'SELECT id, name, created_at FROM users WHERE active = true';
226
+ const sortConditions = {
227
+ created_at: { desc: true, nullsLast: true },
228
+ name: { asc: true }
229
+ };
230
+
231
+ const injector = new SqlSortInjector();
232
+ const sortedQuery = injector.inject(baseSql, sortConditions);
233
+
234
+ const formatter = new SqlFormatter();
235
+ const { formattedSql } = formatter.format(sortedQuery);
236
+
237
+ console.log(formattedSql);
238
+ // Output: select "id", "name", "created_at" from "users" where "active" = true order by "created_at" desc nulls last, "name"
239
+
240
+ // Append to existing ORDER BY
241
+ const existingSql = 'SELECT id, name FROM users ORDER BY id ASC';
242
+ const additionalSort = { name: { desc: true } };
243
+ const appendedQuery = injector.inject(existingSql, additionalSort);
244
+ // Result: SELECT id, name FROM users ORDER BY id ASC, name DESC
245
+
246
+ // Remove existing ORDER BY when needed
247
+ const cleanQuery = SqlSortInjector.removeOrderBy(existingSql);
248
+ const newSortedQuery = injector.inject(cleanQuery, { name: { desc: true } });
249
+ // Result: SELECT id, name FROM users ORDER BY name DESC
250
+ ```
251
+
252
+ For more details, see the [SqlSortInjector Usage Guide](./docs/usage-guides/class-SqlSortInjector-usage-guide.md).
253
+
254
+ ---
255
+
256
+ ## SqlPaginationInjector Features
257
+
258
+ The `SqlPaginationInjector` class enables dynamic LIMIT/OFFSET clause injection into SQL queries, providing a clean and efficient way to handle data pagination. Instead of manually constructing different SQL statements for various page sizes and offsets, you can inject pagination into your base SQL query, making your code more maintainable and performance-optimized.
259
+
260
+ Key benefits include:
261
+ - **Page-Based Pagination**: Simple page number and page size configuration with automatic offset calculation
262
+ - **Automatic OFFSET Optimization**: Smart handling where page 1 omits unnecessary OFFSET 0 clauses
263
+ - **Existing Clause Detection**: Prevents conflicts by detecting and reporting existing LIMIT/OFFSET clauses
264
+ - **Validation & Safety**: Built-in validation for page numbers, page sizes, and configurable maximum limits
265
+ - **Clean Removal**: Remove existing pagination clauses when needed with `removePagination()`
266
+ - **Performance Conscious**: Generates standard LIMIT/OFFSET patterns optimized for database engines
267
+
268
+ ```typescript
269
+ import { SqlPaginationInjector, SqlFormatter } from 'rawsql-ts';
270
+
271
+ // Basic pagination injection
272
+ const baseSql = 'SELECT id, name, email FROM users WHERE active = true ORDER BY created_at DESC';
273
+ const pagination = {
274
+ page: 2, // Page number (1-based)
275
+ pageSize: 20 // Items per page
276
+ };
277
+
278
+ const injector = new SqlPaginationInjector();
279
+ const paginatedQuery = injector.inject(baseSql, pagination);
280
+
281
+ const formatter = new SqlFormatter();
282
+ const { formattedSql } = formatter.format(paginatedQuery);
283
+
284
+ console.log(formattedSql);
285
+ // Output: select "id", "name", "email" from "users" where "active" = true order by "created_at" desc limit 20 offset 20
286
+
287
+ // First page optimization (no OFFSET needed)
288
+ const firstPagePagination = { page: 1, pageSize: 10 };
289
+ const firstPageQuery = injector.inject(baseSql, firstPagePagination);
290
+ const { formattedSql: firstPageSql } = formatter.format(firstPageQuery);
291
+ console.log(firstPageSql);
292
+ // Output: select "id", "name", "email" from "users" where "active" = true order by "created_at" desc limit 10
293
+
294
+ // Remove existing pagination when needed
295
+ const existingPaginatedSql = 'SELECT id, name FROM users LIMIT 50 OFFSET 100';
296
+ const cleanQuery = SqlPaginationInjector.removePagination(existingPaginatedSql);
297
+ const newPagination = { page: 1, pageSize: 25 };
298
+ const repaginatedQuery = injector.inject(cleanQuery, newPagination);
299
+ // Result: Clean query with new pagination applied
300
+
301
+ // Combine with other injectors for complete query building
302
+ let query = new SqlParamInjector().inject(baseSql, { status: 'active' });
303
+ query = new SqlSortInjector().inject(query, { created_at: { desc: true } });
304
+ query = new SqlPaginationInjector().inject(query, { page: 3, pageSize: 15 });
305
+ // Result: Filtered, sorted, and paginated query ready for execution
306
+ ```
307
+
308
+ For more details, see the [SqlPaginationInjector Usage Guide](./docs/usage-guides/class-SqlPaginationInjector-usage-guide.md).
309
+
310
+ ---
311
+
202
312
  ## PostgresJsonQueryBuilder Features
203
313
 
204
314
  The `PostgresJsonQueryBuilder` class transforms relational SQL queries into PostgreSQL JSON queries that return hierarchical JSON structures. It automatically handles complex relationships between entities and generates optimized Common Table Expressions (CTEs) for efficient JSON aggregation, making it perfect for building APIs, reports, and data exports.
package/dist/esm/index.js CHANGED
@@ -18,6 +18,8 @@ export * from './transformers/TableSourceCollector';
18
18
  export * from './transformers/UpstreamSelectQueryFinder';
19
19
  export * from './transformers/SchemaCollector';
20
20
  export * from './transformers/SqlParamInjector';
21
+ export * from './transformers/SqlSortInjector';
22
+ export * from './transformers/SqlPaginationInjector';
21
23
  export * from './utils/SqlSchemaValidator';
22
24
  export * from './utils/SchemaManager';
23
25
  // Add more exports here if you want to expose additional public API
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AAErC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yCAAyC,CAAC;AACxD,cAAc,6BAA6B,CAAC,CAAC,0BAA0B;AACvE,cAAc,qCAAqC,CAAC;AACpD,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,qCAAqC,CAAC;AACpD,cAAc,0CAA0C,CAAC;AACzD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,oEAAoE"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AAErC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yCAAyC,CAAC;AACxD,cAAc,6BAA6B,CAAC,CAAC,0BAA0B;AACvE,cAAc,qCAAqC,CAAC;AACpD,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,qCAAqC,CAAC;AACpD,cAAc,0CAA0C,CAAC;AACzD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AAErD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,oEAAoE"}