fx 24.1.0 → 26.0.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/README.md +33 -7
- package/index.js +49 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,19 +9,19 @@ npm i -g fx
|
|
|
9
9
|
Or use **npx**:
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
cat file.json | npx fx .
|
|
12
|
+
cat file.json | npx fx .field
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Or use **node**:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
cat file.json | node <(curl -s https://fx.wtf) .
|
|
18
|
+
cat file.json | node <(curl -s https://fx.wtf) .field
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Or use **deno**:
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
|
-
cat file.json | deno run https://fx.wtf .
|
|
24
|
+
cat file.json | deno run https://fx.wtf .field
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Usage
|
|
@@ -41,20 +41,46 @@ access the input data without a `x => x` part.
|
|
|
41
41
|
echo '{"name": "world"}' | fx '.name' '`Hello, ${this}!`'
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
can be written without leading dot and without `x =>` parts.
|
|
44
|
+
Use other JS functions to process the data.
|
|
46
45
|
|
|
47
46
|
```sh
|
|
48
|
-
|
|
47
|
+
echo `{"name": "world"}` | fx 'Object.keys'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Advanced Usage
|
|
51
|
+
|
|
52
|
+
Fx has a shortcut for the map function. Fox example, `this.map(x => x.commit.message)`
|
|
53
|
+
can be rewritten without leading dot and without `x => x` parts.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
curl https://api.github.com/repos/antonmedv/fx/commits | fx 'map(.commit.message)'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
echo '[{"name": "world"}]' | fx 'map(`Hello, ${x.name}!`)'
|
|
49
61
|
```
|
|
50
62
|
|
|
51
63
|
Fx has a special syntax for the flatMap function. Fox example,
|
|
52
|
-
`.flatMap(x => x.labels.flatMap(x => x.name))` can be
|
|
64
|
+
`.flatMap(x => x.labels.flatMap(x => x.name))` can be rewritten in the next way.
|
|
53
65
|
|
|
54
66
|
```sh
|
|
55
67
|
curl https://api.github.com/repos/kubernetes/kubernetes/issues | fx '.[].labels[].name'
|
|
56
68
|
```
|
|
57
69
|
|
|
70
|
+
Fx works with promises.
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
echo '"https://medv.io/*"' | fx 'fetch' '.text()'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
When using the **-r** or **--raw** flag, the input will be treated as a raw string
|
|
77
|
+
instead of JSON. This can be useful when working with non-JSON input data, such as
|
|
78
|
+
plain text or CSV data.
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
ls | fx -r '.trim().split("\n")'
|
|
82
|
+
```
|
|
83
|
+
|
|
58
84
|
## License
|
|
59
85
|
|
|
60
86
|
[MIT](../LICENSE)
|
package/index.js
CHANGED
|
@@ -1,26 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
void async function main() {
|
|
2
3
|
const process = await import('node:process')
|
|
4
|
+
const args = process.argv.slice(2)
|
|
5
|
+
if ((args.length === 0 && process.stdin.isTTY)
|
|
6
|
+
|| (args.length === 1 && ['-h', '--help'].includes(args[0]))) {
|
|
7
|
+
printUsage()
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
let input = ''
|
|
4
12
|
process.stdin.setEncoding('utf8')
|
|
5
13
|
for await (const chunk of process.stdin)
|
|
6
14
|
input += chunk
|
|
7
|
-
const args = process.argv.slice(2)
|
|
8
15
|
|
|
9
16
|
let json
|
|
10
|
-
|
|
17
|
+
if (['-r', '--raw'].includes(args[0])) {
|
|
18
|
+
args.shift()
|
|
19
|
+
json = input
|
|
20
|
+
} else try {
|
|
11
21
|
json = JSON.parse(input)
|
|
12
22
|
} catch (err) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} catch (_) {
|
|
16
|
-
process.stderr.write(`Invalid JSON: ${err.message}\n`)
|
|
17
|
-
process.exit(1)
|
|
18
|
-
}
|
|
23
|
+
process.stderr.write(`Invalid JSON: ${err.message}\n`)
|
|
24
|
+
process.exit(1)
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
let i, code, output = json
|
|
22
28
|
for ([i, code] of args.entries()) try {
|
|
23
|
-
output = transform(output, code)
|
|
29
|
+
output = await transform(output, code)
|
|
24
30
|
} catch (err) {
|
|
25
31
|
printErr(err)
|
|
26
32
|
process.exit(1)
|
|
@@ -46,7 +52,7 @@ void async function main() {
|
|
|
46
52
|
}
|
|
47
53
|
}()
|
|
48
54
|
|
|
49
|
-
function transform(json, code) {
|
|
55
|
+
async function transform(json, code) {
|
|
50
56
|
if ('.' === code)
|
|
51
57
|
return json
|
|
52
58
|
|
|
@@ -68,20 +74,23 @@ function transform(json, code) {
|
|
|
68
74
|
return this${code}
|
|
69
75
|
})`).call(json)
|
|
70
76
|
|
|
71
|
-
if (/^map\(.+?\)$/.test(code))
|
|
77
|
+
if (/^map\(.+?\)$/.test(code)) {
|
|
78
|
+
let s = code.substring(4, code.length - 1)
|
|
79
|
+
if (s[0] === '.') s = 'x' + s
|
|
72
80
|
return eval(`(function () {
|
|
73
|
-
return this.map(x => apply(
|
|
81
|
+
return this.map((x, i) => apply(${s}, x, i))
|
|
74
82
|
})`).call(json)
|
|
83
|
+
}
|
|
75
84
|
|
|
76
85
|
const fn = eval(`(function () {
|
|
77
86
|
return ${code}
|
|
78
87
|
})`).call(json)
|
|
79
88
|
|
|
80
|
-
return apply(
|
|
89
|
+
return apply(fn, json)
|
|
81
90
|
}
|
|
82
91
|
|
|
83
|
-
function apply(
|
|
84
|
-
if (typeof fn === 'function') return fn(
|
|
92
|
+
function apply(fn, ...args) {
|
|
93
|
+
if (typeof fn === 'function') return fn(...args)
|
|
85
94
|
return fn
|
|
86
95
|
}
|
|
87
96
|
|
|
@@ -100,3 +109,28 @@ function uniq(array) {
|
|
|
100
109
|
function sort(array) {
|
|
101
110
|
return array.sort()
|
|
102
111
|
}
|
|
112
|
+
|
|
113
|
+
function groupBy(keyOrFunction) {
|
|
114
|
+
return array => {
|
|
115
|
+
const grouped = {}
|
|
116
|
+
for (const item of array) {
|
|
117
|
+
const key = typeof keyOrFunction === 'function'
|
|
118
|
+
? keyOrFunction(item)
|
|
119
|
+
: item[keyOrFunction]
|
|
120
|
+
if (!grouped.hasOwnProperty(key))
|
|
121
|
+
grouped[key] = []
|
|
122
|
+
grouped[key].push(item)
|
|
123
|
+
}
|
|
124
|
+
return grouped
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function printUsage() {
|
|
129
|
+
const usage = `Usage
|
|
130
|
+
fx [flags] [code...]
|
|
131
|
+
|
|
132
|
+
Flags
|
|
133
|
+
-h, --help Display this help message
|
|
134
|
+
-r, --raw Treat input as raw string`
|
|
135
|
+
console.log(usage)
|
|
136
|
+
}
|