rawsql-ts 0.9.0-beta → 0.10.1-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 +90 -7
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/models/SqlPrintToken.js +2 -0
- package/dist/esm/models/SqlPrintToken.js.map +1 -1
- package/dist/esm/models/ValueComponent.js +13 -12
- package/dist/esm/models/ValueComponent.js.map +1 -1
- package/dist/esm/parsers/SqlPrintTokenParser.js +24 -6
- package/dist/esm/parsers/SqlPrintTokenParser.js.map +1 -1
- package/dist/esm/transformers/PostgresArrayEntityCteBuilder.js +231 -0
- package/dist/esm/transformers/PostgresArrayEntityCteBuilder.js.map +1 -0
- package/dist/esm/transformers/PostgresJsonQueryBuilder.js +226 -0
- package/dist/esm/transformers/PostgresJsonQueryBuilder.js.map +1 -0
- package/dist/esm/transformers/PostgresObjectEntityCteBuilder.js +283 -0
- package/dist/esm/transformers/PostgresObjectEntityCteBuilder.js.map +1 -0
- package/dist/esm/transformers/SqlPrinter.js +9 -3
- package/dist/esm/transformers/SqlPrinter.js.map +1 -1
- package/dist/esm/types/index.d.ts +2 -0
- package/dist/esm/types/models/SqlPrintToken.d.ts +2 -0
- package/dist/esm/types/models/ValueComponent.d.ts +2 -2
- package/dist/esm/types/transformers/PostgresArrayEntityCteBuilder.d.ts +97 -0
- package/dist/esm/types/transformers/PostgresJsonQueryBuilder.d.ts +86 -0
- package/dist/esm/types/transformers/PostgresObjectEntityCteBuilder.d.ts +140 -0
- package/dist/esm/types/utils/SchemaManager.d.ts +132 -0
- package/dist/esm/utils/SchemaManager.js +194 -0
- package/dist/esm/utils/SchemaManager.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/models/SqlPrintToken.d.ts +2 -0
- package/dist/models/SqlPrintToken.js +2 -0
- package/dist/models/SqlPrintToken.js.map +1 -1
- package/dist/models/ValueComponent.d.ts +2 -2
- package/dist/models/ValueComponent.js +13 -12
- package/dist/models/ValueComponent.js.map +1 -1
- package/dist/parsers/SelectQueryParser.js +3 -14
- package/dist/parsers/SelectQueryParser.js.map +1 -1
- package/dist/parsers/SqlPrintTokenParser.js +25 -7
- package/dist/parsers/SqlPrintTokenParser.js.map +1 -1
- package/dist/transformers/PostgresArrayEntityCteBuilder.d.ts +97 -0
- package/dist/transformers/PostgresArrayEntityCteBuilder.js +235 -0
- package/dist/transformers/PostgresArrayEntityCteBuilder.js.map +1 -0
- package/dist/transformers/PostgresJsonQueryBuilder.d.ts +86 -0
- package/dist/transformers/PostgresJsonQueryBuilder.js +230 -0
- package/dist/transformers/PostgresJsonQueryBuilder.js.map +1 -0
- package/dist/transformers/PostgresObjectEntityCteBuilder.d.ts +140 -0
- package/dist/transformers/PostgresObjectEntityCteBuilder.js +287 -0
- package/dist/transformers/PostgresObjectEntityCteBuilder.js.map +1 -0
- package/dist/transformers/SqlFormatter.js +6 -1
- package/dist/transformers/SqlFormatter.js.map +1 -1
- package/dist/transformers/SqlPrinter.js +9 -3
- package/dist/transformers/SqlPrinter.js.map +1 -1
- package/dist/utils/SchemaManager.d.ts +132 -0
- package/dist/utils/SchemaManager.js +201 -0
- package/dist/utils/SchemaManager.js.map +1 -0
- package/package.json +1 -1
@@ -0,0 +1,97 @@
|
|
1
|
+
import { CommonTable } from '../models/Clause';
|
2
|
+
import { JsonMapping } from './PostgresJsonQueryBuilder';
|
3
|
+
import { ProcessableEntity } from './PostgresObjectEntityCteBuilder';
|
4
|
+
/**
|
5
|
+
* PostgreSQL-specific builder for creating CTEs for array entities (array relationships).
|
6
|
+
* This class handles the creation of CTEs that build JSON/JSONB arrays for child entities,
|
7
|
+
* processing them from the deepest level up to ensure proper dependency ordering.
|
8
|
+
*
|
9
|
+
* Features:
|
10
|
+
* - Depth-based CTE naming (cte_array_depth_N)
|
11
|
+
* - Row compression using GROUP BY operations
|
12
|
+
* - JSONB/JSON array aggregation
|
13
|
+
* - Hierarchical processing of nested arrays
|
14
|
+
* - Column exclusion to avoid duplication
|
15
|
+
*
|
16
|
+
* Why depth calculation is critical:
|
17
|
+
* 1. Array entities can be nested at multiple levels. We must process the deepest
|
18
|
+
* (most distant) arrays first to ensure their JSON representations are available
|
19
|
+
* when building their parent arrays.
|
20
|
+
* 2. Array entity processing is essentially a row compression operation using GROUP BY.
|
21
|
+
* Unlike parent entities which use column compression, arrays require grouping
|
22
|
+
* to aggregate multiple rows into JSON arrays.
|
23
|
+
*
|
24
|
+
* Example hierarchy:
|
25
|
+
* Order (root, depth 0)
|
26
|
+
* └─ Items (array, depth 1)
|
27
|
+
* └─ Details (array, depth 2)
|
28
|
+
*
|
29
|
+
* Processing order: depth 2 → depth 1 → depth 0
|
30
|
+
*/
|
31
|
+
export declare class PostgresArrayEntityCteBuilder {
|
32
|
+
private static readonly CTE_ARRAY_PREFIX;
|
33
|
+
/**
|
34
|
+
* Build CTEs for all array entities in the correct dependency order
|
35
|
+
* @param ctesSoFar Array of CTEs built so far (starts with the initial CTE)
|
36
|
+
* @param aliasOfCteToBuildUpon Alias of the CTE from which the current array CTE will select
|
37
|
+
* @param allEntities Map of all entities in the mapping
|
38
|
+
* @param mapping The JSON mapping configuration
|
39
|
+
* @returns Object containing the updated list of all CTEs and the alias of the last CTE created
|
40
|
+
*/
|
41
|
+
buildArrayEntityCtes(ctesSoFar: CommonTable[], aliasOfCteToBuildUpon: string, allEntities: Map<string, ProcessableEntity>, mapping: JsonMapping): {
|
42
|
+
updatedCtes: CommonTable[];
|
43
|
+
lastCteAlias: string;
|
44
|
+
};
|
45
|
+
/**
|
46
|
+
* Collect all array entities and calculate their depth from root.
|
47
|
+
*
|
48
|
+
* Depth calculation ensures proper processing order where deeper nested
|
49
|
+
* arrays are processed first, making their aggregated data available
|
50
|
+
* for parent array processing.
|
51
|
+
*
|
52
|
+
* @param mapping The JSON mapping configuration
|
53
|
+
* @param allEntities Map of all entities in the mapping
|
54
|
+
* @returns Array of array entity information with calculated depths, sorted deepest first
|
55
|
+
*/
|
56
|
+
private collectAndSortArrayEntities;
|
57
|
+
/**
|
58
|
+
* Group array entities by their depth level.
|
59
|
+
*
|
60
|
+
* Grouping by depth allows us to:
|
61
|
+
* - Process all entities at the same level in a single CTE
|
62
|
+
* - Optimize query performance by reducing the number of CTEs
|
63
|
+
* - Maintain clear dependency ordering
|
64
|
+
*
|
65
|
+
* @param arrayInfos Array of array entity information with depths
|
66
|
+
* @returns Map of depth level to entities at that depth
|
67
|
+
*/
|
68
|
+
private groupEntitiesByDepth;
|
69
|
+
/**
|
70
|
+
* Build a CTE that processes all array entities at a specific depth level.
|
71
|
+
*
|
72
|
+
* This method creates a single CTE that aggregates multiple array entities
|
73
|
+
* at the same depth, using GROUP BY to compress rows into JSON arrays.
|
74
|
+
*
|
75
|
+
* @param infos Array entities at this depth level
|
76
|
+
* @param currentCteAlias Alias of the CTE to build upon
|
77
|
+
* @param currentCtes All CTEs built so far
|
78
|
+
* @param depth Current depth level being processed
|
79
|
+
* @param mapping JSON mapping configuration
|
80
|
+
* @returns The new CTE and its alias
|
81
|
+
*/
|
82
|
+
private buildDepthCte;
|
83
|
+
/**
|
84
|
+
* Build JSON aggregation function for an array entity.
|
85
|
+
*
|
86
|
+
* This method creates a jsonb_agg or json_agg function call that aggregates
|
87
|
+
* the entity's columns into a JSON array. It also handles nested relationships
|
88
|
+
* by including child entity properties in the JSON object.
|
89
|
+
*
|
90
|
+
* @param entity The array entity being processed
|
91
|
+
* @param nestedEntities All nested entities from the mapping
|
92
|
+
* @param allEntities Map of all entities (not used in current implementation)
|
93
|
+
* @param useJsonb Whether to use JSONB functions
|
94
|
+
* @returns Object containing the JSON aggregation function
|
95
|
+
*/
|
96
|
+
private buildAggregationDetailsForArrayEntity;
|
97
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import { SimpleSelectQuery } from '../models/SimpleSelectQuery';
|
2
|
+
/**
|
3
|
+
* Universal JSON mapping definition for creating any level of JSON structures.
|
4
|
+
* Supports flat arrays, nested objects, and unlimited hierarchical structures.
|
5
|
+
*/
|
6
|
+
export interface JsonMapping {
|
7
|
+
rootName: string;
|
8
|
+
rootEntity: {
|
9
|
+
id: string;
|
10
|
+
name: string;
|
11
|
+
columns: {
|
12
|
+
[jsonKey: string]: string;
|
13
|
+
};
|
14
|
+
};
|
15
|
+
nestedEntities: Array<{
|
16
|
+
id: string;
|
17
|
+
name: string;
|
18
|
+
parentId: string;
|
19
|
+
propertyName: string;
|
20
|
+
relationshipType?: "object" | "array";
|
21
|
+
columns: {
|
22
|
+
[jsonKey: string]: string;
|
23
|
+
};
|
24
|
+
}>;
|
25
|
+
useJsonb?: boolean;
|
26
|
+
resultFormat?: "array" | "single";
|
27
|
+
emptyResult?: string;
|
28
|
+
}
|
29
|
+
/**
|
30
|
+
* PostgreSQL JSON query builder that transforms SimpleSelectQuery into queries
|
31
|
+
* that return JSON arrays or single JSON objects using PostgreSQL JSON functions.
|
32
|
+
*/
|
33
|
+
export declare class PostgresJsonQueryBuilder {
|
34
|
+
private selectValueCollector;
|
35
|
+
private objectEntityCteBuilder;
|
36
|
+
private arrayEntityCteBuilder;
|
37
|
+
constructor();
|
38
|
+
/**
|
39
|
+
* Validates the JSON mapping and the original query.
|
40
|
+
* @param query Original query to transform
|
41
|
+
* @param mapping JSON mapping configuration
|
42
|
+
*/
|
43
|
+
private validateMapping;
|
44
|
+
/**
|
45
|
+
* Build JSON query from original query and mapping configuration.
|
46
|
+
* @param originalQuery Original query to transform
|
47
|
+
* @param mapping JSON mapping configuration
|
48
|
+
* @returns Transformed query with JSON aggregation
|
49
|
+
*/
|
50
|
+
buildJsonQuery(originalQuery: SimpleSelectQuery, mapping: JsonMapping): SimpleSelectQuery;
|
51
|
+
/**
|
52
|
+
* Build JSON query from original query and mapping configuration.
|
53
|
+
* @deprecated Use buildJsonQuery instead. This method will be removed in a future version.
|
54
|
+
* @param originalQuery Original query to transform
|
55
|
+
* @param mapping JSON mapping configuration
|
56
|
+
* @returns Transformed query with JSON aggregation
|
57
|
+
*/
|
58
|
+
buildJson(originalQuery: SimpleSelectQuery, mapping: JsonMapping): SimpleSelectQuery;
|
59
|
+
/**
|
60
|
+
* Builds the JSON structure using a unified CTE-based strategy.
|
61
|
+
* @param originalQuery Original query
|
62
|
+
* @param mapping JSON mapping configuration
|
63
|
+
* @returns Query with CTE-based JSON aggregation
|
64
|
+
*/
|
65
|
+
private buildJsonWithCteStrategy;
|
66
|
+
/**
|
67
|
+
* Creates the initial Common Table Expression (CTE) from the original query.
|
68
|
+
* @param originalQuery The base SimpleSelectQuery.
|
69
|
+
* @returns An object containing the initial CTE and its alias.
|
70
|
+
*/
|
71
|
+
private createInitialCte;
|
72
|
+
/**
|
73
|
+
* Builds the final SELECT query that constructs the root JSON object (or array of objects).
|
74
|
+
* This query uses all previously generated CTEs.
|
75
|
+
* @param finalCtesList The complete list of all CTEs (initial and array CTEs).
|
76
|
+
* @param lastCteAliasForFromClause Alias of the final CTE from which the root object will be built.
|
77
|
+
* @param allEntities Map of all processable entities.
|
78
|
+
* @param mapping JSON mapping configuration.
|
79
|
+
* @returns The final SimpleSelectQuery.
|
80
|
+
*/
|
81
|
+
private buildFinalSelectQuery;
|
82
|
+
/**
|
83
|
+
* Build JSON object for entity, using parent JSON columns when available
|
84
|
+
*/
|
85
|
+
private buildEntityJsonObject;
|
86
|
+
}
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import { CommonTable } from '../models/Clause';
|
2
|
+
import { JsonMapping } from './PostgresJsonQueryBuilder';
|
3
|
+
/**
|
4
|
+
* Entity with processing metadata
|
5
|
+
*/
|
6
|
+
export interface ProcessableEntity {
|
7
|
+
id: string;
|
8
|
+
name: string;
|
9
|
+
columns: {
|
10
|
+
[jsonKey: string]: string;
|
11
|
+
};
|
12
|
+
isRoot: boolean;
|
13
|
+
propertyName: string;
|
14
|
+
parentId?: string;
|
15
|
+
relationshipType?: "object" | "array";
|
16
|
+
}
|
17
|
+
/**
|
18
|
+
* PostgreSQL-specific builder for creating CTEs for object entities (object relationships).
|
19
|
+
* This class handles the creation of CTEs that build JSON/JSONB objects for object entities,
|
20
|
+
* processing them from the deepest level up to ensure proper dependency ordering.
|
21
|
+
*
|
22
|
+
* Features:
|
23
|
+
* - Depth-based CTE naming (cte_object_depth_N)
|
24
|
+
* - NULL handling for entity columns
|
25
|
+
* - JSONB/JSON object construction
|
26
|
+
* - Hierarchical processing of nested objects
|
27
|
+
*
|
28
|
+
* Why depth calculation is critical:
|
29
|
+
* 1. Object entities can be nested at multiple levels. We must process the deepest
|
30
|
+
* (most distant) objects first to ensure their JSON representations are available
|
31
|
+
* when building their parent entities.
|
32
|
+
* 2. Object entity processing is essentially a column compression operation. Entities
|
33
|
+
* at the same depth level can be processed simultaneously since they don't depend
|
34
|
+
* on each other.
|
35
|
+
*
|
36
|
+
* Example hierarchy:
|
37
|
+
* Order (root, depth 0)
|
38
|
+
* └─ Customer (depth 1)
|
39
|
+
* └─ Address (depth 2)
|
40
|
+
* └─ Shipping (depth 1)
|
41
|
+
* └─ Carrier (depth 2)
|
42
|
+
*
|
43
|
+
* Processing order: depth 2 → depth 1 → depth 0
|
44
|
+
*/
|
45
|
+
export declare class PostgresObjectEntityCteBuilder {
|
46
|
+
private static readonly JSON_COLUMN_SUFFIX;
|
47
|
+
private static readonly CTE_OBJECT_PREFIX;
|
48
|
+
private static readonly WILDCARD_COLUMN; /**
|
49
|
+
* Build CTEs for all object entities in the correct dependency order
|
50
|
+
* @param initialCte The starting CTE containing all raw data
|
51
|
+
* @param allEntities Map of all entities in the mapping
|
52
|
+
* @param mapping The JSON mapping configuration
|
53
|
+
* @returns Array of CTEs and the alias of the last CTE created
|
54
|
+
*/
|
55
|
+
buildObjectEntityCtes(initialCte: CommonTable, allEntities: Map<string, ProcessableEntity>, mapping: JsonMapping): {
|
56
|
+
ctes: CommonTable[];
|
57
|
+
lastCteAlias: string;
|
58
|
+
}; /**
|
59
|
+
* Collect all object entities and calculate their depth from root.
|
60
|
+
*
|
61
|
+
* Depth calculation is crucial because:
|
62
|
+
* - It determines the processing order (deepest first)
|
63
|
+
* - It ensures dependencies are resolved before an entity is processed
|
64
|
+
* - It allows parallel processing of entities at the same depth level
|
65
|
+
*
|
66
|
+
* @param mapping The JSON mapping configuration
|
67
|
+
* @param allEntities Map of all entities in the mapping
|
68
|
+
* @returns Array of object entity information with calculated depths
|
69
|
+
*/
|
70
|
+
private collectAndSortObjectEntities;
|
71
|
+
/**
|
72
|
+
* Group entities by their depth level.
|
73
|
+
*
|
74
|
+
* Grouping by depth allows us to:
|
75
|
+
* - Process all entities at the same level in a single CTE
|
76
|
+
* - Optimize query performance by reducing the number of CTEs
|
77
|
+
* - Maintain clear dependency ordering
|
78
|
+
*
|
79
|
+
* @param parentInfos Array of parent entity information with depths
|
80
|
+
* @returns Map of depth level to entities at that depth
|
81
|
+
*/ private groupEntitiesByDepth;
|
82
|
+
/**
|
83
|
+
* Build a CTE that processes all entities at a specific depth level
|
84
|
+
*/
|
85
|
+
private buildDepthCte;
|
86
|
+
/**
|
87
|
+
* Build JSON column for a single entity with NULL handling
|
88
|
+
*/
|
89
|
+
private buildEntityJsonColumn;
|
90
|
+
/**
|
91
|
+
* Prepare entity columns and NULL checks.
|
92
|
+
*
|
93
|
+
* This method extracts column data and creates NULL checks for each column.
|
94
|
+
* The NULL checking is essential for handling outer joins correctly.
|
95
|
+
*
|
96
|
+
* In outer join scenarios, when there's no matching row in the joined table,
|
97
|
+
* all columns from that table will be NULL. Instead of creating an empty object
|
98
|
+
* with all NULL properties (e.g., {id: null, name: null, email: null}),
|
99
|
+
* we want to represent the absence of the entity as NULL itself.
|
100
|
+
*
|
101
|
+
* This ensures cleaner JSON output where missing relationships are represented
|
102
|
+
* as NULL rather than objects with all NULL fields.
|
103
|
+
*
|
104
|
+
* @param entity The entity whose columns are being processed
|
105
|
+
* @returns Object containing arrays of JSON object arguments and NULL check conditions
|
106
|
+
*/
|
107
|
+
private prepareEntityColumns;
|
108
|
+
/**
|
109
|
+
* Add child object relationships to JSON object arguments.
|
110
|
+
*
|
111
|
+
* This method processes nested object-type entities that are direct children of the current entity.
|
112
|
+
* For each child entity, it adds the property name and corresponding JSON column reference
|
113
|
+
* to the arguments array that will be used to build the parent's JSON object.
|
114
|
+
*
|
115
|
+
* The child JSON columns are expected to already exist in the data source (created by deeper
|
116
|
+
* level CTEs), as we process from the deepest level up to the root.
|
117
|
+
*
|
118
|
+
* Note: In this context, "child" refers to entities that have an object relationship (0..1)
|
119
|
+
* with their parent. From a data perspective, these are typically entities referenced via
|
120
|
+
* foreign keys, representing "parent" entities in traditional database terminology.
|
121
|
+
*
|
122
|
+
* @param entity The current entity being processed
|
123
|
+
* @param jsonObjectArgs Array to which JSON object arguments will be added
|
124
|
+
* @param mapping The JSON mapping configuration
|
125
|
+
* @param allEntities Map of all entities in the mapping
|
126
|
+
*/
|
127
|
+
private addChildObjectRelationships;
|
128
|
+
/**
|
129
|
+
* Create JSON object function call
|
130
|
+
*/
|
131
|
+
private createJsonObject;
|
132
|
+
/**
|
133
|
+
* Build NULL condition from NULL checks
|
134
|
+
*/
|
135
|
+
private buildNullCondition;
|
136
|
+
/**
|
137
|
+
* Create CASE expression with NULL handling
|
138
|
+
*/
|
139
|
+
private createCaseExpression;
|
140
|
+
}
|
@@ -0,0 +1,132 @@
|
|
1
|
+
/**
|
2
|
+
* Schema Manager for rawsql-ts
|
3
|
+
* Provides unified schema definition and automatic conversion to various formats
|
4
|
+
* Eliminates code duplication and provides type-safe schema management
|
5
|
+
*/
|
6
|
+
import type { JsonMapping } from '../transformers/PostgresJsonQueryBuilder';
|
7
|
+
/**
|
8
|
+
* Database column metadata for schema mapping
|
9
|
+
*/
|
10
|
+
export interface ColumnDefinition {
|
11
|
+
/** Column name in database */
|
12
|
+
name: string;
|
13
|
+
/** Primary key indicator - used for UPDATE/DELETE query WHERE conditions */
|
14
|
+
isPrimaryKey?: boolean;
|
15
|
+
/** Foreign key reference */
|
16
|
+
foreignKey?: {
|
17
|
+
table: string;
|
18
|
+
column: string;
|
19
|
+
};
|
20
|
+
/** Alias for JSON output (useful for avoiding conflicts) */
|
21
|
+
jsonAlias?: string;
|
22
|
+
}
|
23
|
+
/**
|
24
|
+
* Table relationship definition
|
25
|
+
*/
|
26
|
+
export interface RelationshipDefinition {
|
27
|
+
/** Type of relationship */
|
28
|
+
type: 'object' | 'array';
|
29
|
+
/** Target table name */
|
30
|
+
table: string;
|
31
|
+
/** Property name in JSON output */
|
32
|
+
propertyName: string;
|
33
|
+
/** Optional: Override target table's primary key */
|
34
|
+
targetKey?: string;
|
35
|
+
}
|
36
|
+
/**
|
37
|
+
* Complete table schema definition that users write
|
38
|
+
*/
|
39
|
+
export interface TableDefinition {
|
40
|
+
/** Table name in database */
|
41
|
+
name: string;
|
42
|
+
/** Human-readable entity name */
|
43
|
+
displayName?: string;
|
44
|
+
/** Column definitions */
|
45
|
+
columns: Record<string, ColumnDefinition>;
|
46
|
+
/** Relationships with other tables */
|
47
|
+
relationships?: RelationshipDefinition[];
|
48
|
+
}
|
49
|
+
/**
|
50
|
+
* Schema registry containing all table definitions
|
51
|
+
*/
|
52
|
+
export interface SchemaRegistry {
|
53
|
+
[tableName: string]: TableDefinition;
|
54
|
+
}
|
55
|
+
/**
|
56
|
+
* Central schema management utility for rawsql-ts
|
57
|
+
* Converts user-defined schemas to various internal formats
|
58
|
+
*/
|
59
|
+
export declare class SchemaManager {
|
60
|
+
private schemas;
|
61
|
+
constructor(schemas: SchemaRegistry);
|
62
|
+
/**
|
63
|
+
* Validate schema definitions for consistency
|
64
|
+
* Ensures each table has a primary key (required for UPDATE/DELETE operations)
|
65
|
+
* and validates relationship references
|
66
|
+
*/
|
67
|
+
private validateSchemas;
|
68
|
+
/**
|
69
|
+
* Get table column names for SqlParamInjector TableColumnResolver
|
70
|
+
* @param tableName Name of the table
|
71
|
+
* @returns Array of column names
|
72
|
+
*/
|
73
|
+
getTableColumns(tableName: string): string[];
|
74
|
+
/**
|
75
|
+
* Create TableColumnResolver function for SqlParamInjector
|
76
|
+
* @returns Function compatible with SqlParamInjector
|
77
|
+
*/
|
78
|
+
createTableColumnResolver(): (tableName: string) => string[];
|
79
|
+
/**
|
80
|
+
* Generate JSON mapping configuration for PostgresJsonQueryBuilder
|
81
|
+
* @param rootTableName Root table for the JSON structure
|
82
|
+
* @returns JSON mapping configuration
|
83
|
+
*/
|
84
|
+
createJsonMapping(rootTableName: string): JsonMapping;
|
85
|
+
/**
|
86
|
+
* Get all table names in the schema
|
87
|
+
* @returns Array of table names
|
88
|
+
*/
|
89
|
+
getTableNames(): string[];
|
90
|
+
/**
|
91
|
+
* Get table definition by name
|
92
|
+
* @param tableName Name of the table
|
93
|
+
* @returns Table definition or undefined
|
94
|
+
*/
|
95
|
+
getTable(tableName: string): TableDefinition | undefined;
|
96
|
+
/**
|
97
|
+
* Get primary key column name for a table
|
98
|
+
* Used by QueryBuilder.buildUpdateQuery for WHERE clause conditions
|
99
|
+
* @param tableName Name of the table
|
100
|
+
* @returns Primary key column name or undefined
|
101
|
+
*/
|
102
|
+
getPrimaryKey(tableName: string): string | undefined;
|
103
|
+
/**
|
104
|
+
* Get foreign key relationships for a table
|
105
|
+
* @param tableName Name of the table
|
106
|
+
* @returns Array of foreign key relationships
|
107
|
+
*/
|
108
|
+
getForeignKeys(tableName: string): Array<{
|
109
|
+
column: string;
|
110
|
+
referencedTable: string;
|
111
|
+
referencedColumn: string;
|
112
|
+
}>;
|
113
|
+
}
|
114
|
+
/**
|
115
|
+
* Create a SchemaManager instance from schema definitions
|
116
|
+
* @param schemas Schema registry object
|
117
|
+
* @returns SchemaManager instance
|
118
|
+
*/
|
119
|
+
export declare function createSchemaManager(schemas: SchemaRegistry): SchemaManager;
|
120
|
+
/**
|
121
|
+
* Create TableColumnResolver function from schema definitions
|
122
|
+
* @param schemas Schema registry object
|
123
|
+
* @returns TableColumnResolver function for SqlParamInjector
|
124
|
+
*/
|
125
|
+
export declare function createTableColumnResolver(schemas: SchemaRegistry): (tableName: string) => string[];
|
126
|
+
/**
|
127
|
+
* Create JSON mapping from schema definitions
|
128
|
+
* @param schemas Schema registry object
|
129
|
+
* @param rootTableName Root table name
|
130
|
+
* @returns JSON mapping for PostgresJsonQueryBuilder
|
131
|
+
*/
|
132
|
+
export declare function createJsonMappingFromSchema(schemas: SchemaRegistry, rootTableName: string): JsonMapping;
|
@@ -0,0 +1,194 @@
|
|
1
|
+
/**
|
2
|
+
* Schema Manager for rawsql-ts
|
3
|
+
* Provides unified schema definition and automatic conversion to various formats
|
4
|
+
* Eliminates code duplication and provides type-safe schema management
|
5
|
+
*/
|
6
|
+
// === Schema Manager Class ===
|
7
|
+
/**
|
8
|
+
* Central schema management utility for rawsql-ts
|
9
|
+
* Converts user-defined schemas to various internal formats
|
10
|
+
*/
|
11
|
+
export class SchemaManager {
|
12
|
+
constructor(schemas) {
|
13
|
+
this.schemas = schemas;
|
14
|
+
this.validateSchemas();
|
15
|
+
}
|
16
|
+
/**
|
17
|
+
* Validate schema definitions for consistency
|
18
|
+
* Ensures each table has a primary key (required for UPDATE/DELETE operations)
|
19
|
+
* and validates relationship references
|
20
|
+
*/
|
21
|
+
validateSchemas() {
|
22
|
+
const tableNames = Object.keys(this.schemas);
|
23
|
+
const errors = [];
|
24
|
+
// Validate each table
|
25
|
+
Object.entries(this.schemas).forEach(([tableName, table]) => {
|
26
|
+
var _a;
|
27
|
+
// Check primary key exists (required for UPDATE/DELETE WHERE conditions)
|
28
|
+
const primaryKeys = Object.entries(table.columns)
|
29
|
+
.filter(([_, col]) => col.isPrimaryKey)
|
30
|
+
.map(([name, _]) => name);
|
31
|
+
if (primaryKeys.length === 0) {
|
32
|
+
errors.push(`Table '${tableName}' has no primary key defined`);
|
33
|
+
}
|
34
|
+
// Validate foreign key references
|
35
|
+
(_a = table.relationships) === null || _a === void 0 ? void 0 : _a.forEach(rel => {
|
36
|
+
if (!tableNames.includes(rel.table)) {
|
37
|
+
errors.push(`Table '${tableName}' references unknown table '${rel.table}' in relationship`);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
});
|
41
|
+
if (errors.length > 0) {
|
42
|
+
throw new Error(`Schema validation failed:\\n${errors.join('\\n')}`);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* Get table column names for SqlParamInjector TableColumnResolver
|
47
|
+
* @param tableName Name of the table
|
48
|
+
* @returns Array of column names
|
49
|
+
*/
|
50
|
+
getTableColumns(tableName) {
|
51
|
+
const table = this.schemas[tableName];
|
52
|
+
if (!table) {
|
53
|
+
return [];
|
54
|
+
}
|
55
|
+
return Object.keys(table.columns);
|
56
|
+
}
|
57
|
+
/**
|
58
|
+
* Create TableColumnResolver function for SqlParamInjector
|
59
|
+
* @returns Function compatible with SqlParamInjector
|
60
|
+
*/
|
61
|
+
createTableColumnResolver() {
|
62
|
+
return (tableName) => this.getTableColumns(tableName);
|
63
|
+
}
|
64
|
+
/**
|
65
|
+
* Generate JSON mapping configuration for PostgresJsonQueryBuilder
|
66
|
+
* @param rootTableName Root table for the JSON structure
|
67
|
+
* @returns JSON mapping configuration
|
68
|
+
*/
|
69
|
+
createJsonMapping(rootTableName) {
|
70
|
+
var _a;
|
71
|
+
const rootTable = this.schemas[rootTableName];
|
72
|
+
if (!rootTable) {
|
73
|
+
throw new Error(`Table '${rootTableName}' not found in schema registry`);
|
74
|
+
}
|
75
|
+
// Build root entity columns mapping
|
76
|
+
const rootColumns = {};
|
77
|
+
Object.entries(rootTable.columns).forEach(([columnName, column]) => {
|
78
|
+
rootColumns[columnName] = column.jsonAlias || column.name;
|
79
|
+
});
|
80
|
+
// Build nested entities from relationships
|
81
|
+
const nestedEntities = [];
|
82
|
+
(_a = rootTable.relationships) === null || _a === void 0 ? void 0 : _a.forEach(rel => {
|
83
|
+
const relatedTable = this.schemas[rel.table];
|
84
|
+
if (!relatedTable) {
|
85
|
+
throw new Error(`Related table '${rel.table}' not found in schema registry`);
|
86
|
+
}
|
87
|
+
// Build columns mapping for related table
|
88
|
+
const relatedColumns = {};
|
89
|
+
Object.entries(relatedTable.columns).forEach(([columnName, column]) => {
|
90
|
+
relatedColumns[columnName] = column.jsonAlias || column.name;
|
91
|
+
});
|
92
|
+
// Determine relationship type for JSON builder
|
93
|
+
const relationshipType = rel.type;
|
94
|
+
nestedEntities.push({
|
95
|
+
id: rel.propertyName,
|
96
|
+
name: relatedTable.displayName || rel.table,
|
97
|
+
parentId: rootTableName,
|
98
|
+
propertyName: rel.propertyName,
|
99
|
+
relationshipType: relationshipType,
|
100
|
+
columns: relatedColumns
|
101
|
+
});
|
102
|
+
});
|
103
|
+
return {
|
104
|
+
rootName: rootTableName,
|
105
|
+
rootEntity: {
|
106
|
+
id: rootTableName,
|
107
|
+
name: rootTable.displayName || rootTableName,
|
108
|
+
columns: rootColumns
|
109
|
+
},
|
110
|
+
nestedEntities,
|
111
|
+
useJsonb: true,
|
112
|
+
resultFormat: "single"
|
113
|
+
};
|
114
|
+
}
|
115
|
+
/**
|
116
|
+
* Get all table names in the schema
|
117
|
+
* @returns Array of table names
|
118
|
+
*/
|
119
|
+
getTableNames() {
|
120
|
+
return Object.keys(this.schemas);
|
121
|
+
}
|
122
|
+
/**
|
123
|
+
* Get table definition by name
|
124
|
+
* @param tableName Name of the table
|
125
|
+
* @returns Table definition or undefined
|
126
|
+
*/
|
127
|
+
getTable(tableName) {
|
128
|
+
return this.schemas[tableName];
|
129
|
+
}
|
130
|
+
/**
|
131
|
+
* Get primary key column name for a table
|
132
|
+
* Used by QueryBuilder.buildUpdateQuery for WHERE clause conditions
|
133
|
+
* @param tableName Name of the table
|
134
|
+
* @returns Primary key column name or undefined
|
135
|
+
*/
|
136
|
+
getPrimaryKey(tableName) {
|
137
|
+
const table = this.schemas[tableName];
|
138
|
+
if (!table)
|
139
|
+
return undefined;
|
140
|
+
const primaryKeyEntry = Object.entries(table.columns)
|
141
|
+
.find(([_, col]) => col.isPrimaryKey);
|
142
|
+
return primaryKeyEntry ? primaryKeyEntry[0] : undefined;
|
143
|
+
}
|
144
|
+
/**
|
145
|
+
* Get foreign key relationships for a table
|
146
|
+
* @param tableName Name of the table
|
147
|
+
* @returns Array of foreign key relationships
|
148
|
+
*/
|
149
|
+
getForeignKeys(tableName) {
|
150
|
+
const table = this.schemas[tableName];
|
151
|
+
if (!table)
|
152
|
+
return [];
|
153
|
+
const foreignKeys = [];
|
154
|
+
Object.entries(table.columns).forEach(([columnName, column]) => {
|
155
|
+
if (column.foreignKey) {
|
156
|
+
foreignKeys.push({
|
157
|
+
column: columnName,
|
158
|
+
referencedTable: column.foreignKey.table,
|
159
|
+
referencedColumn: column.foreignKey.column
|
160
|
+
});
|
161
|
+
}
|
162
|
+
});
|
163
|
+
return foreignKeys;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
// === Convenience Functions ===
|
167
|
+
/**
|
168
|
+
* Create a SchemaManager instance from schema definitions
|
169
|
+
* @param schemas Schema registry object
|
170
|
+
* @returns SchemaManager instance
|
171
|
+
*/
|
172
|
+
export function createSchemaManager(schemas) {
|
173
|
+
return new SchemaManager(schemas);
|
174
|
+
}
|
175
|
+
/**
|
176
|
+
* Create TableColumnResolver function from schema definitions
|
177
|
+
* @param schemas Schema registry object
|
178
|
+
* @returns TableColumnResolver function for SqlParamInjector
|
179
|
+
*/
|
180
|
+
export function createTableColumnResolver(schemas) {
|
181
|
+
const manager = new SchemaManager(schemas);
|
182
|
+
return manager.createTableColumnResolver();
|
183
|
+
}
|
184
|
+
/**
|
185
|
+
* Create JSON mapping from schema definitions
|
186
|
+
* @param schemas Schema registry object
|
187
|
+
* @param rootTableName Root table name
|
188
|
+
* @returns JSON mapping for PostgresJsonQueryBuilder
|
189
|
+
*/
|
190
|
+
export function createJsonMappingFromSchema(schemas, rootTableName) {
|
191
|
+
const manager = new SchemaManager(schemas);
|
192
|
+
return manager.createJsonMapping(rootTableName);
|
193
|
+
}
|
194
|
+
//# sourceMappingURL=SchemaManager.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SchemaManager.js","sourceRoot":"","sources":["../../../src/utils/SchemaManager.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
@@ -8,6 +8,7 @@ export * from './transformers/CTECollector';
|
|
8
8
|
export * from './transformers/CTENormalizer';
|
9
9
|
export * from './transformers/Formatter';
|
10
10
|
export * from './transformers/SqlFormatter';
|
11
|
+
export * from './transformers/PostgresJsonQueryBuilder';
|
11
12
|
export * from './transformers/QueryBuilder';
|
12
13
|
export * from './transformers/SelectValueCollector';
|
13
14
|
export * from './transformers/SelectableColumnCollector';
|
@@ -17,3 +18,4 @@ export * from './transformers/UpstreamSelectQueryFinder';
|
|
17
18
|
export * from './transformers/SchemaCollector';
|
18
19
|
export * from './transformers/SqlParamInjector';
|
19
20
|
export * from './utils/SqlSchemaValidator';
|
21
|
+
export * from './utils/SchemaManager';
|