fx 35.0.0 → 36.0.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.
Files changed (3) hide show
  1. package/README.md +22 -10
  2. package/index.js +41 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -16,7 +16,7 @@ cat file.json | npx fx .field
16
16
  Or use **deno**:
17
17
 
18
18
  ```sh
19
- cat file.json | deno run -A https://fx.wtf .field
19
+ cat file.json | deno run -A npm:fx .field
20
20
  ```
21
21
 
22
22
  ## Usage
@@ -42,7 +42,7 @@ Use other JS functions to process the data.
42
42
  echo '{"name": "world"}' | fx 'Object.keys'
43
43
  ```
44
44
 
45
- ## Advanced Usage
45
+ ### Stream processing
46
46
 
47
47
  Fx can process a stream of json objects. Fx will apply arguments to each object.
48
48
 
@@ -57,6 +57,8 @@ use the **--slurp** or **-s** flag.
57
57
  echo '{"name": "hello"}\n{"name": "world"}' | fx --slurp '.map(x => x.name)' '.join(", ")'
58
58
  ```
59
59
 
60
+ ### Raw input
61
+
60
62
  If you want to process non-JSON data, use the **--raw** or **-r** flag.
61
63
 
62
64
  ```sh
@@ -75,18 +77,24 @@ Fx has a special symbol **skip** for skipping the printing of the result.
75
77
  ls | fx -r '.includes(".md") ? this : skip'
76
78
  ```
77
79
 
80
+ ### Built-in functions
81
+
78
82
  Fx comes with a set of useful functions: **uniq**, **sort**, **groupBy**, **chunk**, **zip**.
79
83
 
80
84
  ```sh
81
85
  cat file.json | fx 'uniq' 'sort' 'groupBy(x => x.name)'
82
86
  ```
83
87
 
84
- Fx works with promises.
88
+ ### Edit-in-place
89
+
90
+ You can use special function **save** to edit-in-place the input data.
85
91
 
86
92
  ```sh
87
- echo '"https://medv.io/*"' | fx 'fetch' '.text()'
93
+ fx file.json 'x.name = x.name.toUpperCase(), x' 'save'
88
94
  ```
89
95
 
96
+ The edited data will be saved to the same `file.json` file.
97
+
90
98
  ### Syntactic Sugar
91
99
 
92
100
  Fx has a shortcut for the map function. Fox example, `this.map(x => x.commit.message)`
@@ -101,28 +109,32 @@ echo '[{"name": "world"}]' | fx 'map(`Hello, ${x.name}!`)'
101
109
  ```
102
110
 
103
111
  Fx has a special syntax for the flatMap function. Fox example,
104
- `.flatMap(x => x.labels.flatMap(x => x.name))` can be rewritten in the next way.
112
+ `.issues.flatMap(x => x.labels.flatMap(x => x))` can be rewritten in the next way.
105
113
 
106
114
  ```sh
107
- curl https://api.github.com/repos/kubernetes/kubernetes/issues | fx '.[].labels[].name'
115
+ curl https://fx.wtf/example.json | fx '.issues[].labels[]'
108
116
  ```
109
117
 
110
118
  ### .fxrc.js
111
119
 
112
- Fx supports `.fxrc.js` file in the current directory or in the home directory.
120
+ Fx supports `.fxrc.js` file in the current directory, or in the home directory, or in XDG config directory.
113
121
 
114
122
  Put the next code in the `.fxrc.js` file to make `myFunction` available in the fx.
115
123
 
116
124
  ```js
117
- global.myFunction = x => x + 1
125
+ function addOne(x) {
126
+ return x + 1
127
+ }
118
128
  ```
119
129
 
120
- Now you can use `myFunction` in the fx.
130
+ Now you can use `addOne` in the fx.
121
131
 
122
132
  ```sh
