rawsql-ts 0.11.0-beta → 0.11.2-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 +1 -3
- package/dist/esm/index.js +8 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +47 -13
- package/dist/esm/index.min.js.map +4 -4
- package/dist/esm/src/index.js +8 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/parsers/ValueParser.js +86 -4
- package/dist/esm/src/parsers/ValueParser.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.map +1 -1
- package/dist/esm/src/transformers/EnhancedJsonMapping.js +217 -0
- package/dist/esm/src/transformers/EnhancedJsonMapping.js.map +1 -0
- package/dist/esm/src/transformers/JsonMappingConverter.js +388 -0
- package/dist/esm/src/transformers/JsonMappingConverter.js.map +1 -0
- package/dist/esm/src/transformers/JsonMappingUnifier.js +207 -0
- package/dist/esm/src/transformers/JsonMappingUnifier.js.map +1 -0
- package/dist/esm/src/transformers/ModelDrivenJsonMapping.js +115 -0
- package/dist/esm/src/transformers/ModelDrivenJsonMapping.js.map +1 -0
- package/dist/esm/src/transformers/PostgresArrayEntityCteBuilder.js +293 -70
- package/dist/esm/src/transformers/PostgresArrayEntityCteBuilder.js.map +1 -1
- package/dist/esm/src/transformers/PostgresJsonQueryBuilder.js +26 -15
- package/dist/esm/src/transformers/PostgresJsonQueryBuilder.js.map +1 -1
- package/dist/esm/src/transformers/PostgresObjectEntityCteBuilder.js +75 -15
- 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/SqlParamInjector.js +189 -108
- package/dist/esm/src/transformers/SqlParamInjector.js.map +1 -1
- package/dist/esm/src/transformers/UnifiedJsonMapping.js +2 -4
- package/dist/esm/src/transformers/UnifiedJsonMapping.js.map +1 -1
- package/dist/esm/src/transformers/UpstreamSelectQueryFinder.js +51 -3
- package/dist/esm/src/transformers/UpstreamSelectQueryFinder.js.map +1 -1
- 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 +8 -1
- package/dist/esm/types/src/parsers/ValueParser.d.ts +8 -0
- package/dist/esm/types/src/transformers/CTEDependencyTracer.d.ts +58 -0
- package/dist/esm/types/src/transformers/DynamicQueryBuilder.d.ts +6 -0
- package/dist/esm/types/src/transformers/EnhancedJsonMapping.d.ts +194 -0
- package/dist/esm/types/src/transformers/JsonMappingConverter.d.ts +200 -0
- package/dist/esm/types/src/transformers/JsonMappingUnifier.d.ts +100 -0
- package/dist/esm/types/src/transformers/ModelDrivenJsonMapping.d.ts +62 -0
- package/dist/esm/types/src/transformers/PostgresArrayEntityCteBuilder.d.ts +93 -52
- package/dist/esm/types/src/transformers/PostgresJsonQueryBuilder.d.ts +3 -3
- package/dist/esm/types/src/transformers/PostgresObjectEntityCteBuilder.d.ts +31 -6
- package/dist/esm/types/src/transformers/SelectableColumnCollector.d.ts +14 -3
- package/dist/esm/types/src/transformers/SqlParamInjector.d.ts +48 -0
- package/dist/esm/types/src/transformers/UnifiedJsonMapping.d.ts +0 -1
- package/dist/esm/types/src/transformers/UpstreamSelectQueryFinder.d.ts +13 -1
- package/dist/index.min.js +47 -13
- package/dist/index.min.js.map +4 -4
- package/dist/src/index.d.ts +8 -1
- package/dist/src/index.js +15 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/parsers/ValueParser.d.ts +8 -0
- package/dist/src/parsers/ValueParser.js +86 -4
- package/dist/src/parsers/ValueParser.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 +6 -0
- package/dist/src/transformers/DynamicQueryBuilder.js.map +1 -1
- package/dist/src/transformers/EnhancedJsonMapping.d.ts +194 -0
- package/dist/src/transformers/EnhancedJsonMapping.js +223 -0
- package/dist/src/transformers/EnhancedJsonMapping.js.map +1 -0
- package/dist/src/transformers/JsonMappingConverter.d.ts +200 -0
- package/dist/src/transformers/JsonMappingConverter.js +392 -0
- package/dist/src/transformers/JsonMappingConverter.js.map +1 -0
- package/dist/src/transformers/JsonMappingUnifier.d.ts +100 -0
- package/dist/src/transformers/JsonMappingUnifier.js +216 -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 +122 -0
- package/dist/src/transformers/ModelDrivenJsonMapping.js.map +1 -0
- package/dist/src/transformers/PostgresArrayEntityCteBuilder.d.ts +93 -52
- package/dist/src/transformers/PostgresArrayEntityCteBuilder.js +293 -70
- package/dist/src/transformers/PostgresArrayEntityCteBuilder.js.map +1 -1
- package/dist/src/transformers/PostgresJsonQueryBuilder.d.ts +3 -3
- package/dist/src/transformers/PostgresJsonQueryBuilder.js +26 -15
- package/dist/src/transformers/PostgresJsonQueryBuilder.js.map +1 -1
- package/dist/src/transformers/PostgresObjectEntityCteBuilder.d.ts +31 -6
- package/dist/src/transformers/PostgresObjectEntityCteBuilder.js +75 -15
- 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/SqlParamInjector.d.ts +48 -0
- package/dist/src/transformers/SqlParamInjector.js +189 -108
- package/dist/src/transformers/SqlParamInjector.js.map +1 -1
- package/dist/src/transformers/UnifiedJsonMapping.d.ts +0 -1
- package/dist/src/transformers/UnifiedJsonMapping.js +2 -4
- package/dist/src/transformers/UnifiedJsonMapping.js.map +1 -1
- package/dist/src/transformers/UpstreamSelectQueryFinder.d.ts +13 -1
- package/dist/src/transformers/UpstreamSelectQueryFinder.js +51 -3
- package/dist/src/transformers/UpstreamSelectQueryFinder.js.map +1 -1
- 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 +2 -2
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Unified JSON Mapping processor that supports both legacy and model-driven formats.
|
|
4
|
+
*
|
|
5
|
+
* @deprecated Use JsonMappingConverter instead. This module is kept for backward compatibility.
|
|
6
|
+
* This module provides backward compatibility while encouraging migration to the model-driven format.
|
|
7
|
+
* It automatically detects the input format and normalizes to a consistent internal representation.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.detectMappingFormat = detectMappingFormat;
|
|
11
|
+
exports.processJsonMapping = processJsonMapping;
|
|
12
|
+
exports.unifyJsonMapping = unifyJsonMapping;
|
|
13
|
+
exports.isModelDrivenFormat = isModelDrivenFormat;
|
|
14
|
+
exports.isUnifiedFormat = isUnifiedFormat;
|
|
15
|
+
exports.isLegacyFormat = isLegacyFormat;
|
|
16
|
+
exports.suggestModelDrivenMigration = suggestModelDrivenMigration;
|
|
17
|
+
const JsonMappingConverter_1 = require("./JsonMappingConverter");
|
|
18
|
+
/**
|
|
19
|
+
* Detects the format of a JSON mapping configuration.
|
|
20
|
+
*
|
|
21
|
+
* @param input - The mapping configuration to analyze
|
|
22
|
+
* @returns The detected format type
|
|
23
|
+
*/
|
|
24
|
+
function detectMappingFormat(input) {
|
|
25
|
+
// Model-driven format: has typeInfo and structure
|
|
26
|
+
if (input.typeInfo && input.structure) {
|
|
27
|
+
return 'model-driven';
|
|
28
|
+
}
|
|
29
|
+
// Unified format: has rootName and rootEntity
|
|
30
|
+
if (input.rootName && input.rootEntity) {
|
|
31
|
+
return 'unified';
|
|
32
|
+
}
|
|
33
|
+
// Legacy format: direct JsonMapping structure
|
|
34
|
+
if (input.columns || input.relationships) {
|
|
35
|
+
return 'legacy';
|
|
36
|
+
}
|
|
37
|
+
// Default fallback
|
|
38
|
+
return 'legacy';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Converts legacy unified format to JsonMapping.
|
|
42
|
+
*
|
|
43
|
+
* @param input - Unified format mapping configuration
|
|
44
|
+
* @returns Converted JsonMapping
|
|
45
|
+
*/
|
|
46
|
+
function convertUnifiedFormat(input) {
|
|
47
|
+
if (!input.rootEntity) {
|
|
48
|
+
throw new Error('Unified format requires rootEntity');
|
|
49
|
+
}
|
|
50
|
+
const result = {
|
|
51
|
+
rootName: input.rootName || 'root',
|
|
52
|
+
rootEntity: {
|
|
53
|
+
id: input.rootEntity.id || 'root',
|
|
54
|
+
name: input.rootEntity.name || 'Root',
|
|
55
|
+
columns: input.rootEntity.columns || {}
|
|
56
|
+
},
|
|
57
|
+
nestedEntities: []
|
|
58
|
+
};
|
|
59
|
+
// Convert nestedEntities
|
|
60
|
+
if (input.nestedEntities && Array.isArray(input.nestedEntities)) {
|
|
61
|
+
result.nestedEntities = input.nestedEntities.map(entity => ({
|
|
62
|
+
id: entity.id || entity.propertyName || 'nested',
|
|
63
|
+
name: entity.name || entity.propertyName || 'Nested',
|
|
64
|
+
parentId: entity.parentId || result.rootEntity.id,
|
|
65
|
+
propertyName: entity.propertyName || 'nested',
|
|
66
|
+
relationshipType: entity.relationshipType || 'object',
|
|
67
|
+
columns: entity.columns || {}
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Converts legacy format directly to JsonMapping.
|
|
74
|
+
*
|
|
75
|
+
* @param input - Legacy format mapping configuration
|
|
76
|
+
* @returns JsonMapping
|
|
77
|
+
*/
|
|
78
|
+
function convertLegacyFormat(input) {
|
|
79
|
+
const result = {
|
|
80
|
+
rootName: input.rootName || 'root',
|
|
81
|
+
rootEntity: {
|
|
82
|
+
id: 'root',
|
|
83
|
+
name: input.rootName || 'Root',
|
|
84
|
+
columns: input.columns || {}
|
|
85
|
+
},
|
|
86
|
+
nestedEntities: []
|
|
87
|
+
};
|
|
88
|
+
// Convert relationships to nestedEntities
|
|
89
|
+
if (input.relationships && typeof input.relationships === 'object') {
|
|
90
|
+
for (const [propertyName, relationship] of Object.entries(input.relationships)) {
|
|
91
|
+
// Type assertion for legacy relationship format
|
|
92
|
+
const rel = relationship;
|
|
93
|
+
result.nestedEntities.push({
|
|
94
|
+
id: propertyName,
|
|
95
|
+
name: propertyName.charAt(0).toUpperCase() + propertyName.slice(1),
|
|
96
|
+
parentId: 'root',
|
|
97
|
+
propertyName,
|
|
98
|
+
relationshipType: rel.type === 'hasMany' ? 'array' : 'object',
|
|
99
|
+
columns: rel.columns || {}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Main processor that unifies all JSON mapping formats into a consistent JsonMapping.
|
|
107
|
+
*
|
|
108
|
+
* @deprecated Use JsonMappingConverter.convert() instead.
|
|
109
|
+
*
|
|
110
|
+
* Features:
|
|
111
|
+
* - Automatic format detection
|
|
112
|
+
* - Backward compatibility with all existing formats
|
|
113
|
+
* - Metadata preservation for advanced features
|
|
114
|
+
* - Zero external dependencies
|
|
115
|
+
*
|
|
116
|
+
* @param input - Any supported JSON mapping format
|
|
117
|
+
* @returns Unified processing result with JsonMapping and metadata
|
|
118
|
+
*/
|
|
119
|
+
function processJsonMapping(input) {
|
|
120
|
+
var _a;
|
|
121
|
+
// Runtime deprecation warning
|
|
122
|
+
console.warn('⚠️ DEPRECATED: processJsonMapping() is deprecated. Use JsonMappingConverter.convert() instead.');
|
|
123
|
+
console.warn('Migration guide: https://github.com/mk3008/rawsql-ts/blob/main/docs/migration-guide.md');
|
|
124
|
+
// Check for legacy format with columns and relationships
|
|
125
|
+
if ((input.columns || input.relationships) && !input.rootName && !input.rootEntity) {
|
|
126
|
+
const jsonMapping = convertLegacyFormat(input);
|
|
127
|
+
return {
|
|
128
|
+
format: 'legacy',
|
|
129
|
+
jsonMapping,
|
|
130
|
+
originalInput: input,
|
|
131
|
+
metadata: {}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const converter = new JsonMappingConverter_1.JsonMappingConverter();
|
|
135
|
+
const result = converter.convert(input);
|
|
136
|
+
// Map converter formats to unifier formats for backward compatibility
|
|
137
|
+
let format = result.format;
|
|
138
|
+
// If it's detected as 'legacy' by converter but has rootName and rootEntity, it's 'unified' format
|
|
139
|
+
if (result.format === 'legacy' && input.rootName && input.rootEntity) {
|
|
140
|
+
format = 'unified';
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
format,
|
|
144
|
+
jsonMapping: result.mapping,
|
|
145
|
+
originalInput: input,
|
|
146
|
+
metadata: {
|
|
147
|
+
typeInfo: (_a = result.metadata) === null || _a === void 0 ? void 0 : _a.typeInfo,
|
|
148
|
+
typeProtection: result.typeProtection
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Convenience function for direct JsonMapping extraction.
|
|
154
|
+
*
|
|
155
|
+
* @deprecated Use JsonMappingConverter.toLegacyMapping() instead.
|
|
156
|
+
*
|
|
157
|
+
* @param input - Any supported JSON mapping format
|
|
158
|
+
* @returns JsonMapping ready for use with PostgresJsonQueryBuilder
|
|
159
|
+
*/
|
|
160
|
+
function unifyJsonMapping(input) {
|
|
161
|
+
// Runtime deprecation warning
|
|
162
|
+
console.warn('⚠️ DEPRECATED: unifyJsonMapping() is deprecated. Use JsonMappingConverter.toLegacyMapping() instead.');
|
|
163
|
+
console.warn('Migration guide: https://github.com/mk3008/rawsql-ts/blob/main/docs/migration-guide.md');
|
|
164
|
+
const converter = new JsonMappingConverter_1.JsonMappingConverter();
|
|
165
|
+
return converter.toLegacyMapping(input);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Type guard to check if input uses model-driven format.
|
|
169
|
+
*
|
|
170
|
+
* @param input - Mapping input to check
|
|
171
|
+
* @returns True if input is model-driven format
|
|
172
|
+
*/
|
|
173
|
+
function isModelDrivenFormat(input) {
|
|
174
|
+
return detectMappingFormat(input) === 'model-driven';
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Type guard to check if input uses unified format.
|
|
178
|
+
*
|
|
179
|
+
* @param input - Mapping input to check
|
|
180
|
+
* @returns True if input is unified format
|
|
181
|
+
*/
|
|
182
|
+
function isUnifiedFormat(input) {
|
|
183
|
+
return detectMappingFormat(input) === 'unified';
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Type guard to check if input uses legacy format.
|
|
187
|
+
*
|
|
188
|
+
* @param input - Mapping input to check
|
|
189
|
+
* @returns True if input is legacy format
|
|
190
|
+
*/
|
|
191
|
+
function isLegacyFormat(input) {
|
|
192
|
+
return detectMappingFormat(input) === 'legacy';
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Migration helper that suggests upgrading to model-driven format.
|
|
196
|
+
*
|
|
197
|
+
* @param input - Current mapping configuration
|
|
198
|
+
* @returns Suggestions for migration (if applicable)
|
|
199
|
+
*/
|
|
200
|
+
function suggestModelDrivenMigration(input) {
|
|
201
|
+
const format = detectMappingFormat(input);
|
|
202
|
+
const suggestions = [];
|
|
203
|
+
if (format !== 'model-driven') {
|
|
204
|
+
suggestions.push('Consider migrating to model-driven JSON mapping format');
|
|
205
|
+
suggestions.push('Benefits: Better type safety, IDE support, and future-proof design');
|
|
206
|
+
suggestions.push('See: Model-Driven JSON Mapping Guide for migration instructions');
|
|
207
|
+
if (format === 'unified') {
|
|
208
|
+
suggestions.push('Your current unified format can be automatically converted');
|
|
209
|
+
}
|
|
210
|
+
if (format === 'legacy') {
|
|
211
|
+
suggestions.push('Legacy format support will be maintained but new features target model-driven format');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return suggestions;
|
|
215
|
+
}
|
|
216
|
+
//# 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,122 @@
|
|
|
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
|
+
const propertyNameCounters = {};
|
|
17
|
+
// Generate unique entity IDs
|
|
18
|
+
const generateEntityId = () => `entity_${++entityIdCounter}`;
|
|
19
|
+
// Generate unique property names to avoid JSON key conflicts
|
|
20
|
+
const generateUniquePropertyName = (baseName) => {
|
|
21
|
+
if (!propertyNameCounters[baseName]) {
|
|
22
|
+
propertyNameCounters[baseName] = 0;
|
|
23
|
+
}
|
|
24
|
+
propertyNameCounters[baseName]++;
|
|
25
|
+
return propertyNameCounters[baseName] === 1 ? baseName : `${baseName}_${propertyNameCounters[baseName]}`;
|
|
26
|
+
};
|
|
27
|
+
// Helper function to process structure fields and extract entities
|
|
28
|
+
const processStructure = (structure, parentId = null) => {
|
|
29
|
+
const columns = {};
|
|
30
|
+
const nestedEntities = [];
|
|
31
|
+
for (const [fieldName, config] of Object.entries(structure)) {
|
|
32
|
+
if (typeof config === 'string') {
|
|
33
|
+
// Simple field mapping: "fieldName": "column_name"
|
|
34
|
+
columns[fieldName] = config;
|
|
35
|
+
}
|
|
36
|
+
else if ('column' in config && typeof config.column === 'string' && !('type' in config && (config.type === 'object' || config.type === 'array'))) {
|
|
37
|
+
// Enhanced field mapping: "fieldName": { "column": "column_name", "type": "string" }
|
|
38
|
+
const fieldConfig = config;
|
|
39
|
+
if (typeof fieldConfig === 'object' && 'column' in fieldConfig) {
|
|
40
|
+
columns[fieldName] = fieldConfig.column;
|
|
41
|
+
if (fieldConfig.type === 'string') {
|
|
42
|
+
protectedStringFields.push(fieldConfig.column);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if ('from' in config && typeof config.from === 'string' && !('type' in config && (config.type === 'object' || config.type === 'array'))) {
|
|
47
|
+
// Legacy field mapping: "fieldName": { "from": "column_name", "type": "string" }
|
|
48
|
+
const fieldConfig = config;
|
|
49
|
+
if (typeof fieldConfig === 'object' && 'from' in fieldConfig) {
|
|
50
|
+
columns[fieldName] = fieldConfig.from;
|
|
51
|
+
if (fieldConfig.type === 'string') {
|
|
52
|
+
protectedStringFields.push(fieldConfig.from);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if ('type' in config && (config.type === 'object' || config.type === 'array')) {
|
|
57
|
+
// Nested structure: object or array
|
|
58
|
+
const nestedStructure = config;
|
|
59
|
+
const uniquePropertyName = generateUniquePropertyName(fieldName);
|
|
60
|
+
// Generate globally unique entity ID to ensure unique JSON column names
|
|
61
|
+
const entityId = generateEntityId();
|
|
62
|
+
const processedNested = processStructure(nestedStructure.structure, entityId);
|
|
63
|
+
nestedEntities.push({
|
|
64
|
+
id: entityId, // Use unique ID to avoid column conflicts
|
|
65
|
+
name: fieldName.charAt(0).toUpperCase() + fieldName.slice(1), // Capitalize first letter
|
|
66
|
+
parentId: parentId || 'root',
|
|
67
|
+
propertyName: uniquePropertyName,
|
|
68
|
+
originalPropertyName: fieldName, // Store original name for final mapping
|
|
69
|
+
relationshipType: nestedStructure.type,
|
|
70
|
+
columns: processedNested.columns
|
|
71
|
+
});
|
|
72
|
+
// Add nested entities from deeper levels
|
|
73
|
+
nestedEntities.push(...processedNested.nestedEntities.map(entity => ({
|
|
74
|
+
...entity,
|
|
75
|
+
parentId: entity.parentId === 'root' ? entityId : entity.parentId
|
|
76
|
+
})));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { columns, nestedEntities };
|
|
80
|
+
};
|
|
81
|
+
// Process the root structure
|
|
82
|
+
const processed = processStructure(modelMapping.structure); // Build the traditional JsonMapping
|
|
83
|
+
const jsonMapping = {
|
|
84
|
+
rootName: 'root', // Default root name
|
|
85
|
+
rootEntity: {
|
|
86
|
+
id: 'root',
|
|
87
|
+
name: 'Root',
|
|
88
|
+
columns: processed.columns
|
|
89
|
+
},
|
|
90
|
+
nestedEntities: processed.nestedEntities
|
|
91
|
+
};
|
|
92
|
+
// Add typeInfo for backward compatibility
|
|
93
|
+
jsonMapping.typeInfo = modelMapping.typeInfo;
|
|
94
|
+
return {
|
|
95
|
+
jsonMapping,
|
|
96
|
+
typeProtection: { protectedStringFields }
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Validate that a model-driven mapping structure is well-formed.
|
|
101
|
+
*/
|
|
102
|
+
function validateModelDrivenMapping(mapping) {
|
|
103
|
+
const errors = [];
|
|
104
|
+
// Validate typeInfo
|
|
105
|
+
if (!mapping.typeInfo) {
|
|
106
|
+
errors.push('typeInfo is required');
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
if (!mapping.typeInfo.interface) {
|
|
110
|
+
errors.push('typeInfo.interface is required');
|
|
111
|
+
}
|
|
112
|
+
if (!mapping.typeInfo.importPath) {
|
|
113
|
+
errors.push('typeInfo.importPath is required');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Validate structure
|
|
117
|
+
if (!mapping.structure || typeof mapping.structure !== 'object') {
|
|
118
|
+
errors.push('structure is required and must be an object');
|
|
119
|
+
}
|
|
120
|
+
return errors;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=ModelDrivenJsonMapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModelDrivenJsonMapping.js","sourceRoot":"","sources":["../../../src/transformers/ModelDrivenJsonMapping.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,97 +1,138 @@
|
|
|
1
1
|
import { CommonTable } from '../models/Clause';
|
|
2
2
|
import { JsonMapping } from './PostgresJsonQueryBuilder';
|
|
3
|
-
import { ProcessableEntity } from './PostgresObjectEntityCteBuilder';
|
|
3
|
+
import { ProcessableEntity, JsonColumnMapping } from './PostgresObjectEntityCteBuilder';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
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.
|
|
5
|
+
* Builds CTEs for array entities using depth-first processing and row compression.
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
* - Row
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
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
|
|
7
|
+
* Core concepts:
|
|
8
|
+
* - Column Compression: OBJECT relationships (user_id, user_name → user_json)
|
|
9
|
+
* - Row Compression: ARRAY relationships (multiple rows → JSON array via GROUP BY)
|
|
10
|
+
* - Depth-First: Process deepest arrays first for dependency ordering
|
|
11
|
+
* - GROUP BY Exclusion: Exclude array-internal columns to prevent over-grouping
|
|
30
12
|
*/
|
|
31
13
|
export declare class PostgresArrayEntityCteBuilder {
|
|
32
14
|
private static readonly CTE_ARRAY_PREFIX;
|
|
15
|
+
private static readonly JSON_FUNCTIONS;
|
|
33
16
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
17
|
+
* Builds CTEs for all array entities using depth-first processing.
|
|
18
|
+
* Collects arrays by depth, processes deepest first, chains CTEs.
|
|
19
|
+
*
|
|
20
|
+
* @param ctesSoFar Array of CTEs built so far
|
|
21
|
+
* @param aliasOfCteToBuildUpon Alias of the CTE to build upon
|
|
37
22
|
* @param allEntities Map of all entities in the mapping
|
|
38
23
|
* @param mapping The JSON mapping configuration
|
|
39
|
-
* @
|
|
24
|
+
* @param columnMappings Optional mappings from object entity IDs to generated JSON column names
|
|
25
|
+
* @returns Object containing updated CTEs and last CTE alias
|
|
40
26
|
*/
|
|
41
|
-
buildArrayEntityCtes(ctesSoFar: CommonTable[], aliasOfCteToBuildUpon: string, allEntities: Map<string, ProcessableEntity>, mapping: JsonMapping): {
|
|
27
|
+
buildArrayEntityCtes(ctesSoFar: CommonTable[], aliasOfCteToBuildUpon: string, allEntities: Map<string, ProcessableEntity>, mapping: JsonMapping, columnMappings?: JsonColumnMapping[]): {
|
|
42
28
|
updatedCtes: CommonTable[];
|
|
43
29
|
lastCteAlias: string;
|
|
44
30
|
};
|
|
45
31
|
/**
|
|
46
|
-
*
|
|
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.
|
|
32
|
+
* Collects array entities and calculates depth for dependency ordering.
|
|
33
|
+
* Depth = distance from root. Deeper arrays processed first.
|
|
51
34
|
*
|
|
52
35
|
* @param mapping The JSON mapping configuration
|
|
53
36
|
* @param allEntities Map of all entities in the mapping
|
|
54
|
-
* @returns Array of array entity information with
|
|
37
|
+
* @returns Array of array entity information with depths, sorted deepest first
|
|
55
38
|
*/
|
|
56
39
|
private collectAndSortArrayEntities;
|
|
57
40
|
/**
|
|
58
|
-
*
|
|
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
|
|
41
|
+
* Groups array entities by depth level for batch processing.
|
|
64
42
|
*
|
|
65
43
|
* @param arrayInfos Array of array entity information with depths
|
|
66
44
|
* @returns Map of depth level to entities at that depth
|
|
67
45
|
*/
|
|
68
46
|
private groupEntitiesByDepth;
|
|
69
47
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* at the same depth, using GROUP BY to compress rows into JSON arrays.
|
|
48
|
+
* Builds CTE for specific depth level using row compression.
|
|
49
|
+
* Uses GROUP BY to aggregate multiple rows into JSON arrays.
|
|
50
|
+
* Excludes array-internal columns from GROUP BY to prevent over-grouping.
|
|
74
51
|
*
|
|
75
52
|
* @param infos Array entities at this depth level
|
|
76
53
|
* @param currentCteAlias Alias of the CTE to build upon
|
|
77
54
|
* @param currentCtes All CTEs built so far
|
|
78
55
|
* @param depth Current depth level being processed
|
|
79
56
|
* @param mapping JSON mapping configuration
|
|
57
|
+
* @param columnMappings Optional mappings from object entity IDs to generated JSON column names
|
|
80
58
|
* @returns The new CTE and its alias
|
|
81
59
|
*/
|
|
82
60
|
private buildDepthCte;
|
|
83
61
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* the entity's columns into a JSON array. It also handles nested relationships
|
|
88
|
-
* by including child entity properties in the JSON object.
|
|
62
|
+
* Creates jsonb_agg function for array entity.
|
|
63
|
+
* Handles entity columns and nested child relationships.
|
|
64
|
+
* Uses originalPropertyName to avoid sequential numbering.
|
|
89
65
|
*
|
|
90
66
|
* @param entity The array entity being processed
|
|
91
67
|
* @param nestedEntities All nested entities from the mapping
|
|
92
68
|
* @param allEntities Map of all entities (not used in current implementation)
|
|
93
|
-
* @param
|
|
69
|
+
* @param columnMappings Mappings from object entity IDs to generated JSON column names
|
|
94
70
|
* @returns Object containing the JSON aggregation function
|
|
95
71
|
*/
|
|
96
72
|
private buildAggregationDetailsForArrayEntity;
|
|
73
|
+
/**
|
|
74
|
+
* Collects array entity columns by depth for GROUP BY exclusion strategy.
|
|
75
|
+
*
|
|
76
|
+
* @param mapping The JSON mapping configuration containing all entities
|
|
77
|
+
* @param currentDepth The current aggregation depth being processed
|
|
78
|
+
* @returns A map where keys are depth levels and values are sets of column names
|
|
79
|
+
*/
|
|
80
|
+
private collectArrayEntityColumnsByDepth;
|
|
81
|
+
/**
|
|
82
|
+
* Calculates entity depth by traversing up to root.
|
|
83
|
+
*
|
|
84
|
+
* @param entity The entity to calculate depth for
|
|
85
|
+
* @param mapping The JSON mapping containing all entities
|
|
86
|
+
* @returns The depth level (0 for root level, 1 for first level, etc.)
|
|
87
|
+
*/
|
|
88
|
+
private calculateEntityDepth;
|
|
89
|
+
/**
|
|
90
|
+
* Adds entity columns to depth set.
|
|
91
|
+
*
|
|
92
|
+
* @param entity The entity whose columns should be added
|
|
93
|
+
* @param depth The depth level to add columns to
|
|
94
|
+
* @param arrayEntitiesByDepth The map to update
|
|
95
|
+
*/
|
|
96
|
+
private addEntityColumnsToDepthSet;
|
|
97
|
+
/**
|
|
98
|
+
* Recursively collects columns from descendant entities.
|
|
99
|
+
*
|
|
100
|
+
* @param parentEntityId The ID of the parent entity
|
|
101
|
+
* @param targetDepth The depth level to assign collected columns to
|
|
102
|
+
* @param mapping The JSON mapping containing all entities
|
|
103
|
+
* @param arrayEntitiesByDepth The map to update with collected columns
|
|
104
|
+
*/
|
|
105
|
+
private collectDescendantColumns;
|
|
106
|
+
/**
|
|
107
|
+
* Implements GROUP BY exclusion strategy for array aggregation.
|
|
108
|
+
* Excludes current array columns and array-internal object JSON columns.
|
|
109
|
+
*
|
|
110
|
+
* @param prevSelects SELECT variables from the previous CTE
|
|
111
|
+
* @param arrayColumns Columns that are being aggregated (should be excluded from GROUP BY)
|
|
112
|
+
* @param arrayEntitiesByDepth Map of depth levels to their column sets
|
|
113
|
+
* @param currentDepth The current aggregation depth being processed
|
|
114
|
+
* @param selectItems Output array for SELECT items
|
|
115
|
+
* @param groupByItems Output array for GROUP BY items
|
|
116
|
+
* @param arrayInternalObjectColumns JSON columns from objects within arrays being processed
|
|
117
|
+
*/
|
|
118
|
+
private processSelectVariablesForGroupBy;
|
|
119
|
+
/**
|
|
120
|
+
* Determines if column should be included in GROUP BY clause.
|
|
121
|
+
* Applies depth-based filtering and special handling for JSON columns.
|
|
122
|
+
*
|
|
123
|
+
* @param columnName The name of the column to evaluate
|
|
124
|
+
* @param arrayEntitiesByDepth Map of depth levels to their column sets
|
|
125
|
+
* @param currentDepth The current aggregation depth
|
|
126
|
+
* @returns True if the column should be included in GROUP BY, false otherwise
|
|
127
|
+
*/
|
|
128
|
+
private shouldIncludeColumnInGroupBy;
|
|
129
|
+
/**
|
|
130
|
+
* Applies heuristics for entity JSON column inclusion in GROUP BY.
|
|
131
|
+
* Uses entity numbering patterns to identify deeply nested entities.
|
|
132
|
+
*
|
|
133
|
+
* @param columnName The JSON column name (expected format: entity_N_json)
|
|
134
|
+
* @param currentDepth The current aggregation depth
|
|
135
|
+
* @returns True if the JSON column should be included, false otherwise
|
|
136
|
+
*/
|
|
137
|
+
private shouldIncludeJsonColumn;
|
|
97
138
|
}
|