@peter_marklund/json 0.0.4 → 0.0.5

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 CHANGED
@@ -16,6 +16,57 @@ npm install @peter_marklund/json -g
16
16
 
17
17
  ```sh
18
18
  echo '{"foo": "1"}' | json .foo
19
+
20
+ # Colorized pretty printing is the default
21
+ cat test/input/array.json | json
22
+ # [
23
+ # {
24
+ # "id": 1,
25
+ # "name": "Item 1",
26
+ # "value": 100
27
+ # },
28
+ # {
29
+ # "id": 2,
30
+ # "name": "Item 2",
31
+ # "value": 200
32
+ # },
33
+ # {
34
+ # "id": 3,
35
+ # "name": "Item 3",
36
+ # "value": 300
37
+ # }
38
+ # ]
39
+
40
+ # Without pretty printing (single line):
41
+ cat test/input/basic.json | PRETTY=false json
42
+ # {"bar":"Hello world","baz":false,"data":[{"id":1,"name":"Item 1","value":100},{"id":2,"name":"Item 2","value":200},{"id":3,"name":"Item 3","value":300}],"foo":1,"nested":{"foo":{"bar":"nested value"}}}
43
+
44
+ # JSONL output (for an array with one JSON object per line)
45
+ cat test/input/array.json | JSONL=true json
46
+ # {"id":1,"name":"Item 1","value":100}
47
+ # {"id":2,"name":"Item 2","value":200}
48
+ # {"id":3,"name":"Item 3","value":300}
49
+
50
+ # The json command can take JSONL as input as well
51
+ cat test/input/array.jsonl | json
52
+
53
+ # The json command can also parse JSON data at the end of log lines:
54
+ cat test/input/log-with-json.log | json
55
+ # [
56
+ # {
57
+ # "_line": "192.168.1.1 - - [21/Feb/2026:10:00:01 +0000] \"GET /api/users HTTP/1.1\" 200 ",
58
+ # "cache": "hit",
59
+ # "duration_ms": 42,
60
+ # "user_id": 1021
61
+ # },
62
+ # {
63
+ # "_line": "192.168.1.2 - - [21/Feb/2026:10:00:03 +0000] \"POST /api/orders HTTP/1.1\" 201 ",
64
+ # "cache": "miss",
65
+ # "duration_ms": 87,
66
+ # "user_id": 4432
67
+ # },
68
+ # ...
69
+ # ]
19
70
  ```
20
71
 
21
72
  ## Running the Tests