123
- echo '1' | fx 'myFunction'
133
+ echo '1' | fx addOne
124
134
  ```
125
135
 
136
+ If you would like to create global variables use `var` instead of `let` or `const`.
137
+
126
138
  ## License
127
139
 
128
140
  [MIT](../LICENSE)
package/index.js CHANGED
@@ -4,6 +4,7 @@
4
4
  void async function main() {
5
5
  const os = await import('node:os')
6
6
  const fs = await import('node:fs')
7
+ const path = await import('node:path')
7
8
  const process = await import('node:process')
8
9
 
9
10
  let flagHelp = false
@@ -26,8 +27,7 @@ void async function main() {
26
27
 
27
28
  const theme = themes(process.stdout.isTTY ? (process.env.FX_THEME || '1') : '0')
28
29
 
29
- await importFxrc(process.cwd())
30
- await importFxrc(os.homedir())
30
+ loadFxrc(os, fs, path, process)
31
31
 
32
32
  let fd = 0 // stdin
33
33
  if (args.length > 0) {
@@ -35,6 +35,7 @@ void async function main() {
35
35
  isFile(fs, args[0]) ? args.shift() :
36
36
  isFile(fs, args.at(-1)) ? args.pop() : false
37
37
  if (filename) {
38
+ globalThis.__file__ = filename
38
39
  fd = fs.openSync(filename, 'r')
39
40
  if (!flagYaml) flagYaml = /\.ya?ml$/i.test(filename)
40
41
  }
@@ -138,6 +139,7 @@ function transpile(code) {
138
139
  }
139
140
 
140
141
  async function run(json, code) {
142
+ const fs = await import('node:fs')
141
143
  const fn = eval(code).call(json)
142
144
 
143
145
  return apply(fn, json)
@@ -241,6 +243,12 @@ async function run(json, code) {
241
243
  }
242
244
  throw new Error(`Cannot list ${typeof x}`)
243
245
  }
246
+
247
+ function save(x) {
248
+ if (!globalThis.__file__) throw new Error('Specify a file as the first argument to be able to save: fx file.json ...')
249
+ fs.writeFileSync(globalThis.__file__, JSON.stringify(x, null, 2))
250
+ return x
251
+ }
244
252
  }
245
253
 
246
254
  async function read(fd = 0) {
@@ -683,6 +691,37 @@ async function importFxrc(path) {
683
691
  }
684
692
  }
685
693
 
694
+ function loadFxrc(os, fs, path, process) {
695
+ let script = ''
696
+
697
+ const cwd = process.cwd()
698
+ const home = os.homedir()
699
+ const xdgHome = process.env.XDG_CONFIG_HOME || path.join(home, '.config')
700
+ const xdgDirsEnv = process.env.XDG_CONFIG_DIRS || '/etc/xdg'
701
+
702
+ const paths = [path.join(cwd, '.fxrc.js')]
703
+ paths.push(path.join(home, '.fxrc.js'))
704
+ paths.push(path.join(xdgHome, 'fx', '.fxrc.js'))
705
+ for (const dir of xdgDirsEnv.split(':')) {
706
+ paths.push(path.join(dir, 'fx', '.fxrc.js'))
707
+ }
708
+
709
+ for (const filePath of paths) {
710
+ try {
711
+ const stat = fs.statSync(filePath)
712
+ if (stat.isDirectory()) continue
713
+
714
+ const data = fs.readFileSync(filePath, 'utf8')
715
+ script += data + '\n'
716
+ } catch (err) {
717
+ if (err.code === 'ENOENT') continue
718
+ throw new Error(`read ${filePath}: ${err.message}`)
719
+ }
720
+ }
721
+
722
+ eval?.(script)
723
+ }
724
+
686
725
  function printUsage() {
687
726
  const usage = `Usage
688
727
  fx [flags] [code...]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fx",
3
- "version": "35.0.0",
3
+ "version": "36.0.1",
4
4
  "bin": {
5
5
  "fx": "index.js"
6
6
  },