@nulledexp/translatable-criteria 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 (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +207 -0
  3. package/package.json +71 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Nelson Alberto Cabrera Quijada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # @nulledexp/translatable-criteria
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/@nulledexp/translatable-criteria.svg)](https://www.npmjs.com/package/@nulledexp/translatable-criteria)
4
+ ![NPM Downloads](https://img.shields.io/npm/dw/%40nulledexp%2Ftranslatable-criteria)
5
+ [![Development Stage](https://img.shields.io/badge/Development-Active%20Development-green)]()
6
+ [![Documentation](https://img.shields.io/badge/Documentation-EN/ES-blue)](./src/docs/introduction/en.md)
7
+
8
+ A TypeScript library for building data-source agnostic, translatable query criteria. Define complex filtering, ordering, and join logic in a structured, type-safe way, then translate it to your specific data source using custom translators.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @nulledexp/translatable-criteria
14
+ ```
15
+
16
+ ## Overview
17
+
18
+ This library simplifies the construction of complex data queries by providing a consistent and abstract way to define filtering, ordering, field selection, pagination (offset and cursor-based), and relationship (joins) configurations. The core concept revolves around the `Criteria` object hierarchy, which allows developers to define sophisticated query specifications in a data source-agnostic manner. These `Criteria` objects can then be processed by a `CriteriaTranslator` (using the Visitor pattern) to generate queries for various data sources.
19
+
20
+ ## Key Features
21
+
22
+ - **Enhanced Type-Safety:** Construct queries with a fluent, strongly-typed interface, benefiting from compile-time and runtime validation of field names, aliases, and join parameters based on your schemas.
23
+ - **Powerful Filtering:** Define intricate filtering logic with multiple operators (including for JSON and arrays) and grouping. Filter groups are automatically normalized for consistency.
24
+ - **Flexible Join System:** Support for various join types (inner, left, full outer) and pivot table configurations, with validation of join parameters according to the relation type.
25
+ - **Default Join Field Selection:** When a join is added, if `setSelect()` is not explicitly called on the `JoinCriteria`, all fields from the joined schema will be automatically included in the main `SELECT` clause. This can be overridden by using `setSelect()` on the specific `JoinCriteria`.
26
+ - **Field Selection:** Specify exactly which fields to retrieve using `setSelect()`. Use `resetSelect()` to select all fields (which is also the default behavior).
27
+ - **Pagination:** Supports both offset-based (`setTake()`, `setSkip()`) and cursor-based (`setCursor()`) pagination.
28
+ - **Visitor Pattern for Translation:** Criteria objects implement an `accept` method, allowing for clean and extensible translation logic via the Visitor pattern.
29
+ - **Data Source Agnostic:** Design criteria independently of the underlying data source.
30
+ - **Translator-Based Architecture:** The core library defines criteria; actual translation is handled by separate translator packages that implement the `CriteriaTranslator` interface.
31
+ - **Full TypeScript Support:** Benefit from compile-time validation and autocompletion.
32
+
33
+ ## Core Concepts
34
+
35
+ The library is built upon a few fundamental concepts. For detailed explanations, please refer to our Core Concepts Documentation.
36
+
37
+ - **`Criteria` Hierarchy:** Abstract base for query specifications (`RootCriteria`, `InnerJoinCriteria`, etc.). Learn more.
38
+ - **`CriteriaFactory`:** Recommended utility for creating `Criteria` instances (e.g., `CriteriaFactory.GetCriteria(...)`, `CriteriaFactory.GetInnerJoinCriteria(...)`). Learn more.
39
+ - **Schemas (`CriteriaSchema` & `GetTypedCriteriaSchema`):** Define your data entities' structure for type-safe criteria construction. Learn more.
40
+ - **`CriteriaTranslator`:** Abstract class for converting `Criteria` objects into specific data source queries using the Visitor pattern. Learn more.
41
+
42
+ ## Usage Example (Core Library)
43
+
44
+ This package provides the tools to define your query criteria.
45
+
46
+ ### 1. Define Schemas
47
+
48
+ ```typescript
49
+ import { GetTypedCriteriaSchema } from '@nulledexp/translatable-criteria';
50
+
51
+ export const UserSchema = GetTypedCriteriaSchema({
52
+ source_name: 'user',
53
+ alias: ['users', 'user', 'publisher'],
54
+ fields: ['uuid', 'email', 'username', 'created_at'],
55
+ joins: [
56
+ { alias: 'posts', join_relation_type: 'one_to_many' },
57
+ // other joins like 'permissions', 'addresses' can be defined here
58
+ ],
59
+ });
60
+ export type UserSchema = typeof UserSchema;
61
+
62
+ export const PostSchema = GetTypedCriteriaSchema({
63
+ source_name: 'post',
64
+ alias: ['posts', 'post'],
65
+ fields: [
66
+ 'uuid',
67
+ 'title',
68
+ 'body',
69
+ 'user_uuid',
70
+ 'created_at',
71
+ 'categories', // Example: for array filters
72
+ 'metadata', // Example: for JSON filters
73
+ ],
74
+ joins: [
75
+ { alias: 'comments', join_relation_type: 'one_to_many' },
76
+ { alias: 'publisher', join_relation_type: 'many_to_one' },
77
+ ],
78
+ });
79
+ export type PostSchema = typeof PostSchema;
80
+
81
+ // Define other schemas (PermissionSchema, PostCommentSchema, AddressSchema) as needed for your application.
82
+ // See the full documentation for more examples.
83
+ ```
84
+
85
+ ### 2. Create Criteria
86
+
87
+ ```typescript
88
+ import {
89
+ CriteriaFactory,
90
+ FilterOperator,
91
+ } from '@nulledexp/translatable-criteria';
92
+ import { UserSchema } from './path/to/your/criteria/schemas'; // Adjust path
93
+
94
+ // Create Criteria for the User entity
95
+ const userCriteria = CriteriaFactory.GetCriteria(UserSchema, 'users');
96
+
97
+ // Example: Add a simple filter
98
+ userCriteria.where({
99
+ field: 'email', // Type-safe based on UserSchema.fields
100
+ operator: FilterOperator.CONTAINS,
101
+ value: '@example.com',
102
+ });
103
+
104
+ // Example: Add ordering
105
+ userCriteria.orderBy('created_at', 'DESC');
106
+
107
+ // The 'userCriteria' object is now ready to be passed to a translator.
108
+ ```
109
+
110
+ ## Available Translators
111
+
112
+ To interact with a database, you'll need a translator package.
113
+
114
+ - **`@nulledexp/typeorm-mysql-criteria-translator`**:
115
+ A translator for generating TypeORM `SelectQueryBuilder` instances for MySQL.
116
+ - **Author:** Nelson Cabrera
117
+ - **Installation**:
118
+
119
+ ```bash
120
+ npm install @nulledexp/typeorm-mysql-criteria-translator
121
+ ```
122
+
123
+ - **Usage (basic)**:
124
+
125
+ ```typescript
126
+ import {
127
+ CriteriaFactory,
128
+ FilterOperator,
129
+ } from '@nulledexp/translatable-criteria';
130
+ import { TypeOrmMysqlTranslator } from '@nulledexp/typeorm-mysql-criteria-translator'; // Using new suggested name
131
+ import { UserSchema } from './path/to/your/criteria/schemas'; // Your Criteria Schema
132
+ // import { YourTypeOrmUserEntity } from './path/to/your/typeorm/entities'; // Your actual TypeORM entity
133
+ // import { DbDatasource } from './path-to-your-datasource-config'; // Your initialized TypeORM DataSource instance
134
+
135
+ // 1. Define your Criteria using @nulledexp/translatable-criteria
136
+ const criteria = CriteriaFactory.GetCriteria(UserSchema, 'users') // 'users' is an alias from UserSchema
137
+ .where({
138
+ field: 'username', // Field from UserSchema
139
+ operator: FilterOperator.EQUALS,
140
+ value: 'testuser',
141
+ })
142
+ .setTake(10);
143
+
144
+ // 2. Use the translator with your TypeORM QueryBuilder
145
+ // (Conceptual - assuming DbDatasource and YourTypeOrmUserEntity are set up)
146
+
147
+ // const queryBuilder = DbDatasource.getRepository(YourTypeOrmUserEntity)
148
+ // .createQueryBuilder(criteria.alias); // Alias must match root criteria alias
149
+
150
+ // const translator = new TypeOrmMysqlTranslator<YourTypeOrmUserEntity>();
151
+ // translator.translate(criteria, queryBuilder);
152
+
153
+ // Now queryBuilder is populated with the translated criteria
154
+ // console.log(queryBuilder.getSql(), queryBuilder.getParameters());
155
+ // const results = await queryBuilder.getMany();
156
+ ```
157
+
158
+ - **Note:** This translator has been tested with integration tests. Please review its implementation at its repository (replace with actual repo link if different) to ensure it meets your specific project needs and production requirements. Contributions and bug reports are welcome!
159
+
160
+ - **(More translators coming soon or can be created by the community)**
161
+
162
+ ### Developing Custom Translators
163
+
164
+ You can create your own translators by extending the abstract `CriteriaTranslator` class. See the Developing Custom Translators Guide for details.
165
+
166
+ ## Type Safety Features
167
+
168
+ - Compile-time validation of field names within criteria based on schemas.
169
+ - Type-checked join configurations ensuring compatibility between schemas.
170
+ - Autocomplete support for schema fields and defined join aliases.
171
+ - Validation of alias usage in `Criteria` constructors.
172
+ - Robust validation of join parameters based on `join_relation_type`.
173
+ - Validation for selected fields, cursor fields, take/skip values.
174
+ - Strictly typed filter values based on the `FilterOperator` used.
175
+
176
+ ## Roadmap (Core Library)
177
+
178
+ - [x] Implement cursor pagination.
179
+ - [x] Implement field selection (`setSelect`, `resetSelect`).
180
+ - [x] Implement `ORDER BY` for root and joined criteria (with `sequenceId` for stable global ordering).
181
+ - [x] Implement `LIMIT` and `OFFSET` (take/skip) for pagination.
182
+ - [x] Implement `PivotJoin` for many-to-many relationships.
183
+ - [x] Strictly typed filter values based on operator.
184
+ - [x] New filter operators (JSON, Array, Set).
185
+ - [x] Enhanced documentation with detailed examples for translator development.
186
+ - [x] `OuterJoinCriteria` support in the core logic.
187
+ - [ ] Explore utility functions to simplify translator development.
188
+ - [ ] Explore utility functions to simplify schema development.
189
+ - [ ] Add more comprehensive unit test coverage for criteria construction and edge cases.
190
+
191
+ ## Contributing
192
+
193
+ This project is in active development. Contributions are welcome! Please feel free to submit a Pull Request on our GitHub repository.
194
+
195
+ ## License
196
+
197
+ This project is licensed under the MIT License - see the `LICENSE` file for details.
198
+
199
+ ## Contact
200
+
201
+ - **LinkedIn:** [Nelson Cabrera](https://www.linkedin.com/in/nulled-nelsoncabrera/)
202
+ - **Email:** [contact@nelsoncabrera.dev](mailto:contact@nelsoncabrera.dev)
203
+ - **GitHub:** [github.com/Techscq](https://github.com/Techscq)
204
+
205
+ ## Author
206
+
207
+ Nelson Cabrera ([@Techscq](https://github.com/Techscq))
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@nulledexp/translatable-criteria",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "description": "A TypeScript library for building data-source agnostic, translatable query criteria. Define complex filtering, ordering, and join logic in a structured, type-safe way, then translate it to your specific data source using custom translators.",
6
+ "keywords": [
7
+ "criteria",
8
+ "query",
9
+ "filter",
10
+ "join",
11
+ "translator",
12
+ "data-access",
13
+ "query-builder",
14
+ "typescript",
15
+ "dsl",
16
+ "database",
17
+ "agnostic",
18
+ "data-source-agnostic"
19
+ ],
20
+ "main": "./dist/index.js",
21
+ "exports": {
22
+ "./package.json": "./package.json",
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "build": "rimraf ./dist && tsc",
30
+ "ci": "npm run check-circular && npm run check-format && npm run check-exports && npm run test",
31
+ "format": "prettier --write .",
32
+ "check-format": "prettier --check .",
33
+ "check-exports": "attw --pack . --ignore-rules=cjs-resolves-to-esm",
34
+ "test": "vitest run",
35
+ "dev": "vitest",
36
+ "build-watch": "tsc --watch",
37
+ "check-circular": "npx madge --circular --extensions ts ./src",
38
+ "local-release": "changeset version && changeset publish",
39
+ "prepublishOnly": "npm run ci"
40
+ },
41
+ "homepage": "https://github.com/Techscq/translatable-criteria",
42
+ "bugs": {
43
+ "url": "https://github.com/Techscq/translatable-criteria/issues"
44
+ },
45
+ "author": "Nelson Cabrera <contact@nelsoncabrera.dev>",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/Techscq/translatable-criteria.git"
49
+ },
50
+ "files": [
51
+ "dist",
52
+ "LICENSE",
53
+ "README.md"
54
+ ],
55
+ "type": "module",
56
+ "devDependencies": {
57
+ "@arethetypeswrong/cli": "^0.18.2",
58
+ "@changesets/cli": "^2.29.4",
59
+ "@types/node": "^24.0.0",
60
+ "@types/uuid": "^10.0.0",
61
+ "dotenv": "^16.5.0",
62
+ "madge": "^7.0.0",
63
+ "prettier": "^3.5.3",
64
+ "rimraf": "^6.0.1",
65
+ "ts-unused-exports": "^11.0.1",
66
+ "tsx": "^4.20.1",
67
+ "typescript": "^5.8.3",
68
+ "uuid": "^11.1.0",
69
+ "vitest": "^3.2.3"
70
+ }
71
+ }