@forestadmin-experimental/datasource-cosmos 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +512 -0
- package/dist/collection.d.ts +14 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +90 -0
- package/dist/datasource.d.ts +26 -0
- package/dist/datasource.d.ts.map +1 -0
- package/dist/datasource.js +87 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/introspection/builder.d.ts +68 -0
- package/dist/introspection/builder.d.ts.map +1 -0
- package/dist/introspection/builder.js +31 -0
- package/dist/introspection/container-introspector.d.ts +27 -0
- package/dist/introspection/container-introspector.d.ts.map +1 -0
- package/dist/introspection/container-introspector.js +168 -0
- package/dist/introspection/introspector.d.ts +18 -0
- package/dist/introspection/introspector.d.ts.map +1 -0
- package/dist/introspection/introspector.js +55 -0
- package/dist/model-builder/model.d.ts +79 -0
- package/dist/model-builder/model.d.ts.map +1 -0
- package/dist/model-builder/model.js +176 -0
- package/dist/utils/aggregation-converter.d.ts +30 -0
- package/dist/utils/aggregation-converter.d.ts.map +1 -0
- package/dist/utils/aggregation-converter.js +181 -0
- package/dist/utils/model-to-collection-schema-converter.d.ts +9 -0
- package/dist/utils/model-to-collection-schema-converter.d.ts.map +1 -0
- package/dist/utils/model-to-collection-schema-converter.js +72 -0
- package/dist/utils/query-converter.d.ts +38 -0
- package/dist/utils/query-converter.d.ts.map +1 -0
- package/dist/utils/query-converter.js +199 -0
- package/dist/utils/serializer.d.ts +6 -0
- package/dist/utils/serializer.d.ts.map +1 -0
- package/dist/utils/serializer.js +29 -0
- package/dist/utils/type-converter.d.ts +43 -0
- package/dist/utils/type-converter.d.ts.map +1 -0
- package/dist/utils/type-converter.js +157 -0
- package/package.json +36 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SqlParameter, SqlQuerySpec } from '@azure/cosmos';
|
|
2
|
+
import { ConditionTree, Sort } from '@forestadmin/datasource-toolkit';
|
|
3
|
+
export default class QueryConverter {
|
|
4
|
+
private parameterCounter;
|
|
5
|
+
private parameters;
|
|
6
|
+
/**
|
|
7
|
+
* Reset the converter state for a new query
|
|
8
|
+
*/
|
|
9
|
+
private reset;
|
|
10
|
+
/**
|
|
11
|
+
* Add a parameter and return its name
|
|
12
|
+
*/
|
|
13
|
+
private addParameter;
|
|
14
|
+
/**
|
|
15
|
+
* Convert a single condition to SQL WHERE clause fragment
|
|
16
|
+
*/
|
|
17
|
+
private makeWhereClause;
|
|
18
|
+
/**
|
|
19
|
+
* Recursively convert a condition tree to SQL WHERE clause
|
|
20
|
+
*/
|
|
21
|
+
private getWhereClauseFromConditionTree;
|
|
22
|
+
/**
|
|
23
|
+
* Convert condition tree to a complete SQL query spec
|
|
24
|
+
*/
|
|
25
|
+
getSqlQuerySpec(conditionTree?: ConditionTree, sort?: Sort, projection?: string[]): SqlQuerySpec;
|
|
26
|
+
/**
|
|
27
|
+
* Convert sort to ORDER BY clause
|
|
28
|
+
*/
|
|
29
|
+
getOrderByClause(sort?: Sort): string;
|
|
30
|
+
/**
|
|
31
|
+
* Get WHERE clause only (for use in subqueries or COUNT operations)
|
|
32
|
+
*/
|
|
33
|
+
getWhereClause(conditionTree?: ConditionTree): {
|
|
34
|
+
where: string;
|
|
35
|
+
parameters: SqlParameter[];
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=query-converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-converter.d.ts","sourceRoot":"","sources":["../../src/utils/query-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,aAAa,EAIb,IAAI,EACL,MAAM,iCAAiC,CAAC;AAEzC,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,UAAU,CAAsB;IAExC;;OAEG;IACH,OAAO,CAAC,KAAK;IAKb;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,eAAe;IA0HvB;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAyCvC;;OAEG;IACI,eAAe,CACpB,aAAa,CAAC,EAAE,aAAa,EAC7B,IAAI,CAAC,EAAE,IAAI,EACX,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,YAAY;IA2Bf;;OAEG;IACI,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM;IAe5C;;OAEG;IACI,cAAc,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG;QACpD,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,YAAY,EAAE,CAAC;KAC5B;CAMF"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class QueryConverter {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.parameterCounter = 0;
|
|
6
|
+
this.parameters = [];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Reset the converter state for a new query
|
|
10
|
+
*/
|
|
11
|
+
reset() {
|
|
12
|
+
this.parameterCounter = 0;
|
|
13
|
+
this.parameters = [];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Add a parameter and return its name
|
|
17
|
+
*/
|
|
18
|
+
addParameter(value) {
|
|
19
|
+
const paramName = `@param${this.parameterCounter}`;
|
|
20
|
+
this.parameterCounter += 1;
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
this.parameters.push({ name: paramName, value: value });
|
|
23
|
+
return paramName;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert a single condition to SQL WHERE clause fragment
|
|
27
|
+
*/
|
|
28
|
+
makeWhereClause(field, operator, value) {
|
|
29
|
+
// Use 'c' as the root alias for Cosmos DB queries
|
|
30
|
+
const fieldPath = field === 'id' ? 'c.id' : `c.${field}`;
|
|
31
|
+
switch (operator) {
|
|
32
|
+
// Presence
|
|
33
|
+
case 'Present':
|
|
34
|
+
return `IS_DEFINED(${fieldPath}) AND ${fieldPath} != null`;
|
|
35
|
+
case 'Missing':
|
|
36
|
+
return `(NOT IS_DEFINED(${fieldPath}) OR ${fieldPath} = null)`;
|
|
37
|
+
// Equality
|
|
38
|
+
case 'Equal':
|
|
39
|
+
if (value === null || value === undefined) {
|
|
40
|
+
return `(NOT IS_DEFINED(${fieldPath}) OR ${fieldPath} = null)`;
|
|
41
|
+
}
|
|
42
|
+
return `${fieldPath} = ${this.addParameter(value)}`;
|
|
43
|
+
case 'NotEqual':
|
|
44
|
+
if (value === null || value === undefined) {
|
|
45
|
+
return `IS_DEFINED(${fieldPath}) AND ${fieldPath} != null`;
|
|
46
|
+
}
|
|
47
|
+
return `${fieldPath} != ${this.addParameter(value)}`;
|
|
48
|
+
case 'In': {
|
|
49
|
+
const values = Array.isArray(value) ? value : [value];
|
|
50
|
+
if (values.length === 0)
|
|
51
|
+
return '1 = 0'; // Always false
|
|
52
|
+
if (values.some(v => v === null || v === undefined)) {
|
|
53
|
+
const nonNullValues = values.filter(v => v !== null && v !== undefined);
|
|
54
|
+
if (nonNullValues.length === 0) {
|
|
55
|
+
return `(NOT IS_DEFINED(${fieldPath}) OR ${fieldPath} = null)`;
|
|
56
|
+
}
|
|
57
|
+
const paramName = this.addParameter(nonNullValues);
|
|
58
|
+
return (`(ARRAY_CONTAINS(${paramName}, ${fieldPath}) OR ` +
|
|
59
|
+
`NOT IS_DEFINED(${fieldPath}) OR ${fieldPath} = null)`);
|
|
60
|
+
}
|
|
61
|
+
const paramName = this.addParameter(values);
|
|
62
|
+
return `ARRAY_CONTAINS(${paramName}, ${fieldPath})`;
|
|
63
|
+
}
|
|
64
|
+
case 'NotIn': {
|
|
65
|
+
const values = Array.isArray(value) ? value : [value];
|
|
66
|
+
if (values.length === 0)
|
|
67
|
+
return '1 = 1'; // Always true
|
|
68
|
+
const paramName = this.addParameter(values);
|
|
69
|
+
return `NOT ARRAY_CONTAINS(${paramName}, ${fieldPath})`;
|
|
70
|
+
}
|
|
71
|
+
// Ranges
|
|
72
|
+
case 'LessThan':
|
|
73
|
+
return `${fieldPath} < ${this.addParameter(value)}`;
|
|
74
|
+
case 'GreaterThan':
|
|
75
|
+
return `${fieldPath} > ${this.addParameter(value)}`;
|
|
76
|
+
// Strings
|
|
77
|
+
case 'Like':
|
|
78
|
+
// fallthrough
|
|
79
|
+
case 'ILike': {
|
|
80
|
+
const pattern = String(value).replace(/^%/, '').replace(/%$/, '');
|
|
81
|
+
const paramName = this.addParameter(pattern);
|
|
82
|
+
if (operator === 'ILike') {
|
|
83
|
+
return `CONTAINS(LOWER(${fieldPath}), LOWER(${paramName}))`;
|
|
84
|
+
}
|
|
85
|
+
return `CONTAINS(${fieldPath}, ${paramName})`;
|
|
86
|
+
}
|
|
87
|
+
case 'Contains': {
|
|
88
|
+
const paramName = this.addParameter(value);
|
|
89
|
+
return `CONTAINS(${fieldPath}, ${paramName})`;
|
|
90
|
+
}
|
|
91
|
+
case 'NotContains': {
|
|
92
|
+
const paramName = this.addParameter(value);
|
|
93
|
+
return `NOT CONTAINS(${fieldPath}, ${paramName})`;
|
|
94
|
+
}
|
|
95
|
+
case 'StartsWith': {
|
|
96
|
+
const paramName = this.addParameter(value);
|
|
97
|
+
return `STARTSWITH(${fieldPath}, ${paramName})`;
|
|
98
|
+
}
|
|
99
|
+
case 'EndsWith': {
|
|
100
|
+
const paramName = this.addParameter(value);
|
|
101
|
+
return `ENDSWITH(${fieldPath}, ${paramName})`;
|
|
102
|
+
}
|
|
103
|
+
// Array operations
|
|
104
|
+
case 'IncludesAll': {
|
|
105
|
+
const values = Array.isArray(value) ? value : [value];
|
|
106
|
+
const conditions = values.map(v => {
|
|
107
|
+
const paramName = this.addParameter(v);
|
|
108
|
+
return `ARRAY_CONTAINS(${fieldPath}, ${paramName})`;
|
|
109
|
+
});
|
|
110
|
+
return `(${conditions.join(' AND ')})`;
|
|
111
|
+
}
|
|
112
|
+
default:
|
|
113
|
+
throw new Error(`Unsupported operator: "${operator}".`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Recursively convert a condition tree to SQL WHERE clause
|
|
118
|
+
*/
|
|
119
|
+
getWhereClauseFromConditionTree(conditionTree) {
|
|
120
|
+
if (!conditionTree)
|
|
121
|
+
return '';
|
|
122
|
+
if (conditionTree.aggregator !== undefined) {
|
|
123
|
+
const { aggregator, conditions } = conditionTree;
|
|
124
|
+
if (aggregator === null) {
|
|
125
|
+
throw new Error('Invalid (null) aggregator.');
|
|
126
|
+
}
|
|
127
|
+
if (!Array.isArray(conditions) || conditions.length === 0) {
|
|
128
|
+
throw new Error('Conditions must be a non-empty array.');
|
|
129
|
+
}
|
|
130
|
+
const operator = aggregator === 'And' ? ' AND ' : ' OR ';
|
|
131
|
+
const clauses = conditions
|
|
132
|
+
.map(condition => this.getWhereClauseFromConditionTree(condition))
|
|
133
|
+
.filter(clause => clause !== '');
|
|
134
|
+
if (clauses.length === 0)
|
|
135
|
+
return '';
|
|
136
|
+
if (clauses.length === 1)
|
|
137
|
+
return clauses[0];
|
|
138
|
+
return `(${clauses.join(operator)})`;
|
|
139
|
+
}
|
|
140
|
+
if (conditionTree.operator !== undefined) {
|
|
141
|
+
const { field, operator, value } = conditionTree;
|
|
142
|
+
// Check for relation fields (not supported yet)
|
|
143
|
+
const isRelation = field.includes(':');
|
|
144
|
+
if (isRelation) {
|
|
145
|
+
throw new Error('Relation ConditionTree not yet supported for Cosmos DB.');
|
|
146
|
+
}
|
|
147
|
+
return this.makeWhereClause(field, operator, value);
|
|
148
|
+
}
|
|
149
|
+
throw new Error('Invalid ConditionTree.');
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Convert condition tree to a complete SQL query spec
|
|
153
|
+
*/
|
|
154
|
+
getSqlQuerySpec(conditionTree, sort, projection) {
|
|
155
|
+
// Reset state for new query
|
|
156
|
+
this.reset();
|
|
157
|
+
// Build SELECT clause
|
|
158
|
+
const selectClause = projection && projection.length > 0
|
|
159
|
+
? projection.map(field => (field === 'id' ? 'c.id' : `c.${field}`)).join(', ')
|
|
160
|
+
: 'c';
|
|
161
|
+
// Build WHERE clause
|
|
162
|
+
const whereClause = this.getWhereClauseFromConditionTree(conditionTree);
|
|
163
|
+
const whereFragment = whereClause ? `WHERE ${whereClause}` : '';
|
|
164
|
+
// Build ORDER BY clause
|
|
165
|
+
const orderByClause = this.getOrderByClause(sort);
|
|
166
|
+
const orderByFragment = orderByClause ? `ORDER BY ${orderByClause}` : '';
|
|
167
|
+
// Combine into full query
|
|
168
|
+
const query = `SELECT ${selectClause} FROM c ${whereFragment} ${orderByFragment}`.trim();
|
|
169
|
+
return {
|
|
170
|
+
query,
|
|
171
|
+
parameters: this.parameters,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Convert sort to ORDER BY clause
|
|
176
|
+
*/
|
|
177
|
+
getOrderByClause(sort) {
|
|
178
|
+
if (!sort || sort.length === 0)
|
|
179
|
+
return '';
|
|
180
|
+
const sortClauses = sort
|
|
181
|
+
.map(({ field, ascending }) => {
|
|
182
|
+
const fieldPath = field === 'id' ? 'c.id' : `c.${field}`;
|
|
183
|
+
const direction = ascending ? 'ASC' : 'DESC';
|
|
184
|
+
return `${fieldPath} ${direction}`;
|
|
185
|
+
})
|
|
186
|
+
.filter(Boolean);
|
|
187
|
+
return sortClauses.join(', ');
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get WHERE clause only (for use in subqueries or COUNT operations)
|
|
191
|
+
*/
|
|
192
|
+
getWhereClause(conditionTree) {
|
|
193
|
+
this.reset();
|
|
194
|
+
const where = this.getWhereClauseFromConditionTree(conditionTree);
|
|
195
|
+
return { where, parameters: this.parameters };
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.default = QueryConverter;
|
|
199
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktY29udmVydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3F1ZXJ5LWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLE1BQXFCLGNBQWM7SUFBbkM7UUFDVSxxQkFBZ0IsR0FBRyxDQUFDLENBQUM7UUFDckIsZUFBVSxHQUFtQixFQUFFLENBQUM7SUErUDFDLENBQUM7SUE3UEM7O09BRUc7SUFDSyxLQUFLO1FBQ1gsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSyxZQUFZLENBQUMsS0FBYztRQUNqQyxNQUFNLFNBQVMsR0FBRyxTQUFTLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLENBQUM7UUFDM0IsOERBQThEO1FBQzlELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBWSxFQUFFLENBQUMsQ0FBQztRQUUvRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxlQUFlLENBQUMsS0FBYSxFQUFFLFFBQWtCLEVBQUUsS0FBZTtRQUN4RSxrREFBa0Q7UUFDbEQsTUFBTSxTQUFTLEdBQUcsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssRUFBRSxDQUFDO1FBRXpELFFBQVEsUUFBUSxFQUFFLENBQUM7WUFDakIsV0FBVztZQUNYLEtBQUssU0FBUztnQkFDWixPQUFPLGNBQWMsU0FBUyxTQUFTLFNBQVMsVUFBVSxDQUFDO1lBRTdELEtBQUssU0FBUztnQkFDWixPQUFPLG1CQUFtQixTQUFTLFFBQVEsU0FBUyxVQUFVLENBQUM7WUFFakUsV0FB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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../../src/utils/serializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU;IAUhD,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAY/C"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class Serializer {
|
|
4
|
+
static serialize(record) {
|
|
5
|
+
Object.entries(record).forEach(([name, value]) => {
|
|
6
|
+
if (value instanceof Date)
|
|
7
|
+
record[name] = this.serializeValue(value);
|
|
8
|
+
if (Array.isArray(value))
|
|
9
|
+
this.serializeValue(value); // the change is by references
|
|
10
|
+
if (value instanceof Object)
|
|
11
|
+
return this.serialize(record[name]);
|
|
12
|
+
});
|
|
13
|
+
return record;
|
|
14
|
+
}
|
|
15
|
+
static serializeValue(value) {
|
|
16
|
+
if (value instanceof Date)
|
|
17
|
+
return value.toISOString();
|
|
18
|
+
if (Array.isArray(value)) {
|
|
19
|
+
value.forEach((v, i) => {
|
|
20
|
+
// serialize by reference to improve performances by avoiding the copies
|
|
21
|
+
if (value instanceof Date)
|
|
22
|
+
value[i] = v.toISOString();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = Serializer;
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9zZXJpYWxpemVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBRUEsTUFBcUIsVUFBVTtJQUM3QixNQUFNLENBQUMsU0FBUyxDQUFDLE1BQWtCO1FBQ2pDLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRTtZQUMvQyxJQUFJLEtBQUssWUFBWSxJQUFJO2dCQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7Z0JBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLDhCQUE4QjtZQUNwRixJQUFJLEtBQUssWUFBWSxNQUFNO2dCQUFFLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNuRSxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQWM7UUFDbEMsSUFBSSxLQUFLLFlBQVksSUFBSTtZQUFFLE9BQU8sS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRXRELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3JCLHdFQUF3RTtnQkFDeEUsSUFBSSxLQUFLLFlBQVksSUFBSTtvQkFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3hELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGO0FBdkJELDZCQXVCQyJ9
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ColumnType, Operator } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
/**
|
|
3
|
+
* Cosmos DB doesn't enforce strict types, but we can infer types from sample data
|
|
4
|
+
* and map them to Forest Admin types
|
|
5
|
+
*/
|
|
6
|
+
export type CosmosDataType = 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array' | 'null' | 'binary' | 'point';
|
|
7
|
+
export default class TypeConverter {
|
|
8
|
+
static fromDataType(dataType: CosmosDataType): ColumnType;
|
|
9
|
+
/**
|
|
10
|
+
* Map Cosmos DB data types to Forest Admin column types
|
|
11
|
+
* Since Cosmos DB is schemaless, these types are inferred from sample documents
|
|
12
|
+
*/
|
|
13
|
+
private static getColumnTypeFromDataType;
|
|
14
|
+
/**
|
|
15
|
+
* Infer Cosmos data type from a JavaScript value
|
|
16
|
+
*/
|
|
17
|
+
static inferTypeFromValue(value: unknown): CosmosDataType;
|
|
18
|
+
/**
|
|
19
|
+
* Check if a string is a valid ISO date
|
|
20
|
+
*/
|
|
21
|
+
private static isDateString;
|
|
22
|
+
/**
|
|
23
|
+
* Check if an object is a GeoJSON Point
|
|
24
|
+
*/
|
|
25
|
+
private static isGeoPoint;
|
|
26
|
+
/**
|
|
27
|
+
* All fields in Cosmos DB are sortable (no text analysis like Elasticsearch)
|
|
28
|
+
*/
|
|
29
|
+
static isSortable(dataType: CosmosDataType): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get supported operators for a given column type
|
|
32
|
+
*/
|
|
33
|
+
static operatorsForColumnType(columnType: ColumnType): Set<Operator>;
|
|
34
|
+
/**
|
|
35
|
+
* Operators supported for the id field
|
|
36
|
+
*/
|
|
37
|
+
static operatorsForId(): Set<Operator>;
|
|
38
|
+
/**
|
|
39
|
+
* Get the most specific common type from an array of types
|
|
40
|
+
*/
|
|
41
|
+
static getMostSpecificType(types: CosmosDataType[]): CosmosDataType;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=type-converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-converter.d.ts","sourceRoot":"","sources":["../../src/utils/type-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAkB,MAAM,iCAAiC,CAAC;AAEvF;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,GACP,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,CAAC,OAAO,OAAO,aAAa;WAClB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,UAAU;IAIhE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;IA8BxC;;OAEG;WACW,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc;IA4BhE;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAU3B;;OAEG;IAEH,OAAO,CAAC,MAAM,CAAC,UAAU;IAUzB;;OAEG;WACW,UAAU,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO;IAK3D;;OAEG;WACW,sBAAsB,CAAC,UAAU,EAAE,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC;IAiC3E;;OAEG;WACW,cAAc,IAAI,GAAG,CAAC,QAAQ,CAAC;IAI7C;;OAEG;WACW,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,cAAc;CAqB3E"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class TypeConverter {
|
|
4
|
+
static fromDataType(dataType) {
|
|
5
|
+
return TypeConverter.getColumnTypeFromDataType(dataType);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Map Cosmos DB data types to Forest Admin column types
|
|
9
|
+
* Since Cosmos DB is schemaless, these types are inferred from sample documents
|
|
10
|
+
*/
|
|
11
|
+
static getColumnTypeFromDataType(dataType) {
|
|
12
|
+
switch (dataType) {
|
|
13
|
+
case 'boolean':
|
|
14
|
+
return 'Boolean';
|
|
15
|
+
case 'date':
|
|
16
|
+
return 'Date';
|
|
17
|
+
case 'number':
|
|
18
|
+
return 'Number';
|
|
19
|
+
case 'string':
|
|
20
|
+
return 'String';
|
|
21
|
+
case 'binary':
|
|
22
|
+
return 'String'; // Base64 encoded strings
|
|
23
|
+
case 'point':
|
|
24
|
+
return 'Point'; // GeoJSON point
|
|
25
|
+
case 'object':
|
|
26
|
+
case 'array':
|
|
27
|
+
case 'null':
|
|
28
|
+
return 'Json';
|
|
29
|
+
default:
|
|
30
|
+
throw new Error(`Unsupported data type: "${dataType}"`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Infer Cosmos data type from a JavaScript value
|
|
35
|
+
*/
|
|
36
|
+
static inferTypeFromValue(value) {
|
|
37
|
+
if (value === null)
|
|
38
|
+
return 'null';
|
|
39
|
+
if (value === undefined)
|
|
40
|
+
return 'null';
|
|
41
|
+
if (typeof value === 'boolean')
|
|
42
|
+
return 'boolean';
|
|
43
|
+
if (typeof value === 'number')
|
|
44
|
+
return 'number';
|
|
45
|
+
if (typeof value === 'string') {
|
|
46
|
+
// Try to detect if it's a date string
|
|
47
|
+
if (this.isDateString(value))
|
|
48
|
+
return 'date';
|
|
49
|
+
return 'string';
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(value))
|
|
52
|
+
return 'array';
|
|
53
|
+
if (typeof value === 'object') {
|
|
54
|
+
// Check for GeoJSON Point
|
|
55
|
+
if (this.isGeoPoint(value))
|
|
56
|
+
return 'point';
|
|
57
|
+
// Check for Date object
|
|
58
|
+
if (value instanceof Date)
|
|
59
|
+
return 'date';
|
|
60
|
+
return 'object';
|
|
61
|
+
}
|
|
62
|
+
return 'string'; // Default fallback
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a string is a valid ISO date
|
|
66
|
+
*/
|
|
67
|
+
static isDateString(value) {
|
|
68
|
+
// Match ISO 8601 date format
|
|
69
|
+
const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$/;
|
|
70
|
+
if (!isoDateRegex.test(value))
|
|
71
|
+
return false;
|
|
72
|
+
const date = new Date(value);
|
|
73
|
+
return !Number.isNaN(date.getTime());
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if an object is a GeoJSON Point
|
|
77
|
+
*/
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
static isGeoPoint(value) {
|
|
80
|
+
return (value &&
|
|
81
|
+
typeof value === 'object' &&
|
|
82
|
+
value.type === 'Point' &&
|
|
83
|
+
Array.isArray(value.coordinates) &&
|
|
84
|
+
value.coordinates.length === 2);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* All fields in Cosmos DB are sortable (no text analysis like Elasticsearch)
|
|
88
|
+
*/
|
|
89
|
+
static isSortable(dataType) {
|
|
90
|
+
// Complex types cannot be sorted
|
|
91
|
+
return !['object', 'array'].includes(dataType);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get supported operators for a given column type
|
|
95
|
+
*/
|
|
96
|
+
static operatorsForColumnType(columnType) {
|
|
97
|
+
const result = ['Present', 'Missing'];
|
|
98
|
+
const equality = ['Equal', 'NotEqual', 'In', 'NotIn'];
|
|
99
|
+
if (typeof columnType === 'string') {
|
|
100
|
+
const orderables = ['LessThan', 'GreaterThan'];
|
|
101
|
+
const strings = ['Like', 'ILike', 'NotContains', 'Contains'];
|
|
102
|
+
if (['Boolean', 'Enum', 'Uuid'].includes(columnType)) {
|
|
103
|
+
result.push(...equality);
|
|
104
|
+
}
|
|
105
|
+
if (['Date', 'Dateonly', 'Number'].includes(columnType)) {
|
|
106
|
+
result.push(...equality, ...orderables);
|
|
107
|
+
}
|
|
108
|
+
if (['String'].includes(columnType)) {
|
|
109
|
+
result.push(...equality, ...orderables, ...strings);
|
|
110
|
+
}
|
|
111
|
+
if (['Point'].includes(columnType)) {
|
|
112
|
+
result.push(...equality);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Cosmos DB supports arrays natively
|
|
116
|
+
if (Array.isArray(columnType)) {
|
|
117
|
+
result.push('IncludesAll');
|
|
118
|
+
}
|
|
119
|
+
return new Set(result);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Operators supported for the id field
|
|
123
|
+
*/
|
|
124
|
+
static operatorsForId() {
|
|
125
|
+
return new Set(['Present', 'Missing', 'Equal', 'NotEqual', 'In', 'NotIn']);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the most specific common type from an array of types
|
|
129
|
+
*/
|
|
130
|
+
static getMostSpecificType(types) {
|
|
131
|
+
if (types.length === 0)
|
|
132
|
+
return 'null';
|
|
133
|
+
if (types.length === 1)
|
|
134
|
+
return types[0];
|
|
135
|
+
// If all types are the same, return that type
|
|
136
|
+
const uniqueTypes = [...new Set(types)];
|
|
137
|
+
if (uniqueTypes.length === 1)
|
|
138
|
+
return uniqueTypes[0];
|
|
139
|
+
// If we have mixed types, check for special cases
|
|
140
|
+
// number + null = number (nullable)
|
|
141
|
+
if (uniqueTypes.every(t => ['number', 'null'].includes(t)))
|
|
142
|
+
return 'number';
|
|
143
|
+
if (uniqueTypes.every(t => ['string', 'null'].includes(t)))
|
|
144
|
+
return 'string';
|
|
145
|
+
if (uniqueTypes.every(t => ['boolean', 'null'].includes(t)))
|
|
146
|
+
return 'boolean';
|
|
147
|
+
if (uniqueTypes.every(t => ['date', 'null'].includes(t)))
|
|
148
|
+
return 'date';
|
|
149
|
+
// Mixed numeric types -> number
|
|
150
|
+
if (uniqueTypes.every(t => ['number', 'null'].includes(t)))
|
|
151
|
+
return 'number';
|
|
152
|
+
// Otherwise, treat as object (Json)
|
|
153
|
+
return 'object';
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.default = TypeConverter;
|
|
157
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZS1jb252ZXJ0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvdHlwZS1jb252ZXJ0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFpQkEsTUFBcUIsYUFBYTtJQUN6QixNQUFNLENBQUMsWUFBWSxDQUFDLFFBQXdCO1FBQ2pELE9BQU8sYUFBYSxDQUFDLHlCQUF5QixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRDs7O09BR0c7SUFDSyxNQUFNLENBQUMseUJBQXlCLENBQUMsUUFBd0I7UUFDL0QsUUFBUSxRQUFRLEVBQUUsQ0FBQztZQUNqQixLQUFLLFNBQVM7Z0JBQ1osT0FBTyxTQUFTLENBQUM7WUFFbkIsS0FBSyxNQUFNO2dCQUNULE9BQU8sTUFBTSxDQUFDO1lBRWhCLEtBQUssUUFBUTtnQkFDWCxPQUFPLFFBQVEsQ0FBQztZQUVsQixLQUFLLFFBQVE7Z0JBQ1gsT0FBTyxRQUFRLENBQUM7WUFFbEIsS0FBSyxRQUFRO2dCQUNYLE9BQU8sUUFBUSxDQUFDLENBQUMseUJBQXlCO1lBRTVDLEtBQUssT0FBTztnQkFDVixPQUFPLE9BQU8sQ0FBQyxDQUFDLGdCQUFnQjtZQUVsQyxLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssT0FBTyxDQUFDO1lBQ2IsS0FBSyxNQUFNO2dCQUNULE9BQU8sTUFBTSxDQUFDO1lBRWhCO2dCQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDNUQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxLQUFjO1FBQzdDLElBQUksS0FBSyxLQUFLLElBQUk7WUFBRSxPQUFPLE1BQU0sQ0FBQztRQUNsQyxJQUFJLEtBQUssS0FBSyxTQUFTO1lBQUUsT0FBTyxNQUFNLENBQUM7UUFFdkMsSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTO1lBQUUsT0FBTyxTQUFTLENBQUM7UUFD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
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forestadmin-experimental/datasource-cosmos",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"license": "GPL-3.0",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/ForestAdmin/forestadmin-experimental.git",
|
|
12
|
+
"directory": "packages/datasource-cosmos"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/**/*.js",
|
|
16
|
+
"dist/**/*.d.ts",
|
|
17
|
+
"dist/**/*.d.ts.map",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"build:watch": "tsc --watch",
|
|
23
|
+
"clean": "rm -rf coverage dist",
|
|
24
|
+
"lint": "eslint src test",
|
|
25
|
+
"test": "docker compose up -d; sleep 10 && jest",
|
|
26
|
+
"publish:package": "semantic-release"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@forestadmin/datasource-toolkit": "^1.45.0",
|
|
30
|
+
"@azure/cosmos": "^4.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@forestadmin/datasource-toolkit": "^1.45.0",
|
|
34
|
+
"@azure/cosmos": "^4.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|