package/bin/json.js CHANGED
@@ -61,7 +61,38 @@ function getCodeArg() {
61
61
  function readStdIn() {
62
62
  return fs.readFileSync(0).toString();
63
63
  }
64
-
64
+
65
+ function parseLine(line, openLines) {
66
+ let result = { openLines: [...openLines] };
67
+ try {
68
+ const openIndex = line.startsWith("[") ? 0 : line.indexOf("{");
69
+ if (
70
+ openLines.length === 0 &&
71
+ ((line.indexOf("{") >= 0 && line.endsWith("}")) ||
72
+ (line.startsWith("[") && line.endsWith("]")))
73
+ ) {
74
+ const doc = JSON.parse(line.substring(openIndex));
75
+ if (openIndex > 0 && !doc._line) doc._line = line.substring(0, openIndex);
76
+ result.parsedLine = doc;
77
+ } else if (line === "{") {
78
+ result.openLines = [line];
79
+ } else if (openLines.length > 0) {
80
+ result.openLines.push(line);
81
+ if (line === "}") {
82
+ result.parsedLine = JSON.parse(openLines.join("\n"));
83
+ result.openLines = [];
84
+ }
85
+ } else {
86
+ result.parsedLine = { _line: line };
87
+ }
88
+ } catch (err) {
89
+ result.error = `Error thrown parsing line: ${line} - ${err.stack}`;
90
+ result.openLines = [];
91
+ result.parsedLine = { _line: line };
92
+ }
93
+ return result;
94
+ }
95
+
65
96
  async function jsonIn(filePath) {
66
97
  let textInput
67
98
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peter_marklund/json",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "A convenient way to work with JSON using JavaScript in the terminal",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/helpers.js CHANGED
@@ -54,10 +54,17 @@ function base64Encode(data) {
54
54
  return data && Buffer.from(data).toString("base64");
55
55
  }
56
56
 
57
- function percentile(values, pct) {
58
- const sorted = values.sort((a, b) => a - b);
59
- const index = Math.floor(sorted.length * pct);
60
- return sorted[index];
57
+ function percentile(arr, p) {
58
+ if (typeof p !== 'number' || p <= 0 || p >= 1.0) {
59
+ throw new Error('Percentile must be a number between 0 and 1');
60
+ }
61
+ const sorted = [...arr].sort((a, b) => a - b);
62
+ const index = p * (sorted.length - 1);
63
+ const lower = Math.floor(index);
64
+ const upper = Math.ceil(index);
65
+ const weight = index - lower;
66
+
67
+ return sorted[lower] * (1 - weight) + sorted[upper] * weight;
61
68
  }
62
69
 
63
70
  function p50(values) {
@@ -0,0 +1,17 @@
1
+ [
2
+ {
3
+ "id": 1,
4
+ "name": "Item 1",
5
+ "value": 100
6
+ },
7
+ {
8
+ "id": 2,
9
+ "name": "Item 2",
10
+ "value": 200
11
+ },
12
+ {
13
+ "id": 3,
14
+ "name": "Item 3",
15
+ "value": 300
16
+ }
17
+ ]
@@ -0,0 +1,3 @@
1
+ {"id":1,"name":"Item 1","value":100}
2
+ {"id":2,"name":"Item 2","value":200}
3
+ {"id":3,"name":"Item 3","value":300}
package/test/run.js CHANGED
@@ -25,7 +25,7 @@ async function runTest(test) {
25
25
  console.log(`output: ${output}`)
26
26
  const elapsedTime = Date.now() - startTime
27
27
  console.log(`elapsed: ${elapsedTime}`)
28
- if (isJsonScalarValue(test.expected)) {
28
+ if (isJsonScalarValue(test.expected) || test.command.includes('JSONL=true')) {
29
29
  assert.strictEqual(output, test.expected)
30
30
  } else {
31
31
  assert.strictEqual(stringify(JSON.parse(output)), stringify(JSON.parse(test.expected)))
@@ -42,6 +42,7 @@ async function run() {
42
42
  const elapsedTime = Date.now() - startTime
43
43
  console.log(`\nTotal elapsed: ${elapsedTime}`)
44
44
  console.log(`Total tests run: ${spec.tests.length}`)
45
+ console.log('SUCCESS!')
45
46
  process.exit(0)
46
47
  } catch (error) {
47
48
  console.log(error.stack || error)
@@ -48,7 +48,22 @@
48
48
  {
49
49
  "name": "stats",
50
50
  "command": "cat test/input/basic.json | json 'pick(stats(data.data.map(i => i.value)), [\"min\", \"max\", \"avg\", \"p50\", \"p90\"])'",
51
- "expected": "{\"min\": 100, \"max\": 300, \"avg\": 200, \"p50\": 200, \"p90\": 300}"
51
+ "expected": "{\"min\": 100, \"max\": 300, \"avg\": 200, \"p50\": 200, \"p90\": 280}"
52
+ },
53
+ {
54
+ "name": "jsonl_input",
55
+ "command": "cat test/input/array.jsonl | json",
56
+ "expected": "[{\"id\":1,\"name\":\"Item 1\",\"value\":100},{\"id\":2,\"name\":\"Item 2\",\"value\":200},{\"id\":3,\"name\":\"Item 3\",\"value\":300}]"
57
+ },
58
+ {
59
+ "name": "jsonl_output",
60
+ "command": "cat test/input/array.jsonl | JSONL=true json",
61
+ "expected": "{\"id\":1,\"name\":\"Item 1\",\"value\":100}\n{\"id\":2,\"name\":\"Item 2\",\"value\":200}\n{\"id\":3,\"name\":\"Item 3\",\"value\":300}"
62
+ },
63
+ {
64
+ "name": "log_with_json_input",
65
+ "command": "cat test/input/log-with-json.log | json 'sum(data.map(d => d.duration_ms))'",
66
+ "expected": "141"
52
67
  }
53
68
  ]
54
69
  }