json-p3 0.1.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/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 James Prior
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,252 @@
1
+ <h1 align="center">JSON P3</h1>
2
+
3
+ <p align="center">
4
+ JSONPath, JSON Patch and JSON Pointer for JavaScript.
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://github.com/jg-rp/json-p3/blob/main/LICENSE">
9
+ <img alt="NPM" src="https://img.shields.io/npm/l/json-p3">
10
+ </a>
11
+ <a href="https://github.com/jg-rp/json-p3/actions">
12
+ <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/json-p3/tests.yaml?branch=main&label=tests&style=flat-square" alt="Tests">
13
+ </a>
14
+ <br>
15
+ </p>
16
+
17
+ ---
18
+
19
+ ## Install
20
+
21
+ ### Node.js
22
+
23
+ Use npm:
24
+
25
+ ```console
26
+ npm install --save json-p3
27
+ ```
28
+
29
+ Or yarn:
30
+
31
+ ```console
32
+ yarn add json-p3
33
+ ```
34
+
35
+ Or pnpm:
36
+
37
+ ```console
38
+ pnpm add json-p3
39
+ ```
40
+
41
+ And use ES module imports:
42
+
43
+ ```javascript
44
+ import { query } from "json-p3";
45
+
46
+ const data = {
47
+ players: [{ name: "Sue" }, { name: "John" }, { name: "Sally" }],
48
+ visitors: [{ name: "Brian" }, { name: "Roy" }],
49
+ };
50
+
51
+ const nodes = query("$..name", data);
52
+ console.log(nodes.values());
53
+ // [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]
54
+ ```
55
+
56
+ Or CommonJS modules:
57
+
58
+ ```javascript
59
+ const { query } = require("json-p3");
60
+
61
+ const data = {
62
+ players: [{ name: "Sue" }, { name: "John" }, { name: "Sally" }],
63
+ visitors: [{ name: "Brian" }, { name: "Roy" }],
64
+ };
65
+
66
+ const nodes = query("$..name", data);
67
+ console.log(nodes.values());
68
+ // [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]
69
+ ```
70
+
71
+ ### Browser
72
+
73
+ TODO:
74
+
75
+ ## JSONPath
76
+
77
+ Retrieve values from JSON-like data using JSONPath query expressions. We strictly follow standards described in the [IETF JSONPath draft](https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-20).
78
+
79
+ ```javascript
80
+ import { jsonpath } from "json-p3";
81
+
82
+ const data = {
83
+ users: [
84
+ { name: "Sue", score: 100 },
85
+ { name: "John", score: 86 },
86
+ { name: "Sally", score: 84 },
87
+ { name: "Jane", score: 55 },
88
+ ],
89
+ };
90
+
91
+ const nodes = jsonpath.query("$.users[?@.score < 100].name", data);
92
+ console.log(nodes.values()); // [ 'John', 'Sally', 'Jane' ]
93
+ ```
94
+
95
+ The result of `jsonpath.query()` is an instance of `JSONPathNodeList`. That is a list of `JSONPathNode` objects, one node for each value in the target JSON document matching the query. Each node has a:
96
+
97
+ - `value` - The value found in the target JSON value. This could be an array, object or primitive value.
98
+ - `location` - An array of property names and array indices that were required to reach the node's value in the target JSON value.
99
+ - `path` - The normalized JSONPath to this node in the target JSON document.
100
+
101
+ Use `JSONPathNodeList.paths()` to retrieve all node paths.
102
+
103
+ ```javascript
104
+ // .. continued from above
105
+ console.log(nodes.paths());
106
+ ```
107
+
108
+ **Output:**
109
+
110
+ ```plain
111
+ [
112
+ "$['users']['1']['name']",
113
+ "$['users']['2']['name']",
114
+ "$['users']['3']['name']"
115
+ ]
116
+ ```
117
+
118
+ And `JSONPathNodeList.locations()` to get an array of node locations.
119
+
120
+ ```javascript
121
+ // .. continued from above
122
+ console.log(nodes.locations());
123
+ ```
124
+
125
+ **Output:**
126
+
127
+ ```plain
128
+ [
129
+ [ 'users', 1, 'name' ],
130
+ [ 'users', 2, 'name' ],
131
+ [ 'users', 3, 'name' ]
132
+ ]
133
+ ```
134
+
135
+ TODO: node lists are iterable
136
+
137
+ You can also compile a JSONPath query for repeated use against different data.
138
+
139
+ ```javascript
140
+ import { jsonpath } from "json-p3";
141
+
142
+ const data = {
143
+ users: [
144
+ { name: "Sue", score: 100 },
145
+ { name: "John", score: 86 },
146
+ { name: "Sally", score: 84 },
147
+ { name: "Jane", score: 55 },
148
+ ],
149
+ };
150
+
151
+ const path = jsonpath.compile("$.users[?@.score < 100].name");
152
+ const nodes = path.query(data);
153
+ console.log(nodes.values()); // [ 'John', 'Sally', 'Jane' ]
154
+ ```
155
+
156
+ ## JSON Pointer
157
+
158
+ Identify a single value in JSON-like data, as per RFC 6901. Use `jsonpointer.resolve()` to retrieve the value.
159
+
160
+ ```javascript
161
+ import { jsonpointer } from "json-p3";
162
+
163
+ const data = {
164
+ users: [
165
+ { name: "Sue", score: 100 },
166
+ { name: "John", score: 86 },
167
+ { name: "Sally", score: 84 },
168
+ { name: "Jane", score: 55 },
169
+ ],
170
+ };
171
+
172
+ const rv = jsonpointer.resolve("/users/1", data);
173
+ console.log(rv); // { name: 'John', score: 86 }
174
+ ```
175
+
176
+ If the pointer can't be resolved against the argument JSON value, one of `JSONPointerIndexError`, `JSONPointerKeyError` or `JSONPointerTypeError` is thrown. All three exceptions inherit from `JSONPointerResolutionError`.
177
+
178
+ ```javascript
179
+ import { jsonpointer } from "json-p3";
180
+
181
+ const data = {
182
+ users: [
183
+ { name: "Sue", score: 100 },
184
+ { name: "John", score: 86 },
185
+ { name: "Sally", score: 84 },
186
+ { name: "Jane", score: 55 },
187
+ ],
188
+ };
189
+
190
+ const rv = jsonpointer.resolve("/users/1/age", data);
191
+ // JSONPointerKeyError: no such property ("/users/1/age")
192
+ ```
193
+
194
+ A fallback value can be given as a third argument, which will be returned in the event of a `JSONPointerResolutionError`.
195
+
196
+ ```javascript
197
+ import { jsonpointer } from "json-p3";
198
+
199
+ const data = {
200
+ users: [
201
+ { name: "Sue", score: 100 },
202
+ { name: "John", score: 86 },
203
+ { name: "Sally", score: 84 },
204
+ { name: "Jane", score: 55 },
205
+ ],
206
+ };
207
+
208
+ const rv = jsonpointer.resolve("/users/1/age", data, -1);
209
+ console.log(rv); // -1
210
+ ```
211
+
212
+ TODO: "compile" a pointer for later use
213
+
214
+ ## JSON Patch
215
+
216
+ Apply a JSON Patch ([RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902)) to some data. A JSON Patch defines update operation to perform on a JSON document. **Data is modified in place.**.
217
+
218
+ ```javascript
219
+ import { jsonpatch } from "json-p3";
220
+
221
+ const ops = [
222
+ { op: "add", path: "/some/foo", value: { foo: {} } },
223
+ { op: "add", path: "/some/foo", value: { bar: [] } },
224
+ { op: "copy", from: "/some/other", path: "/some/foo/else" },
225
+ { op: "add", path: "/some/foo/bar/-", value: 1 },
226
+ ];
227
+
228
+ const data = { some: { other: "thing" } };
229
+ jsonpatch.apply(ops, data);
230
+ console.log(data);
231
+ // { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } }
232
+ ```
233
+
234
+ Use the `JSONPatch` class to create a patch for repeated application.
235
+
236
+ ```javascript
237
+ import { JSONPatch } from "json-p3";
238
+
239
+ const patch = new JSONPatch([
240
+ { op: "add", path: "/some/foo", value: { foo: {} } },
241
+ { op: "add", path: "/some/foo", value: { bar: [] } },
242
+ { op: "copy", from: "/some/other", path: "/some/foo/else" },
243
+ { op: "add", path: "/some/foo/bar/-", value: 1 },
244
+ ]);
245
+
246
+ const data = { some: { other: "thing" } };
247
+ patch.apply(data);
248
+ console.log(data);
249
+ // { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } }
250
+ ```
251
+
252
+ TODO: patch builder api
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Deep equality of JSON-like values.
3
+ *
4
+ * No attempt is made to handle function objects, recursive data
5
+ * structures, NaNs, sparse arrays, primitive wrapper objects....
6
+ *
7
+ * We're not using JSON.stringify because we want objects with the same
8
+ * entries in a different order to compare equal.
9
+ */
10
+ export declare function deepEquals(a: unknown, b: unknown): boolean;
@@ -0,0 +1,10 @@
1
+ export declare const version = "__VERSION__";
2
+ export * as jsonpath from "./path";
3
+ export { FunctionExpressionType, JSONPath, JSONPathEnvironment, JSONPathError, JSONPathIndexError, JSONPathLexerError, JSONPathNode, JSONPathNodeList, JSONPathSyntaxError, JSONPathTypeError, Token, TokenKind, Nothing, query, compile, } from "./path";
4
+ export type { JSONPathEnvironmentOptions, FilterFunction } from "./path";
5
+ export * as jsonpointer from "./pointer";
6
+ export { JSONPointer, resolve, UNDEFINED } from "./pointer";
7
+ export * as jsonpatch from "./patch";
8
+ export { JSONPatch, JSONPatchError, JSONPatchTestFailure, apply, } from "./patch";
9
+ export type { OpObject } from "./patch";
10
+ export type { JSONValue } from "./types";