@uniqu/url 0.1.0 → 0.1.1
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/dist/builder.cjs +8 -0
- package/dist/builder.mjs +8 -0
- package/dist/index.cjs +24 -6
- package/dist/index.mjs +24 -6
- package/package.json +2 -2
package/dist/builder.cjs
CHANGED
|
@@ -91,6 +91,7 @@ function serializeValue(value) {
|
|
|
91
91
|
const KNOWN_CONTROL_KEYS = new Set([
|
|
92
92
|
"$select",
|
|
93
93
|
"$groupBy",
|
|
94
|
+
"$having",
|
|
94
95
|
"$sort",
|
|
95
96
|
"$limit",
|
|
96
97
|
"$skip",
|
|
@@ -122,6 +123,13 @@ function serializeControls(controls) {
|
|
|
122
123
|
const part = `$groupBy=${seg}`;
|
|
123
124
|
result = result ? result + "&" + part : part;
|
|
124
125
|
}
|
|
126
|
+
if (controls.$having) {
|
|
127
|
+
const havingStr = serializeFilter(controls.$having);
|
|
128
|
+
if (havingStr) {
|
|
129
|
+
const part = "$and" in controls.$having ? `$having=(${havingStr})` : `$having=${havingStr}`;
|
|
130
|
+
result = result ? result + "&" + part : part;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
125
133
|
if (controls.$sort) {
|
|
126
134
|
let seg = "";
|
|
127
135
|
for (const [field, dir] of Object.entries(controls.$sort)) {
|
package/dist/builder.mjs
CHANGED
|
@@ -90,6 +90,7 @@ function serializeValue(value) {
|
|
|
90
90
|
const KNOWN_CONTROL_KEYS = new Set([
|
|
91
91
|
"$select",
|
|
92
92
|
"$groupBy",
|
|
93
|
+
"$having",
|
|
93
94
|
"$sort",
|
|
94
95
|
"$limit",
|
|
95
96
|
"$skip",
|
|
@@ -121,6 +122,13 @@ function serializeControls(controls) {
|
|
|
121
122
|
const part = `$groupBy=${seg}`;
|
|
122
123
|
result = result ? result + "&" + part : part;
|
|
123
124
|
}
|
|
125
|
+
if (controls.$having) {
|
|
126
|
+
const havingStr = serializeFilter(controls.$having);
|
|
127
|
+
if (havingStr) {
|
|
128
|
+
const part = "$and" in controls.$having ? `$having=(${havingStr})` : `$having=${havingStr}`;
|
|
129
|
+
result = result ? result + "&" + part : part;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
124
132
|
if (controls.$sort) {
|
|
125
133
|
let seg = "";
|
|
126
134
|
for (const [field, dir] of Object.entries(controls.$sort)) {
|
package/dist/index.cjs
CHANGED
|
@@ -310,9 +310,10 @@ function unescapeString(str) {
|
|
|
310
310
|
merged.push(currentMerge);
|
|
311
311
|
currentMerge = {};
|
|
312
312
|
} else {
|
|
313
|
-
|
|
314
|
-
for (const op of currentOps)
|
|
315
|
-
for (const op of otherOps)
|
|
313
|
+
const m = {};
|
|
314
|
+
for (const op of currentOps) m[op] = (0, _uniqu_core.isPrimitive)(currentVal) ? currentVal : currentVal[op];
|
|
315
|
+
for (const op of otherOps) m[op] = (0, _uniqu_core.isPrimitive)(val) ? val : val[op];
|
|
316
|
+
currentMerge[key] = m;
|
|
316
317
|
}
|
|
317
318
|
} else currentMerge[key] = val;
|
|
318
319
|
}
|
|
@@ -350,9 +351,9 @@ function buildExists(fields, positive) {
|
|
|
350
351
|
let filter = {};
|
|
351
352
|
let parser;
|
|
352
353
|
if (exprParts.length) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
354
|
+
const parsed = parseFilterExpr(exprParts.join("&"));
|
|
355
|
+
parser = parsed.parser;
|
|
356
|
+
filter = parsed.expr;
|
|
356
357
|
} else parser = new Parser([]);
|
|
357
358
|
for (const [field, op] of controlInsights) parser.captureInsight(field, op);
|
|
358
359
|
return {
|
|
@@ -374,6 +375,15 @@ function buildExists(fields, positive) {
|
|
|
374
375
|
parts.push(str.slice(start));
|
|
375
376
|
return parts;
|
|
376
377
|
}
|
|
378
|
+
/** Lex + parse a raw filter expression string. */ function parseFilterExpr(raw) {
|
|
379
|
+
const parser = new Parser(lex(raw));
|
|
380
|
+
const expr = parser.parseExpression();
|
|
381
|
+
parser.expectEof();
|
|
382
|
+
return {
|
|
383
|
+
expr,
|
|
384
|
+
parser
|
|
385
|
+
};
|
|
386
|
+
}
|
|
377
387
|
/** Parse a single `$with` segment like `posts` or `posts($sort=-createdAt&status=active)`. */ function parseWithSegment(seg) {
|
|
378
388
|
if (!seg) return null;
|
|
379
389
|
const parenIdx = seg.indexOf("(");
|
|
@@ -500,6 +510,14 @@ function handleControls(parts) {
|
|
|
500
510
|
controlInsights.push([f, "$groupBy"]);
|
|
501
511
|
}
|
|
502
512
|
break;
|
|
513
|
+
case "$having": {
|
|
514
|
+
if (!value) break;
|
|
515
|
+
const { expr, parser: hp } = parseFilterExpr(value);
|
|
516
|
+
if (controls.$having) controls.$having = { $and: [controls.$having, expr] };
|
|
517
|
+
else controls.$having = expr;
|
|
518
|
+
for (const [field] of hp.getInsights()) controlInsights.push([field, "$having"]);
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
503
521
|
case "$limit":
|
|
504
522
|
case "$top":
|
|
505
523
|
controls.$limit = Number(value);
|
package/dist/index.mjs
CHANGED
|
@@ -309,9 +309,10 @@ function unescapeString(str) {
|
|
|
309
309
|
merged.push(currentMerge);
|
|
310
310
|
currentMerge = {};
|
|
311
311
|
} else {
|
|
312
|
-
|
|
313
|
-
for (const op of currentOps)
|
|
314
|
-
for (const op of otherOps)
|
|
312
|
+
const m = {};
|
|
313
|
+
for (const op of currentOps) m[op] = isPrimitive(currentVal) ? currentVal : currentVal[op];
|
|
314
|
+
for (const op of otherOps) m[op] = isPrimitive(val) ? val : val[op];
|
|
315
|
+
currentMerge[key] = m;
|
|
315
316
|
}
|
|
316
317
|
} else currentMerge[key] = val;
|
|
317
318
|
}
|
|
@@ -349,9 +350,9 @@ function buildExists(fields, positive) {
|
|
|
349
350
|
let filter = {};
|
|
350
351
|
let parser;
|
|
351
352
|
if (exprParts.length) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
const parsed = parseFilterExpr(exprParts.join("&"));
|
|
354
|
+
parser = parsed.parser;
|
|
355
|
+
filter = parsed.expr;
|
|
355
356
|
} else parser = new Parser([]);
|
|
356
357
|
for (const [field, op] of controlInsights) parser.captureInsight(field, op);
|
|
357
358
|
return {
|
|
@@ -373,6 +374,15 @@ function buildExists(fields, positive) {
|
|
|
373
374
|
parts.push(str.slice(start));
|
|
374
375
|
return parts;
|
|
375
376
|
}
|
|
377
|
+
/** Lex + parse a raw filter expression string. */ function parseFilterExpr(raw) {
|
|
378
|
+
const parser = new Parser(lex(raw));
|
|
379
|
+
const expr = parser.parseExpression();
|
|
380
|
+
parser.expectEof();
|
|
381
|
+
return {
|
|
382
|
+
expr,
|
|
383
|
+
parser
|
|
384
|
+
};
|
|
385
|
+
}
|
|
376
386
|
/** Parse a single `$with` segment like `posts` or `posts($sort=-createdAt&status=active)`. */ function parseWithSegment(seg) {
|
|
377
387
|
if (!seg) return null;
|
|
378
388
|
const parenIdx = seg.indexOf("(");
|
|
@@ -499,6 +509,14 @@ function handleControls(parts) {
|
|
|
499
509
|
controlInsights.push([f, "$groupBy"]);
|
|
500
510
|
}
|
|
501
511
|
break;
|
|
512
|
+
case "$having": {
|
|
513
|
+
if (!value) break;
|
|
514
|
+
const { expr, parser: hp } = parseFilterExpr(value);
|
|
515
|
+
if (controls.$having) controls.$having = { $and: [controls.$having, expr] };
|
|
516
|
+
else controls.$having = expr;
|
|
517
|
+
for (const [field] of hp.getInsights()) controlInsights.push([field, "$having"]);
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
502
520
|
case "$limit":
|
|
503
521
|
case "$top":
|
|
504
522
|
controls.$limit = Number(value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniqu/url",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "URL query string parser producing the Uniqu canonical query format",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Artem Maltsev",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dist"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@uniqu/core": "^0.1.
|
|
48
|
+
"@uniqu/core": "^0.1.1"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"pub": "pnpm publish --access public",
|