@webda/ql 4.0.0-beta.6 → 4.0.0-beta.8
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 +42 -4
- package/lib/WebdaQLLexer.d.ts +10 -9
- package/lib/WebdaQLLexer.d.ts.map +1 -1
- package/lib/WebdaQLLexer.js +227 -363
- package/lib/WebdaQLLexer.js.map +1 -1
- package/lib/WebdaQLParserLexer.d.ts +10 -9
- package/lib/WebdaQLParserLexer.d.ts.map +1 -1
- package/lib/WebdaQLParserLexer.js +227 -363
- package/lib/WebdaQLParserLexer.js.map +1 -1
- package/lib/WebdaQLParserListener.d.ts +26 -2
- package/lib/WebdaQLParserListener.d.ts.map +1 -1
- package/lib/WebdaQLParserParser.d.ts +34 -9
- package/lib/WebdaQLParserParser.d.ts.map +1 -1
- package/lib/WebdaQLParserParser.js +585 -732
- package/lib/WebdaQLParserParser.js.map +1 -1
- package/lib/WebdaQLParserVisitor.d.ts +16 -1
- package/lib/WebdaQLParserVisitor.d.ts.map +1 -1
- package/lib/aggregation-select.spec.js +4 -3
- package/lib/aggregation-select.spec.js.map +1 -1
- package/lib/completion.d.ts +84 -0
- package/lib/completion.d.ts.map +1 -0
- package/lib/completion.js +467 -0
- package/lib/completion.js.map +1 -0
- package/lib/completion.spec.d.ts +25 -0
- package/lib/completion.spec.d.ts.map +1 -0
- package/lib/completion.spec.js +409 -0
- package/lib/completion.spec.js.map +1 -0
- package/lib/filter.d.ts +54 -0
- package/lib/filter.d.ts.map +1 -0
- package/lib/filter.js +135 -0
- package/lib/filter.js.map +1 -0
- package/lib/filter.spec.d.ts +2 -0
- package/lib/filter.spec.d.ts.map +1 -0
- package/lib/filter.spec.js +124 -0
- package/lib/filter.spec.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/now.spec.d.ts +2 -0
- package/lib/now.spec.d.ts.map +1 -0
- package/lib/now.spec.js +258 -0
- package/lib/now.spec.js.map +1 -0
- package/lib/query.d.ts +134 -8
- package/lib/query.d.ts.map +1 -1
- package/lib/query.js +314 -39
- package/lib/query.js.map +1 -1
- package/lib/query.spec.js +1 -0
- package/lib/query.spec.js.map +1 -1
- package/lib/statements.spec.js +1 -0
- package/lib/statements.spec.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { suite, test } from "@webda/test";
|
|
36
|
+
import * as assert from "assert";
|
|
37
|
+
import { getCompletions, fieldsFromSchema } from "./completion.js";
|
|
38
|
+
const TEST_FIELDS = [
|
|
39
|
+
{ name: "status", type: "string", enum: ["open", "closed"] },
|
|
40
|
+
{ name: "priority", type: "integer" },
|
|
41
|
+
{ name: "done", type: "boolean" },
|
|
42
|
+
{ name: "profile.email", type: "string" }
|
|
43
|
+
];
|
|
44
|
+
/**
|
|
45
|
+
* Helper that takes a query string containing '|' as caret marker,
|
|
46
|
+
* runs getCompletions, and returns the result.
|
|
47
|
+
*/
|
|
48
|
+
function complete(markedQuery, options = { fields: TEST_FIELDS }) {
|
|
49
|
+
const caret = markedQuery.indexOf("|");
|
|
50
|
+
if (caret === -1) {
|
|
51
|
+
throw new Error(`Test query must contain '|' to mark caret: "${markedQuery}"`);
|
|
52
|
+
}
|
|
53
|
+
const cleanQuery = markedQuery.slice(0, caret) + markedQuery.slice(caret + 1);
|
|
54
|
+
return getCompletions(cleanQuery, caret, options);
|
|
55
|
+
}
|
|
56
|
+
let CompletionTest = (() => {
|
|
57
|
+
let _classDecorators = [suite];
|
|
58
|
+
let _classDescriptor;
|
|
59
|
+
let _classExtraInitializers = [];
|
|
60
|
+
let _classThis;
|
|
61
|
+
let _instanceExtraInitializers = [];
|
|
62
|
+
let _caretAtStart_decorators;
|
|
63
|
+
let _partialIdentifier_decorators;
|
|
64
|
+
let _afterIdentifier_decorators;
|
|
65
|
+
let _afterComparisonOnEnumField_decorators;
|
|
66
|
+
let _afterComparisonOnBooleanField_decorators;
|
|
67
|
+
let _afterCompleteComparison_decorators;
|
|
68
|
+
let _afterCompleteComparisonWithPrefix_decorators;
|
|
69
|
+
let _afterOrderByField_decorators;
|
|
70
|
+
let _afterSelect_decorators;
|
|
71
|
+
let _afterSelectCountStar_decorators;
|
|
72
|
+
let _afterUpdate_decorators;
|
|
73
|
+
let _afterUpdateSet_decorators;
|
|
74
|
+
let _dottedPathPrefix_decorators;
|
|
75
|
+
let _insideStringLiteral_decorators;
|
|
76
|
+
let _insideUnclosedStringLiteral_decorators;
|
|
77
|
+
let _afterLimit_decorators;
|
|
78
|
+
let _syntaxErrorAndCaretBoundsNoThrow_decorators;
|
|
79
|
+
let _noFieldsOption_decorators;
|
|
80
|
+
let _namedParameters_decorators;
|
|
81
|
+
let _candidateLimit_decorators;
|
|
82
|
+
let _fieldsFromSchema_decorators;
|
|
83
|
+
let _performanceCheck_decorators;
|
|
84
|
+
var CompletionTest = class {
|
|
85
|
+
static { _classThis = this; }
|
|
86
|
+
static {
|
|
87
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
88
|
+
_caretAtStart_decorators = [test];
|
|
89
|
+
_partialIdentifier_decorators = [test];
|
|
90
|
+
_afterIdentifier_decorators = [test];
|
|
91
|
+
_afterComparisonOnEnumField_decorators = [test];
|
|
92
|
+
_afterComparisonOnBooleanField_decorators = [test];
|
|
93
|
+
_afterCompleteComparison_decorators = [test];
|
|
94
|
+
_afterCompleteComparisonWithPrefix_decorators = [test];
|
|
95
|
+
_afterOrderByField_decorators = [test];
|
|
96
|
+
_afterSelect_decorators = [test];
|
|
97
|
+
_afterSelectCountStar_decorators = [test];
|
|
98
|
+
_afterUpdate_decorators = [test];
|
|
99
|
+
_afterUpdateSet_decorators = [test];
|
|
100
|
+
_dottedPathPrefix_decorators = [test];
|
|
101
|
+
_insideStringLiteral_decorators = [test];
|
|
102
|
+
_insideUnclosedStringLiteral_decorators = [test];
|
|
103
|
+
_afterLimit_decorators = [test];
|
|
104
|
+
_syntaxErrorAndCaretBoundsNoThrow_decorators = [test];
|
|
105
|
+
_noFieldsOption_decorators = [test];
|
|
106
|
+
_namedParameters_decorators = [test];
|
|
107
|
+
_candidateLimit_decorators = [test];
|
|
108
|
+
_fieldsFromSchema_decorators = [test];
|
|
109
|
+
_performanceCheck_decorators = [test];
|
|
110
|
+
__esDecorate(this, null, _caretAtStart_decorators, { kind: "method", name: "caretAtStart", static: false, private: false, access: { has: obj => "caretAtStart" in obj, get: obj => obj.caretAtStart }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
111
|
+
__esDecorate(this, null, _partialIdentifier_decorators, { kind: "method", name: "partialIdentifier", static: false, private: false, access: { has: obj => "partialIdentifier" in obj, get: obj => obj.partialIdentifier }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
112
|
+
__esDecorate(this, null, _afterIdentifier_decorators, { kind: "method", name: "afterIdentifier", static: false, private: false, access: { has: obj => "afterIdentifier" in obj, get: obj => obj.afterIdentifier }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
113
|
+
__esDecorate(this, null, _afterComparisonOnEnumField_decorators, { kind: "method", name: "afterComparisonOnEnumField", static: false, private: false, access: { has: obj => "afterComparisonOnEnumField" in obj, get: obj => obj.afterComparisonOnEnumField }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
114
|
+
__esDecorate(this, null, _afterComparisonOnBooleanField_decorators, { kind: "method", name: "afterComparisonOnBooleanField", static: false, private: false, access: { has: obj => "afterComparisonOnBooleanField" in obj, get: obj => obj.afterComparisonOnBooleanField }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
115
|
+
__esDecorate(this, null, _afterCompleteComparison_decorators, { kind: "method", name: "afterCompleteComparison", static: false, private: false, access: { has: obj => "afterCompleteComparison" in obj, get: obj => obj.afterCompleteComparison }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
116
|
+
__esDecorate(this, null, _afterCompleteComparisonWithPrefix_decorators, { kind: "method", name: "afterCompleteComparisonWithPrefix", static: false, private: false, access: { has: obj => "afterCompleteComparisonWithPrefix" in obj, get: obj => obj.afterCompleteComparisonWithPrefix }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
117
|
+
__esDecorate(this, null, _afterOrderByField_decorators, { kind: "method", name: "afterOrderByField", static: false, private: false, access: { has: obj => "afterOrderByField" in obj, get: obj => obj.afterOrderByField }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
118
|
+
__esDecorate(this, null, _afterSelect_decorators, { kind: "method", name: "afterSelect", static: false, private: false, access: { has: obj => "afterSelect" in obj, get: obj => obj.afterSelect }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
119
|
+
__esDecorate(this, null, _afterSelectCountStar_decorators, { kind: "method", name: "afterSelectCountStar", static: false, private: false, access: { has: obj => "afterSelectCountStar" in obj, get: obj => obj.afterSelectCountStar }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
120
|
+
__esDecorate(this, null, _afterUpdate_decorators, { kind: "method", name: "afterUpdate", static: false, private: false, access: { has: obj => "afterUpdate" in obj, get: obj => obj.afterUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
121
|
+
__esDecorate(this, null, _afterUpdateSet_decorators, { kind: "method", name: "afterUpdateSet", static: false, private: false, access: { has: obj => "afterUpdateSet" in obj, get: obj => obj.afterUpdateSet }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
122
|
+
__esDecorate(this, null, _dottedPathPrefix_decorators, { kind: "method", name: "dottedPathPrefix", static: false, private: false, access: { has: obj => "dottedPathPrefix" in obj, get: obj => obj.dottedPathPrefix }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
123
|
+
__esDecorate(this, null, _insideStringLiteral_decorators, { kind: "method", name: "insideStringLiteral", static: false, private: false, access: { has: obj => "insideStringLiteral" in obj, get: obj => obj.insideStringLiteral }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
124
|
+
__esDecorate(this, null, _insideUnclosedStringLiteral_decorators, { kind: "method", name: "insideUnclosedStringLiteral", static: false, private: false, access: { has: obj => "insideUnclosedStringLiteral" in obj, get: obj => obj.insideUnclosedStringLiteral }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
125
|
+
__esDecorate(this, null, _afterLimit_decorators, { kind: "method", name: "afterLimit", static: false, private: false, access: { has: obj => "afterLimit" in obj, get: obj => obj.afterLimit }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
126
|
+
__esDecorate(this, null, _syntaxErrorAndCaretBoundsNoThrow_decorators, { kind: "method", name: "syntaxErrorAndCaretBoundsNoThrow", static: false, private: false, access: { has: obj => "syntaxErrorAndCaretBoundsNoThrow" in obj, get: obj => obj.syntaxErrorAndCaretBoundsNoThrow }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
127
|
+
__esDecorate(this, null, _noFieldsOption_decorators, { kind: "method", name: "noFieldsOption", static: false, private: false, access: { has: obj => "noFieldsOption" in obj, get: obj => obj.noFieldsOption }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
128
|
+
__esDecorate(this, null, _namedParameters_decorators, { kind: "method", name: "namedParameters", static: false, private: false, access: { has: obj => "namedParameters" in obj, get: obj => obj.namedParameters }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
129
|
+
__esDecorate(this, null, _candidateLimit_decorators, { kind: "method", name: "candidateLimit", static: false, private: false, access: { has: obj => "candidateLimit" in obj, get: obj => obj.candidateLimit }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
130
|
+
__esDecorate(this, null, _fieldsFromSchema_decorators, { kind: "method", name: "fieldsFromSchema", static: false, private: false, access: { has: obj => "fieldsFromSchema" in obj, get: obj => obj.fieldsFromSchema }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
131
|
+
__esDecorate(this, null, _performanceCheck_decorators, { kind: "method", name: "performanceCheck", static: false, private: false, access: { has: obj => "performanceCheck" in obj, get: obj => obj.performanceCheck }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
132
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
133
|
+
CompletionTest = _classThis = _classDescriptor.value;
|
|
134
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
135
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
136
|
+
}
|
|
137
|
+
caretAtStart() {
|
|
138
|
+
// "|" -> fields, SELECT, DELETE, UPDATE, ORDER BY, LIMIT
|
|
139
|
+
const res = complete("|");
|
|
140
|
+
const labels = res.items.map(i => i.label);
|
|
141
|
+
assert.ok(labels.includes("status"), "Should include status field");
|
|
142
|
+
assert.ok(labels.includes("priority"), "Should include priority field");
|
|
143
|
+
assert.ok(labels.includes("done"), "Should include done field");
|
|
144
|
+
assert.ok(labels.includes("profile.email"), "Should include profile.email field");
|
|
145
|
+
assert.ok(labels.includes("SELECT"), "Should include SELECT");
|
|
146
|
+
assert.ok(labels.includes("DELETE"), "Should include DELETE");
|
|
147
|
+
assert.ok(labels.includes("UPDATE"), "Should include UPDATE");
|
|
148
|
+
assert.ok(labels.includes("ORDER BY"), "Should include ORDER BY");
|
|
149
|
+
assert.ok(labels.includes("LIMIT"), "Should include LIMIT");
|
|
150
|
+
// with filterOnly: no SELECT/DELETE/UPDATE
|
|
151
|
+
const filterRes = complete("|", { fields: TEST_FIELDS, filterOnly: true });
|
|
152
|
+
const filterLabels = filterRes.items.map(i => i.label);
|
|
153
|
+
assert.ok(!filterLabels.includes("SELECT"), "filterOnly should exclude SELECT");
|
|
154
|
+
assert.ok(!filterLabels.includes("DELETE"), "filterOnly should exclude DELETE");
|
|
155
|
+
assert.ok(!filterLabels.includes("UPDATE"), "filterOnly should exclude UPDATE");
|
|
156
|
+
assert.ok(filterLabels.includes("status"), "filterOnly should still include fields");
|
|
157
|
+
assert.ok(filterLabels.includes("ORDER BY"), "filterOnly should still include ORDER BY");
|
|
158
|
+
assert.ok(filterLabels.includes("LIMIT"), "filterOnly should still include LIMIT");
|
|
159
|
+
}
|
|
160
|
+
partialIdentifier() {
|
|
161
|
+
// "sta|" -> status with range [0,3]
|
|
162
|
+
const res = complete("sta|");
|
|
163
|
+
assert.strictEqual(res.prefix, "sta");
|
|
164
|
+
const statusItem = res.items.find(i => i.label === "status");
|
|
165
|
+
assert.ok(statusItem, "Should offer status");
|
|
166
|
+
assert.deepStrictEqual(statusItem.range, [0, 3]);
|
|
167
|
+
assert.strictEqual(statusItem.kind, "field");
|
|
168
|
+
}
|
|
169
|
+
afterIdentifier() {
|
|
170
|
+
// "status |" -> =, !=, IN, LIKE, CONTAINS, IS NULL, IS NOT NULL; no fields
|
|
171
|
+
const res = complete("status |");
|
|
172
|
+
const labels = res.items.map(i => i.label);
|
|
173
|
+
assert.ok(labels.includes("="), "Should include =");
|
|
174
|
+
assert.ok(labels.includes("!="), "Should include !=");
|
|
175
|
+
assert.ok(labels.includes("IN"), "Should include IN");
|
|
176
|
+
assert.ok(labels.includes("LIKE"), "Should include LIKE");
|
|
177
|
+
assert.ok(labels.includes("CONTAINS"), "Should include CONTAINS");
|
|
178
|
+
assert.ok(labels.includes("IS NULL"), "Should include IS NULL");
|
|
179
|
+
assert.ok(labels.includes("IS NOT NULL"), "Should include IS NOT NULL");
|
|
180
|
+
// no fields
|
|
181
|
+
assert.ok(!labels.includes("status"), "Should not include status field");
|
|
182
|
+
assert.ok(!labels.includes("priority"), "Should not include priority field");
|
|
183
|
+
assert.ok(!labels.includes("done"), "Should not include done field");
|
|
184
|
+
}
|
|
185
|
+
afterComparisonOnEnumField() {
|
|
186
|
+
// "status = |" -> 'open', 'closed', ?; no TRUE
|
|
187
|
+
const res = complete("status = |");
|
|
188
|
+
const labels = res.items.map(i => i.label);
|
|
189
|
+
assert.ok(labels.includes("'open'"), "Should include 'open'");
|
|
190
|
+
assert.ok(labels.includes("'closed'"), "Should include 'closed'");
|
|
191
|
+
assert.ok(labels.includes("?"), "Should include ?");
|
|
192
|
+
assert.ok(!labels.includes("TRUE"), "Should NOT include TRUE");
|
|
193
|
+
assert.ok(!labels.includes("FALSE"), "Should NOT include FALSE");
|
|
194
|
+
}
|
|
195
|
+
afterComparisonOnBooleanField() {
|
|
196
|
+
// "done = |" -> TRUE, FALSE
|
|
197
|
+
const res = complete("done = |");
|
|
198
|
+
const labels = res.items.map(i => i.label);
|
|
199
|
+
assert.ok(labels.includes("TRUE"), "Should include TRUE");
|
|
200
|
+
assert.ok(labels.includes("FALSE"), "Should include FALSE");
|
|
201
|
+
}
|
|
202
|
+
afterCompleteComparison() {
|
|
203
|
+
// "status = 'open' |" -> AND, OR, ORDER BY, LIMIT, OFFSET
|
|
204
|
+
const res = complete("status = 'open' |");
|
|
205
|
+
const labels = res.items.map(i => i.label);
|
|
206
|
+
assert.ok(labels.includes("AND"), "Should include AND");
|
|
207
|
+
assert.ok(labels.includes("OR"), "Should include OR");
|
|
208
|
+
assert.ok(labels.includes("ORDER BY"), "Should include ORDER BY");
|
|
209
|
+
assert.ok(labels.includes("LIMIT"), "Should include LIMIT");
|
|
210
|
+
assert.ok(labels.includes("OFFSET"), "Should include OFFSET");
|
|
211
|
+
}
|
|
212
|
+
afterCompleteComparisonWithPrefix() {
|
|
213
|
+
// "status = 'open' ord|" -> ORDER BY
|
|
214
|
+
const res = complete("status = 'open' ord|");
|
|
215
|
+
const labels = res.items.map(i => i.label);
|
|
216
|
+
assert.strictEqual(res.prefix, "ord");
|
|
217
|
+
assert.ok(labels.includes("ORDER BY"), "Should include ORDER BY");
|
|
218
|
+
assert.ok(!labels.includes("AND"), "Should not include AND");
|
|
219
|
+
}
|
|
220
|
+
afterOrderByField() {
|
|
221
|
+
// "ORDER BY priority |" -> ASC, DESC, ,, LIMIT
|
|
222
|
+
const res = complete("ORDER BY priority |");
|
|
223
|
+
const labels = res.items.map(i => i.label);
|
|
224
|
+
assert.ok(labels.includes("ASC"), "Should include ASC");
|
|
225
|
+
assert.ok(labels.includes("DESC"), "Should include DESC");
|
|
226
|
+
assert.ok(labels.includes(","), "Should include ,");
|
|
227
|
+
assert.ok(labels.includes("LIMIT"), "Should include LIMIT");
|
|
228
|
+
}
|
|
229
|
+
afterSelect() {
|
|
230
|
+
// "SELECT |" -> fields, COUNT, SUM, AVG, MIN, MAX
|
|
231
|
+
const res = complete("SELECT |");
|
|
232
|
+
const labels = res.items.map(i => i.label);
|
|
233
|
+
assert.ok(labels.includes("status"), "Should include status");
|
|
234
|
+
assert.ok(labels.includes("priority"), "Should include priority");
|
|
235
|
+
assert.ok(labels.includes("COUNT"), "Should include COUNT");
|
|
236
|
+
assert.ok(labels.includes("SUM"), "Should include SUM");
|
|
237
|
+
assert.ok(labels.includes("AVG"), "Should include AVG");
|
|
238
|
+
assert.ok(labels.includes("MIN"), "Should include MIN");
|
|
239
|
+
assert.ok(labels.includes("MAX"), "Should include MAX");
|
|
240
|
+
}
|
|
241
|
+
afterSelectCountStar() {
|
|
242
|
+
// "SELECT COUNT(*) |" -> AS
|
|
243
|
+
const res = complete("SELECT COUNT(*) |");
|
|
244
|
+
const labels = res.items.map(i => i.label);
|
|
245
|
+
assert.ok(labels.includes("AS"), "Should include AS");
|
|
246
|
+
}
|
|
247
|
+
afterUpdate() {
|
|
248
|
+
// "UPDATE |" -> SET only
|
|
249
|
+
const res = complete("UPDATE |");
|
|
250
|
+
const labels = res.items.map(i => i.label);
|
|
251
|
+
assert.deepStrictEqual(labels, ["SET"]);
|
|
252
|
+
}
|
|
253
|
+
afterUpdateSet() {
|
|
254
|
+
// "UPDATE SET |" -> fields
|
|
255
|
+
const res = complete("UPDATE SET |");
|
|
256
|
+
const labels = res.items.map(i => i.label);
|
|
257
|
+
assert.ok(labels.includes("status"), "Should include status");
|
|
258
|
+
assert.ok(labels.includes("priority"), "Should include priority");
|
|
259
|
+
assert.ok(labels.includes("done"), "Should include done");
|
|
260
|
+
assert.ok(labels.includes("profile.email"), "Should include profile.email");
|
|
261
|
+
}
|
|
262
|
+
dottedPathPrefix() {
|
|
263
|
+
// "profile.|" -> profile.email only, range covers profile.
|
|
264
|
+
const res = complete("profile.|");
|
|
265
|
+
const labels = res.items.map(i => i.label);
|
|
266
|
+
assert.deepStrictEqual(labels, ["profile.email"]);
|
|
267
|
+
assert.strictEqual(res.prefix, "profile.");
|
|
268
|
+
assert.deepStrictEqual(res.items[0].range, [0, 8]);
|
|
269
|
+
}
|
|
270
|
+
insideStringLiteral() {
|
|
271
|
+
// "status = 'op|'" -> 'open' (inside a string)
|
|
272
|
+
const res = complete("status = 'op|'");
|
|
273
|
+
const labels = res.items.map(i => i.label);
|
|
274
|
+
assert.deepStrictEqual(labels, ["'open'"]);
|
|
275
|
+
assert.strictEqual(res.prefix, "op");
|
|
276
|
+
assert.deepStrictEqual(res.items[0].range, [9, 13]);
|
|
277
|
+
}
|
|
278
|
+
insideUnclosedStringLiteral() {
|
|
279
|
+
const res = complete("status = 'op|");
|
|
280
|
+
const labels = res.items.map(i => i.label);
|
|
281
|
+
assert.deepStrictEqual(labels, ["'open'"]);
|
|
282
|
+
assert.strictEqual(res.prefix, "op");
|
|
283
|
+
}
|
|
284
|
+
afterLimit() {
|
|
285
|
+
// "LIMIT |" -> ? (no fields)
|
|
286
|
+
const res = complete("LIMIT |");
|
|
287
|
+
const labels = res.items.map(i => i.label);
|
|
288
|
+
assert.ok(labels.includes("?"), "Should include ?");
|
|
289
|
+
assert.ok(!labels.includes("status"), "Should not include fields");
|
|
290
|
+
assert.ok(!labels.includes("priority"), "Should not include fields");
|
|
291
|
+
}
|
|
292
|
+
syntaxErrorAndCaretBoundsNoThrow() {
|
|
293
|
+
// "x = #|", caret -1, caret 999 -> no throw
|
|
294
|
+
assert.doesNotThrow(() => complete("x = #|"));
|
|
295
|
+
assert.doesNotThrow(() => {
|
|
296
|
+
const res = getCompletions("status =", -1, { fields: TEST_FIELDS });
|
|
297
|
+
assert.ok(Array.isArray(res.items));
|
|
298
|
+
});
|
|
299
|
+
assert.doesNotThrow(() => {
|
|
300
|
+
const res = getCompletions("status =", 999, { fields: TEST_FIELDS });
|
|
301
|
+
assert.ok(Array.isArray(res.items));
|
|
302
|
+
});
|
|
303
|
+
assert.doesNotThrow(() => {
|
|
304
|
+
const res = getCompletions(null, 0);
|
|
305
|
+
assert.deepStrictEqual(res, { items: [], prefix: "" });
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
noFieldsOption() {
|
|
309
|
+
// no fields option -> no field items, keywords still offered
|
|
310
|
+
const res = complete("sta|", { fields: undefined });
|
|
311
|
+
assert.strictEqual(res.items.filter(i => i.kind === "field").length, 0);
|
|
312
|
+
const emptyRes = complete("|", { fields: undefined });
|
|
313
|
+
const labels = emptyRes.items.map(i => i.label);
|
|
314
|
+
assert.ok(labels.includes("SELECT"), "Keywords still offered when fields undefined");
|
|
315
|
+
assert.ok(labels.includes("ORDER BY"), "Keywords still offered when fields undefined");
|
|
316
|
+
}
|
|
317
|
+
namedParameters() {
|
|
318
|
+
const res = complete("status = |", {
|
|
319
|
+
fields: TEST_FIELDS,
|
|
320
|
+
parameters: ["myStatus", ":other"]
|
|
321
|
+
});
|
|
322
|
+
const labels = res.items.map(i => i.label);
|
|
323
|
+
assert.ok(labels.includes(":myStatus"));
|
|
324
|
+
assert.ok(labels.includes(":other"));
|
|
325
|
+
assert.ok(labels.includes("?"));
|
|
326
|
+
}
|
|
327
|
+
candidateLimit() {
|
|
328
|
+
const res = complete("|", { fields: TEST_FIELDS, limit: 3 });
|
|
329
|
+
assert.strictEqual(res.items.length, 3);
|
|
330
|
+
}
|
|
331
|
+
fieldsFromSchema() {
|
|
332
|
+
const schema = {
|
|
333
|
+
type: "object",
|
|
334
|
+
properties: {
|
|
335
|
+
title: { type: "string", description: "Post title" },
|
|
336
|
+
status: { type: "string", enum: ["draft", "published"], description: "Post status" },
|
|
337
|
+
count: { type: "integer" },
|
|
338
|
+
active: { type: "boolean" },
|
|
339
|
+
author: {
|
|
340
|
+
type: "object",
|
|
341
|
+
description: "Author info",
|
|
342
|
+
properties: {
|
|
343
|
+
name: { type: "string" },
|
|
344
|
+
contact: {
|
|
345
|
+
type: "object",
|
|
346
|
+
properties: {
|
|
347
|
+
email: { type: "string" },
|
|
348
|
+
deep: {
|
|
349
|
+
type: "object",
|
|
350
|
+
properties: {
|
|
351
|
+
level4: { type: "string" }
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
ignoredRef: {
|
|
359
|
+
$ref: "#/definitions/SomeType"
|
|
360
|
+
},
|
|
361
|
+
booleanTrueProp: true,
|
|
362
|
+
booleanFalseProp: false
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
const fields = fieldsFromSchema(schema);
|
|
366
|
+
const names = fields.map(f => f.name);
|
|
367
|
+
assert.ok(names.includes("title"), "Should include title");
|
|
368
|
+
assert.ok(names.includes("status"), "Should include status");
|
|
369
|
+
assert.ok(names.includes("count"), "Should include count");
|
|
370
|
+
assert.ok(names.includes("active"), "Should include active");
|
|
371
|
+
assert.ok(names.includes("author.name"), "Should include author.name");
|
|
372
|
+
assert.ok(names.includes("author.contact.email"), "Should include author.contact.email");
|
|
373
|
+
assert.ok(names.includes("booleanTrueProp"), "Should include boolean true property");
|
|
374
|
+
assert.ok(!names.includes("booleanFalseProp"), "Should exclude boolean false property");
|
|
375
|
+
assert.ok(!names.includes("ignoredRef"), "Should skip $ref property");
|
|
376
|
+
// Check depth limit (maxDepth = 3: author(1) -> contact(2) -> deep(3), level4 is at depth 4)
|
|
377
|
+
assert.ok(names.includes("author.contact.deep"), "Deep object should be included as object at depth limit");
|
|
378
|
+
assert.ok(!names.includes("author.contact.deep.level4"), "Should not recurse past maxDepth 3");
|
|
379
|
+
// Check enum/type/description copied
|
|
380
|
+
const statusField = fields.find(f => f.name === "status");
|
|
381
|
+
assert.deepStrictEqual(statusField?.enum, ["draft", "published"]);
|
|
382
|
+
assert.strictEqual(statusField?.type, "string");
|
|
383
|
+
assert.strictEqual(statusField?.description, "Post status");
|
|
384
|
+
// Empty or non-object schema
|
|
385
|
+
assert.deepStrictEqual(fieldsFromSchema({}), []);
|
|
386
|
+
assert.deepStrictEqual(fieldsFromSchema(null), []);
|
|
387
|
+
}
|
|
388
|
+
performanceCheck() {
|
|
389
|
+
const query = "SELECT title, content, author, createdAt WHERE status = 'published' AND priority > 10 AND done = TRUE AND category IN ['tech', 'news'] ORDER BY createdAt DESC LIMIT 20 OFFSET 'token123'";
|
|
390
|
+
assert.ok(query.length >= 180, "Query should be around 200 characters");
|
|
391
|
+
const start = Date.now();
|
|
392
|
+
for (let i = 0; i < 1000; i++) {
|
|
393
|
+
getCompletions(query, 50, { fields: TEST_FIELDS });
|
|
394
|
+
}
|
|
395
|
+
const elapsed = Date.now() - start;
|
|
396
|
+
console.log(`1,000 getCompletions calls completed in ${elapsed}ms`);
|
|
397
|
+
if (elapsed > 1000) {
|
|
398
|
+
console.warn(`Performance warning: 1000 calls took ${elapsed}ms (target <1000ms)`);
|
|
399
|
+
}
|
|
400
|
+
assert.ok(elapsed < 5000, `Expected 1000 calls to complete within reasonable time, took ${elapsed}ms`);
|
|
401
|
+
}
|
|
402
|
+
constructor() {
|
|
403
|
+
__runInitializers(this, _instanceExtraInitializers);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
return CompletionTest = _classThis;
|
|
407
|
+
})();
|
|
408
|
+
export { CompletionTest };
|
|
409
|
+
//# sourceMappingURL=completion.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion.spec.js","sourceRoot":"","sources":["../src/completion.spec.ts"],"names":[],"mappings":"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"}
|
package/lib/filter.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Expression } from "./query.js";
|
|
2
|
+
import type { WebdaQLString } from "./webdaql-string.js";
|
|
3
|
+
type Primitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
4
|
+
type PropertyPaths<T extends object> = {
|
|
5
|
+
[K in Extract<keyof T, string>]: T[K] extends Function ? never : NonNullable<T[K]> extends Primitive | Date | RegExp | Array<any> | Map<any, any> | Set<any> ? K : NonNullable<T[K]> extends object ? K | `${K}.${PropertyPaths<NonNullable<T[K]>>}` : K;
|
|
6
|
+
}[Extract<keyof T, string>];
|
|
7
|
+
type PathValue<T, K extends string> = K extends `${infer H}.${infer R}` ? H extends keyof T ? PathValue<NonNullable<T[H]>, R> : never : K extends keyof T ? T[K] : never;
|
|
8
|
+
type PropertyPathType<T extends object, K extends PropertyPaths<T>> = PathValue<T, K>;
|
|
9
|
+
export type FilterOperators<V> = {
|
|
10
|
+
$eq?: V | null;
|
|
11
|
+
$ne?: V | null;
|
|
12
|
+
$gt?: V;
|
|
13
|
+
$gte?: V;
|
|
14
|
+
$lt?: V;
|
|
15
|
+
$lte?: V;
|
|
16
|
+
$in?: V[];
|
|
17
|
+
$like?: string;
|
|
18
|
+
$contains?: V extends readonly (infer E)[] ? Extract<E, string> : never;
|
|
19
|
+
$exists?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type ModelFilter<T extends object = any> = {
|
|
22
|
+
[K in PropertyPaths<T>]?: PropertyPathType<T, K> | null | FilterOperators<PropertyPathType<T, K>>;
|
|
23
|
+
} & {
|
|
24
|
+
$or?: ModelFilter<T>[];
|
|
25
|
+
$and?: ModelFilter<T>[];
|
|
26
|
+
};
|
|
27
|
+
export interface FindOptions<T extends object> {
|
|
28
|
+
orderBy?: {
|
|
29
|
+
field: PropertyPaths<T>;
|
|
30
|
+
direction: "ASC" | "DESC";
|
|
31
|
+
}[];
|
|
32
|
+
limit?: number;
|
|
33
|
+
continuationToken?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Convert a JSON filter to a WebdaQL expression
|
|
37
|
+
*
|
|
38
|
+
* Keys set to `undefined` are ignored, so optional criteria can be spread in. A plain object without
|
|
39
|
+
* operators matches its nested fields: `{ address: { city: "Paris" } }` is `address.city = "Paris"`.
|
|
40
|
+
* @param filter - the JSON filter
|
|
41
|
+
* @returns the expression
|
|
42
|
+
* @throws {WebdaQLError} for an invalid filter
|
|
43
|
+
*/
|
|
44
|
+
export declare function filterToExpression(filter: ModelFilter): Expression;
|
|
45
|
+
/**
|
|
46
|
+
* Convert a JSON filter and its find options to a WebdaQL query string
|
|
47
|
+
* @param filter - the JSON filter
|
|
48
|
+
* @param options - ordering, limit and continuation token
|
|
49
|
+
* @returns the WebdaQL query
|
|
50
|
+
* @throws {WebdaQLError} for an invalid filter
|
|
51
|
+
*/
|
|
52
|
+
export declare function toWebdaQL<T extends object = any>(filter: ModelFilter<T>, options?: FindOptions<T>): WebdaQLString<T>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"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"}
|
package/lib/filter.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { AndExpression, ComparisonExpression, OrExpression, checkFieldPath, normalizeQuery } from "./query.js";
|
|
2
|
+
import { WebdaQLError } from "./webdaql-string.js";
|
|
3
|
+
const operators = {
|
|
4
|
+
$eq: "=",
|
|
5
|
+
$ne: "!=",
|
|
6
|
+
$gt: ">",
|
|
7
|
+
$gte: ">=",
|
|
8
|
+
$lt: "<",
|
|
9
|
+
$lte: "<=",
|
|
10
|
+
$in: "IN",
|
|
11
|
+
$like: "LIKE",
|
|
12
|
+
$contains: "CONTAINS"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* WebdaQL has no date literal: dates are compared as ISO 8601 strings, the way they are serialized
|
|
16
|
+
* @param value - the filter value
|
|
17
|
+
* @returns the value, with dates as ISO strings
|
|
18
|
+
*/
|
|
19
|
+
function toFilterValue(value) {
|
|
20
|
+
if (Array.isArray(value))
|
|
21
|
+
return value.map(toFilterValue);
|
|
22
|
+
if (!(value instanceof Date))
|
|
23
|
+
return value;
|
|
24
|
+
if (isNaN(value.getTime()))
|
|
25
|
+
throw new WebdaQLError("Invalid date in filter");
|
|
26
|
+
return value.toISOString();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Convert a JSON filter to a WebdaQL expression
|
|
30
|
+
*
|
|
31
|
+
* Keys set to `undefined` are ignored, so optional criteria can be spread in. A plain object without
|
|
32
|
+
* operators matches its nested fields: `{ address: { city: "Paris" } }` is `address.city = "Paris"`.
|
|
33
|
+
* @param filter - the JSON filter
|
|
34
|
+
* @returns the expression
|
|
35
|
+
* @throws {WebdaQLError} for an invalid filter
|
|
36
|
+
*/
|
|
37
|
+
export function filterToExpression(filter) {
|
|
38
|
+
if (!filter || typeof filter !== "object" || Array.isArray(filter))
|
|
39
|
+
throw new WebdaQLError("Filter must be an object");
|
|
40
|
+
const parts = [];
|
|
41
|
+
for (const key of Object.keys(filter)) {
|
|
42
|
+
const value = filter[key];
|
|
43
|
+
if (value === undefined)
|
|
44
|
+
continue;
|
|
45
|
+
if (key === "$or" || key === "$and") {
|
|
46
|
+
if (!Array.isArray(value) || !value.length)
|
|
47
|
+
throw new WebdaQLError(`${key} requires a non-empty array`);
|
|
48
|
+
parts.push(key === "$or"
|
|
49
|
+
? new OrExpression(value.map(filterToExpression))
|
|
50
|
+
: new AndExpression(value.map(filterToExpression)));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (key.startsWith("$"))
|
|
54
|
+
throw new WebdaQLError(`Unknown filter operator '${key}'`);
|
|
55
|
+
fieldToExpressions(key, value, parts);
|
|
56
|
+
}
|
|
57
|
+
return new AndExpression(parts);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Add the conditions on one field
|
|
61
|
+
* @param key - the field path
|
|
62
|
+
* @param value - a plain value, an operator object or a nested object
|
|
63
|
+
* @param parts - the conditions to add to
|
|
64
|
+
*/
|
|
65
|
+
function fieldToExpressions(key, value, parts) {
|
|
66
|
+
checkFieldPath(key);
|
|
67
|
+
if (value === null) {
|
|
68
|
+
parts.push(new ComparisonExpression("IS NULL", key, true));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (typeof value !== "object" || Array.isArray(value) || value instanceof Date) {
|
|
72
|
+
parts.push(new ComparisonExpression("=", key, toFilterValue(value)));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const keys = Object.keys(value);
|
|
76
|
+
if (!keys.length)
|
|
77
|
+
throw new WebdaQLError(`Empty filter object for '${key}'`);
|
|
78
|
+
const operatorKeys = keys.filter(k => k.startsWith("$"));
|
|
79
|
+
if (!operatorKeys.length) {
|
|
80
|
+
// Nested object: match each of its fields
|
|
81
|
+
const before = parts.length;
|
|
82
|
+
for (const sub of keys) {
|
|
83
|
+
if (value[sub] !== undefined)
|
|
84
|
+
fieldToExpressions(`${key}.${sub}`, value[sub], parts);
|
|
85
|
+
}
|
|
86
|
+
if (parts.length === before)
|
|
87
|
+
throw new WebdaQLError(`Empty filter object for '${key}'`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (operatorKeys.length !== keys.length)
|
|
91
|
+
throw new WebdaQLError(`Cannot mix operators and fields in '${key}'`);
|
|
92
|
+
for (const op of keys) {
|
|
93
|
+
const operand = value[op];
|
|
94
|
+
if (operand === undefined)
|
|
95
|
+
continue;
|
|
96
|
+
if (op === "$exists") {
|
|
97
|
+
if (typeof operand !== "boolean")
|
|
98
|
+
throw new WebdaQLError("$exists must be a boolean");
|
|
99
|
+
parts.push(new ComparisonExpression(operand ? "IS NOT NULL" : "IS NULL", key, true));
|
|
100
|
+
}
|
|
101
|
+
else if ((op === "$eq" || op === "$ne") && operand === null) {
|
|
102
|
+
parts.push(new ComparisonExpression(op === "$eq" ? "IS NULL" : "IS NOT NULL", key, true));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const mapped = operators[op];
|
|
106
|
+
if (!mapped)
|
|
107
|
+
throw new WebdaQLError(`Unknown filter operator '${op}'`);
|
|
108
|
+
if (operand === null)
|
|
109
|
+
throw new WebdaQLError("null is only supported with $eq, $ne, or $exists");
|
|
110
|
+
if (op === "$in" && (!Array.isArray(operand) || !operand.length))
|
|
111
|
+
throw new WebdaQLError("$in requires a non-empty array");
|
|
112
|
+
if (op === "$contains" && typeof operand !== "string")
|
|
113
|
+
throw new WebdaQLError("$contains takes a string");
|
|
114
|
+
parts.push(new ComparisonExpression(mapped, key, toFilterValue(operand)));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convert a JSON filter and its find options to a WebdaQL query string
|
|
120
|
+
* @param filter - the JSON filter
|
|
121
|
+
* @param options - ordering, limit and continuation token
|
|
122
|
+
* @returns the WebdaQL query
|
|
123
|
+
* @throws {WebdaQLError} for an invalid filter
|
|
124
|
+
*/
|
|
125
|
+
export function toWebdaQL(filter, options) {
|
|
126
|
+
const q = normalizeQuery({
|
|
127
|
+
type: "SELECT",
|
|
128
|
+
filter: filterToExpression(filter),
|
|
129
|
+
orderBy: options?.orderBy,
|
|
130
|
+
limit: options?.limit,
|
|
131
|
+
continuationToken: options?.continuationToken
|
|
132
|
+
});
|
|
133
|
+
return q.toString();
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=filter.js.map
|