Skip to content

Commit 6bbc495

Browse files
author
Sascha Goldhofer
committed
refactor!: rename library to json-query
1 parent 2912931 commit 6bbc495

File tree

9 files changed

+175
-93
lines changed

9 files changed

+175
-93
lines changed

README.md

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
<h1 align="left"><img src="./docs/gson-query.png" width="256" alt="gson-query"></h1>
1+
<h1 align="left"><img src="./docs/json-query.png" width="256" alt="@sagold/json-query"></h1>
22

3-
**⚠️ package `gson-query` has moved to `@sagold/json-query`. Please change package source as `gson-query` will no longer be updated.**
3+
> `json-query` lets you quickly select values, patterns or types from json-data. Its input requires a simple string, describing a concise query into your data
44
5-
> gson-query lets you quickly select values, patterns or types from json-data. Its input requires a simple string, describing a concise query into your data
5+
install
6+
7+
`yarn add @sagold/json-query`
68

7-
**npm package** `gson-query`. An es5-version is bundled at `dist/gson-query.js`. The command-line integration can be installed separately from [gson-query-cli](https://github.com/sagold/gson-query-cli).
89

910
- [Features](#features)
1011
- [Introduction](#quick-introduction)
@@ -31,7 +32,7 @@
3132
Basically, a **query** is a json-pointer, which describes a path of properties into the json-data
3233

3334
```js
34-
import { get } from "gson-query";
35+
import { get } from "@sagold/json-query";
3536
const input = { object: { a: { id: "id-a" }, b: { id: "id-b" } } };
3637

3738
const values = get(input, "/object/a/id"); // ["id-a"]
@@ -157,6 +158,7 @@ const values = get(input, "/(/a)+"); // [{ id: 2, a: { id: 3, a: 4 } }, { id: 3,
157158

158159
## Breaking Changes
159160

161+
- with version `v5.0.0` package has been rename to `@sagold/json-query`
160162
- with version `v4.0.0` (2019/10/01)
161163
- the api has been simplified to methods `query.get` and `query.delete` (removed `run` and `pattern`)
162164
- with version `v3.0.0`
@@ -167,7 +169,7 @@ const values = get(input, "/(/a)+"); // [{ id: 2, a: { id: 3, a: 4 } }, { id: 3,
167169

168170
## API
169171

170-
*gson-query* exposes `get`, `set`, `remove` and a `split`-helper
172+
*json-query* exposes `get`, `set`, `remove` and a `split`-helper
171173

172174
method | signature | description
173175
--------|-------------------------------------------------------------------|------------------------------
@@ -182,7 +184,7 @@ remove | (input:any, query: string, returnRemoved?:boolean) | de
182184
per default, *get* returns a list of all values
183185

184186
```js
185-
import { get } from "gson-query";
187+
import { get } from "@sagold/json-query";
186188
const input = { object: { a: { id: 33 }, b: { id: "id-b" } } };
187189
const values = get(input, "/**?:value"); // [33, "id-b"]
188190
```
@@ -201,7 +203,7 @@ function | callback with `(value, keyToValue, parentObject, jsonPointer) => {
201203

202204

203205
```js
204-
import { get } from "gson-query";
206+
import { get } from "@sagold/json-query";
205207
const input = { object: { a: { id: 33 }, b: { id: "id-b" } } };
206208

207209
get(input, "/**?:value", get.VALUE); // [33, "id-b"]
@@ -225,7 +227,7 @@ get(input, "/**?:value", (value, key, parent, pointer) => `custom-${pointer}`);
225227
Note: the input will be modified. If this is unwanted behaviour, copy your data up front.
226228

227229
```js
228-
import { remove } from "gson-query";
230+
import { remove } from "@sagold/json-query";
229231
const input = { object: { a: { id: 33 }, b: { id: "id-b" } } };
230232

231233
remove(input, "/object/*/id"); // { object: { a: {}, b: {} } };
@@ -234,7 +236,7 @@ remove(input, "/object/*/id"); // { object: { a: {}, b: {} } };
234236
Per default, the input object is returned. Setting the optional argument `returnRemoved = true`, will return a list of the removed items
235237

236238
```js
237-
import { remove } from "gson-query";
239+
import { remove } from "@sagold/json-query";
238240
const input = { object: { a: { id: 33 }, b: { id: "id-b" } } };
239241

240242
remove(input, "/object/*/id", true); // [ 33, "id-b" ]
@@ -262,15 +264,15 @@ value(pointerOfParent:string, lastPropertyName:string, parentObject:string, poin
262264
Create data from simple properties
263265

264266
```js
265-
import { set } from "gson-query";
267+
import { set } from "@sagold/json-query";
266268

267269
const result = set({}, "/object/id", 42); // { object: { id: 42 }}
268270
```
269271
270272
Add properties to multiple existing objects
271273
272274
```js
273-
import { set } from "gson-query";
275+
import { set } from "@sagold/json-query";
274276

275277
const result = set({ list: [ { id: 1 }, { id: 2 } ] }, "/list/*/index", 42);
276278
// { list: [ { id: 1, index: 42 }, { id: 2, index: 42 } ] }
@@ -279,7 +281,7 @@ const result = set({ list: [ { id: 1 }, { id: 2 } ] }, "/list/*/index", 42);
279281
Or using a value-function
280282
281283
```js
282-
import { set } from "gson-query";
284+
import { set } from "@sagold/json-query";
283285

284286
const result = set({ list: [ { id: 1 }, { id: 2 } ] }, "/list/*/index",
285287
( _, _, parent) => `id-${parent.id}`
@@ -290,15 +292,15 @@ const result = set({ list: [ { id: 1 }, { id: 2 } ] }, "/list/*/index",
290292
Currently, `set` will not override simple values
291293
292294
```js
293-
import { set } from "gson-query";
295+
import { set } from "@sagold/json-query";
294296

295297
const result = set({ value: 2 }, "/value/id", 3);
296298
// { value: 2 }
297299
```
298300
299301
And queries will not add values to the data
300302
```js
301-
import { set } from "gson-query";
303+
import { set } from "@sagold/json-query";
302304

303305
const result = set({ a: { id: 2 } }, "((/a), (/b))/id", true);
304306
// { a: { id: true } }

docs/gson-query.png

-5.08 KB
Binary file not shown.

docs/json-query.png

14.1 KB
Loading

lib/get.ts

+19-15
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,48 @@ import { parse } from "./parser";
22
import { run, VALUE_INDEX, POINTER_INDEX } from "./interpreter";
33
import { Input, JSONPointer, QueryResult } from "./types";
44

5-
65
const returnTypes = {
7-
value: r => r.map(e => e[VALUE_INDEX]),
8-
pointer: r => r.map(e => e[POINTER_INDEX]),
9-
all: r => r,
10-
map: r => {
6+
value: (r) => r.map((e) => e[VALUE_INDEX]),
7+
pointer: (r) => r.map((e) => e[POINTER_INDEX]),
8+
all: (r) => r,
9+
map: (r) => {
1110
const map = {};
12-
r.forEach(e => (map[e[POINTER_INDEX]] = e[VALUE_INDEX]));
11+
r.forEach((e) => (map[e[POINTER_INDEX]] = e[VALUE_INDEX]));
1312
return map;
14-
}
13+
},
1514
};
1615

17-
1816
export enum ReturnType {
1917
POINTER = "pointer",
2018
VALUE = "value",
2119
ALL = "all",
22-
MAP = "map"
20+
MAP = "map",
2321
}
2422

25-
26-
export type ResultCallback = (value: any, property: string|null, parent: { [p: string]: any }|Array<any>|null, pointer: JSONPointer) => any;
27-
23+
export type ResultCallback = (
24+
value: any,
25+
property: string | null,
26+
parent: { [p: string]: any } | Array<any> | null,
27+
pointer: JSONPointer
28+
) => any;
2829

2930
// export return types on function
3031
get.POINTER = ReturnType.POINTER;
3132
get.VALUE = ReturnType.VALUE;
3233
get.ALL = ReturnType.ALL;
3334
get.MAP = ReturnType.MAP;
3435

35-
3636
/**
3737
* Runs query on input data and returns the results
3838
* @param data - input data
39-
* @param queryString - gson-query string
39+
* @param queryString - json-query string
4040
* @param returnType - result format or a custom callback
4141
*/
42-
export default function get(data: Input, queryString: string, returnType: ReturnType|ResultCallback = ReturnType.VALUE) {
42+
export default function get(
43+
data: Input,
44+
queryString: string,
45+
returnType: ReturnType | ResultCallback = ReturnType.VALUE
46+
) {
4347
if (queryString == null) {
4448
return [];
4549
}

lib/interpreter/nodes.ts

+50-19
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,36 @@ import { IToken } from "ebnf";
55

66
const toString = Object.prototype.toString;
77
const rContainer = /Object|Array/;
8-
const isContainer = v => rContainer.test(toString.call(v));
9-
const getTypeOf = v => toString.call(v).match(/\s([^\]]+)\]/).pop().toLowerCase();
8+
const isContainer = (v) => rContainer.test(toString.call(v));
9+
const getTypeOf = (v) =>
10+
toString
11+
.call(v)
12+
.match(/\s([^\]]+)\]/)
13+
.pop()
14+
.toLowerCase();
1015
function nodeAsRegex(node) {
1116
return new RegExp(node.text.replace(/(^{|}$)/g, ""));
1217
}
1318

19+
/**
20+
* Returns all keys of the given input data
21+
*
22+
* @param value
23+
* @return {Array} containing keys of given value
24+
*/
25+
function getKeys(value: unknown) {
26+
let keys;
27+
if (Array.isArray(value)) {
28+
keys = value.map(function (value, index) {
29+
return index;
30+
});
31+
} else if (Object.prototype.toString.call(value) === "[object Object]") {
32+
return Object.keys(value);
33+
} else {
34+
keys = [];
35+
}
36+
return keys;
37+
}
1438

1539
const cache = {
1640
mem: [],
@@ -26,16 +50,22 @@ const cache = {
2650
},
2751
reset() {
2852
cache.mem.length = 0;
29-
}
53+
},
3054
};
3155

32-
3356
const expand = {
3457
any(node: IToken, entry) {
3558
const value = entry[VALUE_INDEX];
36-
return o.keys(value)
37-
// .map(prop => cache.get(entry, prop));
38-
.map(prop => [value[prop], prop, value, join(entry[POINTER_INDEX], prop)]);
59+
return (
60+
getKeys(value)
61+
// .map(prop => cache.get(entry, prop));
62+
.map((prop) => [
63+
value[prop],
64+
prop,
65+
value,
66+
join(entry[POINTER_INDEX], prop),
67+
])
68+
);
3969
},
4070

4171
all(node: IToken, entry) {
@@ -51,13 +81,17 @@ const expand = {
5181
regex(node: IToken, entry) {
5282
const regex = nodeAsRegex(node);
5383
const value = entry[VALUE_INDEX];
54-
return o.keys(value)
55-
.filter(prop => regex.test(prop))
56-
.map(prop => [value[prop], prop, value, join(entry[POINTER_INDEX], prop)]);
57-
}
84+
return getKeys(value)
85+
.filter((prop) => regex.test(prop))
86+
.map((prop) => [
87+
value[prop],
88+
prop,
89+
value,
90+
join(entry[POINTER_INDEX], prop),
91+
]);
92+
},
5893
};
5994

60-
6195
const select = {
6296
// alias to property (but escaped)
6397
escaped: (node: IToken, entry) => select.property(node, entry),
@@ -69,7 +103,7 @@ const select = {
69103
entry[VALUE_INDEX][prop],
70104
prop,
71105
entry[VALUE_INDEX],
72-
join(entry[POINTER_INDEX], prop)
106+
join(entry[POINTER_INDEX], prop),
73107
];
74108
}
75109
},
@@ -89,10 +123,10 @@ const select = {
89123
lookahead: (node: IToken, entry) => {
90124
let valid = true;
91125
let or = false;
92-
node.children.forEach(expr => {
126+
node.children.forEach((expr) => {
93127
if (expr.type === "expression") {
94128
const isValid = select.expression(expr, entry) !== undefined;
95-
valid = or === true ? (valid || isValid) : valid && isValid;
129+
valid = or === true ? valid || isValid : valid && isValid;
96130
} else {
97131
or = expr.type === "orExpr";
98132
}
@@ -111,10 +145,9 @@ const select = {
111145
}
112146

113147
return expressionMatches(value[prop], cmp, test) ? entry : undefined;
114-
}
148+
},
115149
};
116150

117-
118151
function expressionMatches(value, cmp, test) {
119152
if (cmp === undefined) {
120153
return value !== undefined;
@@ -126,7 +159,6 @@ function expressionMatches(value, cmp, test) {
126159
if (test.type === "regex") {
127160
const regex = nodeAsRegex(test);
128161
valid = regex.test(valueString);
129-
130162
} else {
131163
valid = valueString === test.text;
132164
}
@@ -138,5 +170,4 @@ function expressionMatches(value, cmp, test) {
138170
return valid;
139171
}
140172

141-
142173
export { expand, select, cache };

lib/remove.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { PARENT_INDEX, POINTER_INDEX } from "./interpreter/keys";
55
/**
66
* Runs query on input data and removes matching properties from results
77
* @param data - input data
8-
* @param queryString - gson-query string
8+
* @param queryString - json-query string
99
* @param [returnRemoved] - if true, will returned removed properties, else input-data is removed
1010
*/
1111
export default function queryRemove(data, queryString, returnRemoved = false) {

0 commit comments

Comments
 (0)