rawsql-ts 0.10.9-beta → 0.11.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 +175 -47
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +16 -14
- package/dist/esm/index.min.js.map +4 -4
- package/dist/esm/src/index.js +6 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/tokenReaders/OperatorTokenReader.js +4 -0
- package/dist/esm/src/tokenReaders/OperatorTokenReader.js.map +1 -1
- package/dist/esm/src/transformers/CTEDependencyTracer.js +249 -0
- package/dist/esm/src/transformers/CTEDependencyTracer.js.map +1 -0
- package/dist/esm/src/transformers/DynamicQueryBuilder.js +155 -0
- package/dist/esm/src/transformers/DynamicQueryBuilder.js.map +1 -0
- package/dist/esm/src/transformers/JsonMappingUnifier.js +217 -0
- package/dist/esm/src/transformers/JsonMappingUnifier.js.map +1 -0
- package/dist/esm/src/transformers/ModelDrivenJsonMapping.js +103 -0
- package/dist/esm/src/transformers/ModelDrivenJsonMapping.js.map +1 -0
- package/dist/esm/src/transformers/PostgresArrayEntityCteBuilder.js +204 -16
- package/dist/esm/src/transformers/PostgresArrayEntityCteBuilder.js.map +1 -1
- package/dist/esm/src/transformers/PostgresJsonQueryBuilder.js +26 -21
- package/dist/esm/src/transformers/PostgresJsonQueryBuilder.js.map +1 -1
- package/dist/esm/src/transformers/PostgresObjectEntityCteBuilder.js +8 -5
- package/dist/esm/src/transformers/PostgresObjectEntityCteBuilder.js.map +1 -1
- package/dist/esm/src/transformers/SelectableColumnCollector.js +17 -5
- package/dist/esm/src/transformers/SelectableColumnCollector.js.map +1 -1
- package/dist/esm/src/transformers/SqlFormatter.js +1 -2
- package/dist/esm/src/transformers/SqlFormatter.js.map +1 -1
- package/dist/esm/src/transformers/TypeTransformationPostProcessor.js +342 -0
- package/dist/esm/src/transformers/TypeTransformationPostProcessor.js.map +1 -0
- package/dist/esm/src/transformers/UnifiedJsonMapping.js +57 -0
- package/dist/esm/src/transformers/UnifiedJsonMapping.js.map +1 -0
- package/dist/esm/src/transformers/UpstreamSelectQueryFinder.js +8 -1
- package/dist/esm/src/transformers/UpstreamSelectQueryFinder.js.map +1 -1
- package/dist/esm/src/utils/JsonSchemaValidator.js +211 -0
- package/dist/esm/src/utils/JsonSchemaValidator.js.map +1 -0
- package/dist/esm/src/utils/OperatorPrecedence.js +3 -1
- package/dist/esm/src/utils/OperatorPrecedence.js.map +1 -1
- package/dist/esm/src/utils/SchemaManager.js +0 -1
- package/dist/esm/src/utils/SchemaManager.js.map +1 -1
- package/dist/esm/tsconfig.browser.tsbuildinfo +1 -1
- package/dist/esm/types/src/index.d.ts +6 -0
- package/dist/esm/types/src/transformers/CTEDependencyTracer.d.ts +58 -0
- package/dist/esm/types/src/transformers/DynamicQueryBuilder.d.ts +108 -0
- package/dist/esm/types/src/transformers/JsonMappingUnifier.d.ts +95 -0
- package/dist/esm/types/src/transformers/ModelDrivenJsonMapping.d.ts +62 -0
- package/dist/esm/types/src/transformers/PostgresArrayEntityCteBuilder.d.ts +80 -1
- package/dist/esm/types/src/transformers/PostgresJsonQueryBuilder.d.ts +3 -2
- package/dist/esm/types/src/transformers/SelectableColumnCollector.d.ts +14 -3
- package/dist/esm/types/src/transformers/SqlFormatter.d.ts +2 -3
- package/dist/esm/types/src/transformers/TypeTransformationPostProcessor.d.ts +108 -0
- package/dist/esm/types/src/transformers/UnifiedJsonMapping.d.ts +53 -0
- package/dist/esm/types/src/transformers/UpstreamSelectQueryFinder.d.ts +5 -1
- package/dist/esm/types/src/utils/JsonSchemaValidator.d.ts +81 -0
- package/dist/index.min.js +16 -14
- package/dist/index.min.js.map +4 -4
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +14 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/tokenReaders/OperatorTokenReader.js +4 -0
- package/dist/src/tokenReaders/OperatorTokenReader.js.map +1 -1
- package/dist/src/transformers/CTEDependencyTracer.d.ts +58 -0
- package/dist/src/transformers/CTEDependencyTracer.js +253 -0
- package/dist/src/transformers/CTEDependencyTracer.js.map +1 -0
- package/dist/src/transformers/DynamicQueryBuilder.d.ts +108 -0
- package/dist/src/transformers/DynamicQueryBuilder.js +159 -0
- package/dist/src/transformers/DynamicQueryBuilder.js.map +1 -0
- package/dist/src/transformers/JsonMappingUnifier.d.ts +95 -0
- package/dist/src/transformers/JsonMappingUnifier.js +226 -0
- package/dist/src/transformers/JsonMappingUnifier.js.map +1 -0
- package/dist/src/transformers/ModelDrivenJsonMapping.d.ts +62 -0
- package/dist/src/transformers/ModelDrivenJsonMapping.js +110 -0
- package/dist/src/transformers/ModelDrivenJsonMapping.js.map +1 -0
- package/dist/src/transformers/PostgresArrayEntityCteBuilder.d.ts +80 -1
- package/dist/src/transformers/PostgresArrayEntityCteBuilder.js +204 -16
- package/dist/src/transformers/PostgresArrayEntityCteBuilder.js.map +1 -1
- package/dist/src/transformers/PostgresJsonQueryBuilder.d.ts +3 -2
- package/dist/src/transformers/PostgresJsonQueryBuilder.js +26 -21
- package/dist/src/transformers/PostgresJsonQueryBuilder.js.map +1 -1
- package/dist/src/transformers/PostgresObjectEntityCteBuilder.js +8 -5
- package/dist/src/transformers/PostgresObjectEntityCteBuilder.js.map +1 -1
- package/dist/src/transformers/SelectableColumnCollector.d.ts +14 -3
- package/dist/src/transformers/SelectableColumnCollector.js +17 -5
- package/dist/src/transformers/SelectableColumnCollector.js.map +1 -1
- package/dist/src/transformers/SqlFormatter.d.ts +2 -3
- package/dist/src/transformers/SqlFormatter.js +1 -2
- package/dist/src/transformers/SqlFormatter.js.map +1 -1
- package/dist/src/transformers/TypeTransformationPostProcessor.d.ts +108 -0
- package/dist/src/transformers/TypeTransformationPostProcessor.js +351 -0
- package/dist/src/transformers/TypeTransformationPostProcessor.js.map +1 -0
- package/dist/src/transformers/UnifiedJsonMapping.d.ts +53 -0
- package/dist/src/transformers/UnifiedJsonMapping.js +60 -0
- package/dist/src/transformers/UnifiedJsonMapping.js.map +1 -0
- package/dist/src/transformers/UpstreamSelectQueryFinder.d.ts +5 -1
- package/dist/src/transformers/UpstreamSelectQueryFinder.js +8 -1
- package/dist/src/transformers/UpstreamSelectQueryFinder.js.map +1 -1
- package/dist/src/utils/JsonSchemaValidator.d.ts +81 -0
- package/dist/src/utils/JsonSchemaValidator.js +215 -0
- package/dist/src/utils/JsonSchemaValidator.js.map +1 -0
- package/dist/src/utils/OperatorPrecedence.js +3 -1
- package/dist/src/utils/OperatorPrecedence.js.map +1 -1
- package/dist/src/utils/SchemaManager.js +0 -1
- package/dist/src/utils/SchemaManager.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -5
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DynamicQueryBuilder = void 0;
|
|
4
|
+
const SelectQueryParser_1 = require("../parsers/SelectQueryParser");
|
|
5
|
+
const SqlParamInjector_1 = require("./SqlParamInjector");
|
|
6
|
+
const SqlSortInjector_1 = require("./SqlSortInjector");
|
|
7
|
+
const SqlPaginationInjector_1 = require("./SqlPaginationInjector");
|
|
8
|
+
const PostgresJsonQueryBuilder_1 = require("./PostgresJsonQueryBuilder");
|
|
9
|
+
const QueryBuilder_1 = require("./QueryBuilder");
|
|
10
|
+
/**
|
|
11
|
+
* DynamicQueryBuilder provides pure JavaScript SQL query building capabilities.
|
|
12
|
+
* It combines SQL parsing with dynamic condition injection (filtering, sorting, pagination, serialization).
|
|
13
|
+
*
|
|
14
|
+
* This class is framework-agnostic and does not perform any file I/O operations.
|
|
15
|
+
* It only works with SQL content provided as strings.
|
|
16
|
+
*
|
|
17
|
+
* Key features:
|
|
18
|
+
* - Pure JavaScript/TypeScript - no file system dependencies
|
|
19
|
+
* - Framework-agnostic - can be used with any database framework
|
|
20
|
+
* - Composable - combines multiple injectors in the correct order
|
|
21
|
+
* - Type-safe - provides TypeScript types for all options
|
|
22
|
+
* - Testable - easy to unit test without mocking file system
|
|
23
|
+
*/
|
|
24
|
+
class DynamicQueryBuilder {
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new DynamicQueryBuilder instance
|
|
27
|
+
* @param tableColumnResolver Optional function to resolve table columns for wildcard queries
|
|
28
|
+
*/
|
|
29
|
+
constructor(tableColumnResolver) {
|
|
30
|
+
this.tableColumnResolver = tableColumnResolver;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Builds a SelectQuery from SQL content with dynamic conditions.
|
|
34
|
+
* This is a pure function that does not perform any I/O operations.
|
|
35
|
+
* * @param sqlContent Raw SQL string to parse and modify
|
|
36
|
+
* @param options Dynamic conditions to apply (filter, sort, paging, serialize)
|
|
37
|
+
* @returns Modified SelectQuery with all dynamic conditions applied
|
|
38
|
+
* * @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const builder = new DynamicQueryBuilder();
|
|
41
|
+
* const query = builder.buildQuery(
|
|
42
|
+
* 'SELECT id, name FROM users WHERE active = true',
|
|
43
|
+
* {
|
|
44
|
+
* filter: { status: 'premium' },
|
|
45
|
+
* sort: { created_at: { desc: true } },
|
|
46
|
+
* paging: { page: 2, pageSize: 10 },
|
|
47
|
+
* serialize: { rootName: 'user', rootEntity: { id: 'user', name: 'User', columns: { id: 'id', name: 'name' } }, nestedEntities: [] }
|
|
48
|
+
* }
|
|
49
|
+
* );
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
buildQuery(sqlContent, options = {}) {
|
|
53
|
+
// Parse the base SQL
|
|
54
|
+
let parsedQuery;
|
|
55
|
+
try {
|
|
56
|
+
parsedQuery = SelectQueryParser_1.SelectQueryParser.parse(sqlContent);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw new Error(`Failed to parse SQL: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
60
|
+
}
|
|
61
|
+
// Apply dynamic modifications in the correct order
|
|
62
|
+
let modifiedQuery = parsedQuery;
|
|
63
|
+
// 1. Apply filtering first (most selective, should reduce data early)
|
|
64
|
+
if (options.filter && Object.keys(options.filter).length > 0) {
|
|
65
|
+
const paramInjector = new SqlParamInjector_1.SqlParamInjector(this.tableColumnResolver);
|
|
66
|
+
// Ensure we have a SimpleSelectQuery for the injector
|
|
67
|
+
const simpleQuery = QueryBuilder_1.QueryBuilder.buildSimpleQuery(modifiedQuery);
|
|
68
|
+
modifiedQuery = paramInjector.inject(simpleQuery, options.filter);
|
|
69
|
+
}
|
|
70
|
+
// 2. Apply sorting second (after filtering to sort smaller dataset)
|
|
71
|
+
if (options.sort && Object.keys(options.sort).length > 0) {
|
|
72
|
+
const sortInjector = new SqlSortInjector_1.SqlSortInjector(this.tableColumnResolver);
|
|
73
|
+
// Ensure we have a SimpleSelectQuery for the injector
|
|
74
|
+
const simpleQuery = QueryBuilder_1.QueryBuilder.buildSimpleQuery(modifiedQuery);
|
|
75
|
+
modifiedQuery = sortInjector.inject(simpleQuery, options.sort);
|
|
76
|
+
} // 3. Apply pagination third (after filtering and sorting)
|
|
77
|
+
if (options.paging) {
|
|
78
|
+
const { page = 1, pageSize } = options.paging;
|
|
79
|
+
if (pageSize !== undefined) {
|
|
80
|
+
const paginationInjector = new SqlPaginationInjector_1.SqlPaginationInjector();
|
|
81
|
+
const paginationOptions = { page, pageSize };
|
|
82
|
+
// Ensure we have a SimpleSelectQuery for the injector
|
|
83
|
+
const simpleQuery = QueryBuilder_1.QueryBuilder.buildSimpleQuery(modifiedQuery);
|
|
84
|
+
modifiedQuery = paginationInjector.inject(simpleQuery, paginationOptions);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// 4. Apply serialization last (transform the final query structure to JSON)
|
|
88
|
+
// Note: boolean values are handled at RawSqlClient level for auto-loading
|
|
89
|
+
if (options.serialize && typeof options.serialize === 'object') {
|
|
90
|
+
const jsonBuilder = new PostgresJsonQueryBuilder_1.PostgresJsonQueryBuilder();
|
|
91
|
+
// Ensure we have a SimpleSelectQuery for the JSON builder
|
|
92
|
+
const simpleQuery = QueryBuilder_1.QueryBuilder.buildSimpleQuery(modifiedQuery);
|
|
93
|
+
modifiedQuery = jsonBuilder.buildJsonQuery(simpleQuery, options.serialize);
|
|
94
|
+
}
|
|
95
|
+
return modifiedQuery;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Builds a SelectQuery with only filtering applied.
|
|
99
|
+
* Convenience method for when you only need dynamic WHERE conditions.
|
|
100
|
+
*
|
|
101
|
+
* @param sqlContent Raw SQL string to parse and modify
|
|
102
|
+
* @param filter Filter conditions to apply
|
|
103
|
+
* @returns Modified SelectQuery with filter conditions applied
|
|
104
|
+
*/
|
|
105
|
+
buildFilteredQuery(sqlContent, filter) {
|
|
106
|
+
return this.buildQuery(sqlContent, { filter });
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Builds a SelectQuery with only sorting applied.
|
|
110
|
+
* Convenience method for when you only need dynamic ORDER BY clauses.
|
|
111
|
+
*
|
|
112
|
+
* @param sqlContent Raw SQL string to parse and modify
|
|
113
|
+
* @param sort Sort conditions to apply
|
|
114
|
+
* @returns Modified SelectQuery with sort conditions applied
|
|
115
|
+
*/
|
|
116
|
+
buildSortedQuery(sqlContent, sort) {
|
|
117
|
+
return this.buildQuery(sqlContent, { sort });
|
|
118
|
+
} /**
|
|
119
|
+
* Builds a SelectQuery with only pagination applied.
|
|
120
|
+
* Convenience method for when you only need LIMIT/OFFSET clauses.
|
|
121
|
+
*
|
|
122
|
+
* @param sqlContent Raw SQL string to parse and modify
|
|
123
|
+
* @param paging Pagination options to apply
|
|
124
|
+
* @returns Modified SelectQuery with pagination applied
|
|
125
|
+
*/
|
|
126
|
+
buildPaginatedQuery(sqlContent, paging) {
|
|
127
|
+
return this.buildQuery(sqlContent, { paging });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Builds a SelectQuery with only JSON serialization applied.
|
|
131
|
+
* Convenience method for when you only need hierarchical JSON transformation.
|
|
132
|
+
*
|
|
133
|
+
* @param sqlContent Raw SQL string to parse and modify
|
|
134
|
+
* @param serialize JSON mapping configuration to apply
|
|
135
|
+
* @returns Modified SelectQuery with JSON serialization applied
|
|
136
|
+
*/
|
|
137
|
+
buildSerializedQuery(sqlContent, serialize) {
|
|
138
|
+
return this.buildQuery(sqlContent, { serialize });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Validates SQL content by attempting to parse it.
|
|
142
|
+
* Useful for testing SQL validity without applying any modifications.
|
|
143
|
+
*
|
|
144
|
+
* @param sqlContent Raw SQL string to validate
|
|
145
|
+
* @returns true if SQL is valid, throws error if invalid
|
|
146
|
+
* @throws Error if SQL cannot be parsed
|
|
147
|
+
*/
|
|
148
|
+
validateSql(sqlContent) {
|
|
149
|
+
try {
|
|
150
|
+
SelectQueryParser_1.SelectQueryParser.parse(sqlContent);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
throw new Error(`Invalid SQL: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.DynamicQueryBuilder = DynamicQueryBuilder;
|
|
159
|
+
//# sourceMappingURL=DynamicQueryBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicQueryBuilder.js","sourceRoot":"","sources":["../../../src/transformers/DynamicQueryBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified JSON Mapping processor that supports both legacy and model-driven formats.
|
|
3
|
+
*
|
|
4
|
+
* This module provides backward compatibility while encouraging migration to the model-driven format.
|
|
5
|
+
* It automatically detects the input format and normalizes to a consistent internal representation.
|
|
6
|
+
*/
|
|
7
|
+
import { JsonMapping } from './PostgresJsonQueryBuilder';
|
|
8
|
+
import { ModelDrivenJsonMapping } from './ModelDrivenJsonMapping';
|
|
9
|
+
/**
|
|
10
|
+
* Unified mapping format that can handle both legacy and model-driven inputs.
|
|
11
|
+
*/
|
|
12
|
+
export interface UnifiedMappingInput {
|
|
13
|
+
typeInfo?: {
|
|
14
|
+
interface: string;
|
|
15
|
+
importPath: string;
|
|
16
|
+
};
|
|
17
|
+
structure?: any;
|
|
18
|
+
protectedStringFields?: string[];
|
|
19
|
+
rootName?: string;
|
|
20
|
+
rootEntity?: any;
|
|
21
|
+
nestedEntities?: any[];
|
|
22
|
+
columns?: any;
|
|
23
|
+
relationships?: any;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Result of mapping format detection and conversion.
|
|
27
|
+
*/
|
|
28
|
+
export interface MappingProcessResult {
|
|
29
|
+
format: 'model-driven' | 'unified' | 'legacy';
|
|
30
|
+
jsonMapping: JsonMapping;
|
|
31
|
+
originalInput: UnifiedMappingInput;
|
|
32
|
+
metadata?: {
|
|
33
|
+
typeInfo?: {
|
|
34
|
+
interface: string;
|
|
35
|
+
importPath: string;
|
|
36
|
+
};
|
|
37
|
+
protectedStringFields?: string[];
|
|
38
|
+
typeProtection?: any;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detects the format of a JSON mapping configuration.
|
|
43
|
+
*
|
|
44
|
+
* @param input - The mapping configuration to analyze
|
|
45
|
+
* @returns The detected format type
|
|
46
|
+
*/
|
|
47
|
+
export declare function detectMappingFormat(input: UnifiedMappingInput): 'model-driven' | 'unified' | 'legacy';
|
|
48
|
+
/**
|
|
49
|
+
* Main processor that unifies all JSON mapping formats into a consistent JsonMapping.
|
|
50
|
+
*
|
|
51
|
+
* Features:
|
|
52
|
+
* - Automatic format detection
|
|
53
|
+
* - Backward compatibility with all existing formats
|
|
54
|
+
* - Metadata preservation for advanced features
|
|
55
|
+
* - Zero external dependencies
|
|
56
|
+
*
|
|
57
|
+
* @param input - Any supported JSON mapping format
|
|
58
|
+
* @returns Unified processing result with JsonMapping and metadata
|
|
59
|
+
*/
|
|
60
|
+
export declare function processJsonMapping(input: UnifiedMappingInput): MappingProcessResult;
|
|
61
|
+
/**
|
|
62
|
+
* Convenience function for direct JsonMapping extraction.
|
|
63
|
+
*
|
|
64
|
+
* @param input - Any supported JSON mapping format
|
|
65
|
+
* @returns JsonMapping ready for use with PostgresJsonQueryBuilder
|
|
66
|
+
*/
|
|
67
|
+
export declare function unifyJsonMapping(input: UnifiedMappingInput): JsonMapping;
|
|
68
|
+
/**
|
|
69
|
+
* Type guard to check if input uses model-driven format.
|
|
70
|
+
*
|
|
71
|
+
* @param input - Mapping input to check
|
|
72
|
+
* @returns True if input is model-driven format
|
|
73
|
+
*/
|
|
74
|
+
export declare function isModelDrivenFormat(input: UnifiedMappingInput): input is ModelDrivenJsonMapping;
|
|
75
|
+
/**
|
|
76
|
+
* Type guard to check if input uses unified format.
|
|
77
|
+
*
|
|
78
|
+
* @param input - Mapping input to check
|
|
79
|
+
* @returns True if input is unified format
|
|
80
|
+
*/
|
|
81
|
+
export declare function isUnifiedFormat(input: UnifiedMappingInput): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Type guard to check if input uses legacy format.
|
|
84
|
+
*
|
|
85
|
+
* @param input - Mapping input to check
|
|
86
|
+
* @returns True if input is legacy format
|
|
87
|
+
*/
|
|
88
|
+
export declare function isLegacyFormat(input: UnifiedMappingInput): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Migration helper that suggests upgrading to model-driven format.
|
|
91
|
+
*
|
|
92
|
+
* @param input - Current mapping configuration
|
|
93
|
+
* @returns Suggestions for migration (if applicable)
|
|
94
|
+
*/
|
|
95
|
+
export declare function suggestModelDrivenMigration(input: UnifiedMappingInput): string[];
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Unified JSON Mapping processor that supports both legacy and model-driven formats.
|
|
4
|
+
*
|
|
5
|
+
* This module provides backward compatibility while encouraging migration to the model-driven format.
|
|
6
|
+
* It automatically detects the input format and normalizes to a consistent internal representation.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.detectMappingFormat = detectMappingFormat;
|
|
10
|
+
exports.processJsonMapping = processJsonMapping;
|
|
11
|
+
exports.unifyJsonMapping = unifyJsonMapping;
|
|
12
|
+
exports.isModelDrivenFormat = isModelDrivenFormat;
|
|
13
|
+
exports.isUnifiedFormat = isUnifiedFormat;
|
|
14
|
+
exports.isLegacyFormat = isLegacyFormat;
|
|
15
|
+
exports.suggestModelDrivenMigration = suggestModelDrivenMigration;
|
|
16
|
+
const ModelDrivenJsonMapping_1 = require("./ModelDrivenJsonMapping");
|
|
17
|
+
/**
|
|
18
|
+
* Detects the format of a JSON mapping configuration.
|
|
19
|
+
*
|
|
20
|
+
* @param input - The mapping configuration to analyze
|
|
21
|
+
* @returns The detected format type
|
|
22
|
+
*/
|
|
23
|
+
function detectMappingFormat(input) {
|
|
24
|
+
// Model-driven format: has typeInfo and structure
|
|
25
|
+
if (input.typeInfo && input.structure) {
|
|
26
|
+
return 'model-driven';
|
|
27
|
+
}
|
|
28
|
+
// Unified format: has rootName and rootEntity
|
|
29
|
+
if (input.rootName && input.rootEntity) {
|
|
30
|
+
return 'unified';
|
|
31
|
+
}
|
|
32
|
+
// Legacy format: direct JsonMapping structure
|
|
33
|
+
if (input.columns || input.relationships) {
|
|
34
|
+
return 'legacy';
|
|
35
|
+
}
|
|
36
|
+
// Default fallback
|
|
37
|
+
return 'legacy';
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Converts legacy unified format to JsonMapping.
|
|
41
|
+
*
|
|
42
|
+
* @param input - Unified format mapping configuration
|
|
43
|
+
* @returns Converted JsonMapping
|
|
44
|
+
*/
|
|
45
|
+
function convertUnifiedFormat(input) {
|
|
46
|
+
if (!input.rootEntity) {
|
|
47
|
+
throw new Error('Unified format requires rootEntity');
|
|
48
|
+
}
|
|
49
|
+
const result = {
|
|
50
|
+
rootName: input.rootName || 'root',
|
|
51
|
+
rootEntity: {
|
|
52
|
+
id: input.rootEntity.id || 'root',
|
|
53
|
+
name: input.rootEntity.name || 'Root',
|
|
54
|
+
columns: input.rootEntity.columns || {}
|
|
55
|
+
},
|
|
56
|
+
nestedEntities: []
|
|
57
|
+
};
|
|
58
|
+
// Convert nestedEntities
|
|
59
|
+
if (input.nestedEntities && Array.isArray(input.nestedEntities)) {
|
|
60
|
+
result.nestedEntities = input.nestedEntities.map(entity => ({
|
|
61
|
+
id: entity.id || entity.propertyName || 'nested',
|
|
62
|
+
name: entity.name || entity.propertyName || 'Nested',
|
|
63
|
+
parentId: entity.parentId || result.rootEntity.id,
|
|
64
|
+
propertyName: entity.propertyName || 'nested',
|
|
65
|
+
relationshipType: entity.relationshipType || 'object',
|
|
66
|
+
columns: entity.columns || {}
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Converts legacy format directly to JsonMapping.
|
|
73
|
+
*
|
|
74
|
+
* @param input - Legacy format mapping configuration
|
|
75
|
+
* @returns JsonMapping
|
|
76
|
+
*/
|
|
77
|
+
function convertLegacyFormat(input) {
|
|
78
|
+
const result = {
|
|
79
|
+
rootName: input.rootName || 'root',
|
|
80
|
+
rootEntity: {
|
|
81
|
+
id: 'root',
|
|
82
|
+
name: input.rootName || 'Root',
|
|
83
|
+
columns: input.columns || {}
|
|
84
|
+
},
|
|
85
|
+
nestedEntities: []
|
|
86
|
+
};
|
|
87
|
+
// Convert relationships to nestedEntities
|
|
88
|
+
if (input.relationships && typeof input.relationships === 'object') {
|
|
89
|
+
for (const [propertyName, relationship] of Object.entries(input.relationships)) {
|
|
90
|
+
// Type assertion for legacy relationship format
|
|
91
|
+
const rel = relationship;
|
|
92
|
+
result.nestedEntities.push({
|
|
93
|
+
id: propertyName,
|
|
94
|
+
name: propertyName.charAt(0).toUpperCase() + propertyName.slice(1),
|
|
95
|
+
parentId: 'root',
|
|
96
|
+
propertyName,
|
|
97
|
+
relationshipType: rel.type === 'hasMany' ? 'array' : 'object',
|
|
98
|
+
columns: rel.columns || {}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Main processor that unifies all JSON mapping formats into a consistent JsonMapping.
|
|
106
|
+
*
|
|
107
|
+
* Features:
|
|
108
|
+
* - Automatic format detection
|
|
109
|
+
* - Backward compatibility with all existing formats
|
|
110
|
+
* - Metadata preservation for advanced features
|
|
111
|
+
* - Zero external dependencies
|
|
112
|
+
*
|
|
113
|
+
* @param input - Any supported JSON mapping format
|
|
114
|
+
* @returns Unified processing result with JsonMapping and metadata
|
|
115
|
+
*/
|
|
116
|
+
function processJsonMapping(input) {
|
|
117
|
+
const format = detectMappingFormat(input);
|
|
118
|
+
let jsonMapping;
|
|
119
|
+
let metadata = {};
|
|
120
|
+
try {
|
|
121
|
+
switch (format) {
|
|
122
|
+
case 'model-driven':
|
|
123
|
+
// Validate model-driven input
|
|
124
|
+
if (!input.typeInfo || !input.structure) {
|
|
125
|
+
throw new Error('Model-driven format requires typeInfo and structure fields');
|
|
126
|
+
}
|
|
127
|
+
// Convert model-driven to JsonMapping
|
|
128
|
+
const modelDrivenInput = {
|
|
129
|
+
typeInfo: input.typeInfo,
|
|
130
|
+
structure: input.structure
|
|
131
|
+
};
|
|
132
|
+
const converted = (0, ModelDrivenJsonMapping_1.convertModelDrivenMapping)(modelDrivenInput);
|
|
133
|
+
jsonMapping = converted.jsonMapping;
|
|
134
|
+
// Preserve metadata
|
|
135
|
+
metadata = {
|
|
136
|
+
typeInfo: input.typeInfo,
|
|
137
|
+
typeProtection: converted.typeProtection
|
|
138
|
+
};
|
|
139
|
+
break;
|
|
140
|
+
case 'unified':
|
|
141
|
+
// Validate unified input
|
|
142
|
+
if (!input.rootEntity) {
|
|
143
|
+
throw new Error('Unified format requires rootEntity field');
|
|
144
|
+
}
|
|
145
|
+
jsonMapping = convertUnifiedFormat(input);
|
|
146
|
+
break;
|
|
147
|
+
case 'legacy':
|
|
148
|
+
// Validate legacy input
|
|
149
|
+
if (!input.columns && !input.relationships) {
|
|
150
|
+
throw new Error('Legacy format requires at least columns or relationships field');
|
|
151
|
+
}
|
|
152
|
+
jsonMapping = convertLegacyFormat(input);
|
|
153
|
+
break;
|
|
154
|
+
default:
|
|
155
|
+
throw new Error(`Unsupported mapping format: ${format}`);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
format,
|
|
159
|
+
jsonMapping,
|
|
160
|
+
originalInput: input,
|
|
161
|
+
metadata
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
throw new Error(`Failed to process JSON mapping (format: ${format}): ${error instanceof Error ? error.message : String(error)}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Convenience function for direct JsonMapping extraction.
|
|
170
|
+
*
|
|
171
|
+
* @param input - Any supported JSON mapping format
|
|
172
|
+
* @returns JsonMapping ready for use with PostgresJsonQueryBuilder
|
|
173
|
+
*/
|
|
174
|
+
function unifyJsonMapping(input) {
|
|
175
|
+
return processJsonMapping(input).jsonMapping;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Type guard to check if input uses model-driven format.
|
|
179
|
+
*
|
|
180
|
+
* @param input - Mapping input to check
|
|
181
|
+
* @returns True if input is model-driven format
|
|
182
|
+
*/
|
|
183
|
+
function isModelDrivenFormat(input) {
|
|
184
|
+
return detectMappingFormat(input) === 'model-driven';
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Type guard to check if input uses unified format.
|
|
188
|
+
*
|
|
189
|
+
* @param input - Mapping input to check
|
|
190
|
+
* @returns True if input is unified format
|
|
191
|
+
*/
|
|
192
|
+
function isUnifiedFormat(input) {
|
|
193
|
+
return detectMappingFormat(input) === 'unified';
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Type guard to check if input uses legacy format.
|
|
197
|
+
*
|
|
198
|
+
* @param input - Mapping input to check
|
|
199
|
+
* @returns True if input is legacy format
|
|
200
|
+
*/
|
|
201
|
+
function isLegacyFormat(input) {
|
|
202
|
+
return detectMappingFormat(input) === 'legacy';
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Migration helper that suggests upgrading to model-driven format.
|
|
206
|
+
*
|
|
207
|
+
* @param input - Current mapping configuration
|
|
208
|
+
* @returns Suggestions for migration (if applicable)
|
|
209
|
+
*/
|
|
210
|
+
function suggestModelDrivenMigration(input) {
|
|
211
|
+
const format = detectMappingFormat(input);
|
|
212
|
+
const suggestions = [];
|
|
213
|
+
if (format !== 'model-driven') {
|
|
214
|
+
suggestions.push('Consider migrating to model-driven JSON mapping format');
|
|
215
|
+
suggestions.push('Benefits: Better type safety, IDE support, and future-proof design');
|
|
216
|
+
suggestions.push('See: Model-Driven JSON Mapping Guide for migration instructions');
|
|
217
|
+
if (format === 'unified') {
|
|
218
|
+
suggestions.push('Your current unified format can be automatically converted');
|
|
219
|
+
}
|
|
220
|
+
if (format === 'legacy') {
|
|
221
|
+
suggestions.push('Legacy format support will be maintained but new features target model-driven format');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return suggestions;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=JsonMappingUnifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonMappingUnifier.js","sourceRoot":"","sources":["../../../src/transformers/JsonMappingUnifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model-driven JSON mapping structure that mirrors TypeScript model definitions.
|
|
3
|
+
* This approach provides intuitive, hierarchical mapping that closely resembles the target data structure.
|
|
4
|
+
*/
|
|
5
|
+
import { JsonMapping } from './PostgresJsonQueryBuilder';
|
|
6
|
+
/**
|
|
7
|
+
* Supported field types for database column mapping.
|
|
8
|
+
*/
|
|
9
|
+
export type FieldType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'auto';
|
|
10
|
+
/**
|
|
11
|
+
* Field mapping configuration that can be either a simple column name or enhanced mapping with type control.
|
|
12
|
+
*/
|
|
13
|
+
export type FieldMapping = string | {
|
|
14
|
+
column: string;
|
|
15
|
+
type?: FieldType;
|
|
16
|
+
} | {
|
|
17
|
+
from: string;
|
|
18
|
+
type?: FieldType;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Nested object or array structure definition.
|
|
22
|
+
*/
|
|
23
|
+
export interface NestedStructure {
|
|
24
|
+
type: 'object' | 'array';
|
|
25
|
+
from: string;
|
|
26
|
+
structure: StructureFields;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Structure fields can contain either field mappings or nested structures.
|
|
30
|
+
*/
|
|
31
|
+
export type StructureFields = {
|
|
32
|
+
[key: string]: FieldMapping | NestedStructure;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Model-driven JSON mapping that mirrors TypeScript interface structure.
|
|
36
|
+
* This design makes it easy to understand the relationship between models and database columns.
|
|
37
|
+
*/
|
|
38
|
+
export interface ModelDrivenJsonMapping {
|
|
39
|
+
typeInfo: {
|
|
40
|
+
interface: string;
|
|
41
|
+
importPath: string;
|
|
42
|
+
};
|
|
43
|
+
structure: StructureFields;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Type protection configuration extracted from the model-driven mapping.
|
|
47
|
+
*/
|
|
48
|
+
export interface TypeProtectionConfig {
|
|
49
|
+
protectedStringFields: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Convert a model-driven JSON mapping to the traditional JsonMapping format.
|
|
53
|
+
* This enables backward compatibility with existing PostgresJsonQueryBuilder.
|
|
54
|
+
*/
|
|
55
|
+
export declare function convertModelDrivenMapping(modelMapping: ModelDrivenJsonMapping): {
|
|
56
|
+
jsonMapping: JsonMapping;
|
|
57
|
+
typeProtection: TypeProtectionConfig;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Validate that a model-driven mapping structure is well-formed.
|
|
61
|
+
*/
|
|
62
|
+
export declare function validateModelDrivenMapping(mapping: ModelDrivenJsonMapping): string[];
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Model-driven JSON mapping structure that mirrors TypeScript model definitions.
|
|
4
|
+
* This approach provides intuitive, hierarchical mapping that closely resembles the target data structure.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.convertModelDrivenMapping = convertModelDrivenMapping;
|
|
8
|
+
exports.validateModelDrivenMapping = validateModelDrivenMapping;
|
|
9
|
+
/**
|
|
10
|
+
* Convert a model-driven JSON mapping to the traditional JsonMapping format.
|
|
11
|
+
* This enables backward compatibility with existing PostgresJsonQueryBuilder.
|
|
12
|
+
*/
|
|
13
|
+
function convertModelDrivenMapping(modelMapping) {
|
|
14
|
+
const protectedStringFields = [];
|
|
15
|
+
let entityIdCounter = 0;
|
|
16
|
+
// Generate unique entity IDs
|
|
17
|
+
const generateEntityId = () => `entity_${++entityIdCounter}`;
|
|
18
|
+
// Helper function to process structure fields and extract entities
|
|
19
|
+
const processStructure = (structure, parentId = null) => {
|
|
20
|
+
const columns = {};
|
|
21
|
+
const nestedEntities = [];
|
|
22
|
+
for (const [fieldName, config] of Object.entries(structure)) {
|
|
23
|
+
if (typeof config === 'string') {
|
|
24
|
+
// Simple field mapping: "fieldName": "column_name"
|
|
25
|
+
columns[fieldName] = config;
|
|
26
|
+
}
|
|
27
|
+
else if ('column' in config && typeof config.column === 'string' && !('type' in config && (config.type === 'object' || config.type === 'array'))) {
|
|
28
|
+
// Enhanced field mapping: "fieldName": { "column": "column_name", "type": "string" }
|
|
29
|
+
const fieldConfig = config;
|
|
30
|
+
if (typeof fieldConfig === 'object' && 'column' in fieldConfig) {
|
|
31
|
+
columns[fieldName] = fieldConfig.column;
|
|
32
|
+
if (fieldConfig.type === 'string') {
|
|
33
|
+
protectedStringFields.push(fieldConfig.column);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if ('from' in config && typeof config.from === 'string' && !('type' in config && (config.type === 'object' || config.type === 'array'))) {
|
|
38
|
+
// Legacy field mapping: "fieldName": { "from": "column_name", "type": "string" }
|
|
39
|
+
const fieldConfig = config;
|
|
40
|
+
if (typeof fieldConfig === 'object' && 'from' in fieldConfig) {
|
|
41
|
+
columns[fieldName] = fieldConfig.from;
|
|
42
|
+
if (fieldConfig.type === 'string') {
|
|
43
|
+
protectedStringFields.push(fieldConfig.from);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if ('type' in config && (config.type === 'object' || config.type === 'array')) {
|
|
48
|
+
// Nested structure: object or array
|
|
49
|
+
const nestedStructure = config;
|
|
50
|
+
const entityId = generateEntityId();
|
|
51
|
+
const processedNested = processStructure(nestedStructure.structure, entityId);
|
|
52
|
+
nestedEntities.push({
|
|
53
|
+
id: entityId,
|
|
54
|
+
name: fieldName.charAt(0).toUpperCase() + fieldName.slice(1), // Capitalize first letter
|
|
55
|
+
parentId: parentId || 'root',
|
|
56
|
+
propertyName: fieldName,
|
|
57
|
+
relationshipType: nestedStructure.type,
|
|
58
|
+
columns: processedNested.columns
|
|
59
|
+
});
|
|
60
|
+
// Add nested entities from deeper levels
|
|
61
|
+
nestedEntities.push(...processedNested.nestedEntities.map(entity => ({
|
|
62
|
+
...entity,
|
|
63
|
+
parentId: entity.parentId === 'root' ? entityId : entity.parentId
|
|
64
|
+
})));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { columns, nestedEntities };
|
|
68
|
+
};
|
|
69
|
+
// Process the root structure
|
|
70
|
+
const processed = processStructure(modelMapping.structure); // Build the traditional JsonMapping
|
|
71
|
+
const jsonMapping = {
|
|
72
|
+
rootName: 'root', // Default root name
|
|
73
|
+
rootEntity: {
|
|
74
|
+
id: 'root',
|
|
75
|
+
name: 'Root',
|
|
76
|
+
columns: processed.columns
|
|
77
|
+
},
|
|
78
|
+
nestedEntities: processed.nestedEntities
|
|
79
|
+
};
|
|
80
|
+
// Add typeInfo for backward compatibility
|
|
81
|
+
jsonMapping.typeInfo = modelMapping.typeInfo;
|
|
82
|
+
return {
|
|
83
|
+
jsonMapping,
|
|
84
|
+
typeProtection: { protectedStringFields }
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate that a model-driven mapping structure is well-formed.
|
|
89
|
+
*/
|
|
90
|
+
function validateModelDrivenMapping(mapping) {
|
|
91
|
+
const errors = [];
|
|
92
|
+
// Validate typeInfo
|
|
93
|
+
if (!mapping.typeInfo) {
|
|
94
|
+
errors.push('typeInfo is required');
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
if (!mapping.typeInfo.interface) {
|
|
98
|
+
errors.push('typeInfo.interface is required');
|
|
99
|
+
}
|
|
100
|
+
if (!mapping.typeInfo.importPath) {
|
|
101
|
+
errors.push('typeInfo.importPath is required');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Validate structure
|
|
105
|
+
if (!mapping.structure || typeof mapping.structure !== 'object') {
|
|
106
|
+
errors.push('structure is required and must be an object');
|
|
107
|
+
}
|
|
108
|
+
return errors;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=ModelDrivenJsonMapping.js.map
|