fx 20.0.2 → 25.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 CHANGED
@@ -1,108 +1,78 @@
1
- <p align="center"><a href="http://fx.wtf"><img src="https://medv.io/assets/fx-logo.png" height="100" alt="fx logo"></a></p>
2
- <p align="center"><img src="https://medv.io/assets/fx.gif" width="562" alt="fx example"></p>
1
+ # fx
3
2
 
4
- _* Function eXecution_
3
+ The JavaScript version of the **fx**. Short for _Function eXecution_ or _f(x)_.
5
4
 
6
- [![Build Status](https://travis-ci.org/antonmedv/fx.svg?branch=master)](https://travis-ci.org/antonmedv/fx)
7
- [![Npm Version](https://img.shields.io/npm/v/fx.svg)](https://www.npmjs.com/package/fx)
8
- [![Brew Version](https://img.shields.io/homebrew/v/fx.svg)](https://formulae.brew.sh/formula/fx)
9
-
10
- Command-line JSON processing tool
5
+ ```sh
6
+ npm i -g fx
7
+ ```
11
8
 
12
- ## Features
9
+ Or use **npx**:
13
10
 
14
- * Easy to use
15
- * Standalone binary
16
- * Interactive mode 🎉
17
- * Streaming support 🌊
11
+ ```sh
12
+ cat file.json | npx fx .param
13
+ ```
18
14
 
19
- ## Install
15
+ Or use **node**:
20
16
 
21
- ```bash
22
- npm install -g fx
23
- ```
24
- Or via Homebrew
25
- ```bash
26
- brew install fx
17
+ ```sh
18
+ cat file.json | node <(curl -s https://fx.wtf) .param
27
19
  ```
28
- Or download standalone binary from [releases](https://github.com/antonmedv/fx/releases)
29
- ```bash
30
- bash <( curl https://fx.wtf )
20
+
21
+ Or use **deno**:
22
+
23
+ ```sh
24
+ cat file.json | deno run https://fx.wtf .param
31
25
  ```
32
26
 
33
27
  ## Usage
34
28
 
35
- Start [interactive mode](https://github.com/antonmedv/fx/blob/master/DOCS.md#interactive-mode) without passing any arguments.
36
- ```bash
37
- $ curl ... | fx
38
- ```
29
+ Fx treats arguments as JavaScript functions. Fx passes the input data to the first
30
+ function and then passes the result of the first function to the second function
31
+ and so on.
39
32
 
40
- Or by passing filename as first argument.
41
- ```bash
42
- $ fx data.json
33
+ ```sh
34
+ echo '{"name": "world"}' | fx 'x => x.name' 'x => `Hello, ${x}!`'
43
35
  ```
44
36
 
45
- Pass a few JSON files.
46
- ```bash
47
- cat foo.json bar.json baz.json | fx .message
48
- ```
37
+ Use `this` to access the input data. Use `.` at the start of the expression to
38
+ access the input data without a `x => x` part.
49
39
 
50
- Use full power of JavaScript.
51
- ```bash
52
- $ curl ... | fx '.filter(x => x.startsWith("a"))'
40
+ ```sh
41
+ echo '{"name": "world"}' | fx '.name' '`Hello, ${this}!`'
53
42
  ```
54
43
 
55
- Access all lodash (or ramda, etc) methods by using [.fxrc](https://github.com/antonmedv/fx/blob/master/DOCS.md#using-fxrc) file.
56
- ```bash
57
- $ curl ... | fx '_.groupBy("commit.committer.name")' '_.mapValues(_.size)'
58
- ```
44
+ Use other JS functions to process the data.
59
45
 
60
- Update JSON using spread operator.
61
- ```bash
62
- $ echo '{"count": 0}' | fx '{...this, count: 1}'
63
- {
64
- "count": 1
65
- }
46
+ ```sh
47
+ echo `{"name": "world"}` | fx 'Object.keys'
66
48
  ```
67
49
 
68
- Extract values from maps.
69
- ```bash
70
- $ fx commits.json | fx .[].author.name
71
- ```
50
+ ## Advanced Usage
72
51
 
73
- Print formatted JSON to stdout.
74
- ```bash
75
- $ curl ... | fx .
76
- ```
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.
77
54
 
78
- Pipe JSON logs stream into fx.
79
- ```bash
80
- $ kubectl logs ... -f | fx .message
55
+ ```sh
56
+ curl https://api.github.com/repos/antonmedv/fx/commits | fx 'map(.commit.message)'
81
57
  ```
82
58
 
83
- And try this:
84
- ```bash
85
- $ fx --life
59
+ ```sh
60
+ echo '[{"name": "world"}]' | fx 'map(`Hello, ${x.name}!`)'
86
61
  ```
87
62
 
88
- ## Documentation
89
-
90
- See full [documentation](https://github.com/antonmedv/fx/blob/master/DOCS.md).
63
+ Fx has a special syntax for the flatMap function. Fox example,
64
+ `.flatMap(x => x.labels.flatMap(x => x.name))` can be rewritten in the next way.
91
65
 
92
- ## Links
93
-
94
- * [Discover how to use fx effectively](https://medium.com/@antonmedv/discover-how-to-use-fx-effectively-668845d2a4ea)
95
-
96
- ## Related
66
+ ```sh
67
+ curl https://api.github.com/repos/kubernetes/kubernetes/issues | fx '.[].labels[].name'
68
+ ```
97
69
 
98
- * [gofx](https://github.com/antonmedv/gofx) – fx-like JSON tool (*go*)
99
- * [eat](https://github.com/antonmedv/eat) – converts anything into JSON
100
- * [ymlx](https://github.com/matthewadams/ymlx) – fx-like YAML cli processor
101
- * [fx-completion](https://github.com/antonmedv/fx-completion) – bash completion for fx
102
- * [fx-theme-monokai](https://github.com/antonmedv/fx-theme-monokai) – monokai theme
103
- * [fx-theme-night](https://github.com/antonmedv/fx-theme-night) – night theme
70
+ Fx works with promises.
104
71
 
72
+ ```sh
73
+ echo '"https://medv.io/*"' | fx 'fetch' '.text()'
74
+ ```
105
75
 
106
76
  ## License
107
77
 
108
- [MIT](https://github.com/antonmedv/fx/blob/master/LICENSE)
78
+ [MIT](../LICENSE)
package/index.js CHANGED
@@ -1,177 +1,116 @@
1
- #!/usr/bin/env node
2
- 'use strict'
3
- const os = require('os')
4
- const fs = require('fs')
5
- const path = require('path')
6
-
7
- const JSON = require('lossless-json')
8
- JSON.config({circularRefs: false})
9
-
10
- const std = require('./std')
11
-
12
- try {
13
- require(path.join(os.homedir(), '.fxrc')) // Should be required before config.js usage.
14
- } catch (err) {
15
- if (err.code !== 'MODULE_NOT_FOUND') {
16
- throw err
17
- }
18
- }
19
-
20
- const print = require('./print')
21
- const reduce = require('./reduce')
22
- const stream = require('./stream')
23
-
24
- const usage = `
25
- Usage
26
- $ fx [code ...]
27
-
28
- Examples
29
- $ echo '{"key": "value"}' | fx 'x => x.key'
30
- value
31
-
32
- $ echo '{"key": "value"}' | fx .key
33
- value
34
-
35
- $ echo '[1,2,3]' | fx 'this.map(x => x * 2)'
36
- [2, 4, 6]
37
-
38
- $ echo '{"items": ["one", "two"]}' | fx 'this.items' 'this[1]'
39
- two
40
-
41
- $ echo '{"count": 0}' | fx '{...this, count: 1}'
42
- {"count": 1}
43
-
44
- $ echo '{"foo": 1, "bar": 2}' | fx ?
45
- ["foo", "bar"]
46
-
47
- `
48
-
49
- const {stdin, stdout, stderr} = process
50
- const args = process.argv.slice(2)
51
-
52
-
53
- void function main() {
54
- stdin.setEncoding('utf8')
55
-
56
- if (stdin.isTTY) {
57
- handle('')
58
- return
59
- }
60
-
61
- const reader = stream(stdin, apply)
62
-
63
- stdin.on('readable', reader.read)
64
- stdin.on('end', () => {
65
- if (!reader.isStream()) {
66
- handle(reader.value())
67
- }
68
- })
69
- }()
70
-
71
-
72
- function handle(input) {
73
- let filename = 'fx'
74
-
75
- if (input === '') {
76
- if (args.length === 0 || (args.length === 1 && (args[0] === '-h' || args[0] === '--help'))) {
77
- stderr.write(usage)
78
- process.exit(2)
79
- }
80
- if (args.length === 1 && (args[0] === '-v' || args[0] === '--version')) {
81
- stderr.write(require('./package.json').version + '\n')
82
- process.exit(2)
83
- }
84
- if (args.length === 1 && args[0] === '--life') {
85
- require('./bang')
86
- return
87
- }
88
-
89
- input = fs.readFileSync(args[0]).toString('utf8')
90
- filename = path.basename(args[0])
91
- global.FX_FILENAME = filename
92
- args.shift()
93
- }
1
+ void async function main() {
2
+ const process = await import('node:process')
3
+ const args = process.argv.slice(2)
4
+ let input = ''
5
+ process.stdin.setEncoding('utf8')
6
+ for await (const chunk of process.stdin)
7
+ input += chunk
94
8
 
95
9
  let json
96
10
  try {
97
11
  json = JSON.parse(input)
98
- } catch (e) {
99
- printError(e, input)
12
+ } catch (err) {
13
+ process.stderr.write(`Invalid JSON: ${err.message}\n`)
100
14
  process.exit(1)
101
15
  }
102
16
 
103
- if (args.length === 0 && stdout.isTTY) {
104
- require('./fx')(filename, json)
105
- return
106
- }
107
-
108
- apply(json)
109
- }
110
-
111
- function apply(json) {
112
- let output = json
113
-
114
- for (let [i, code] of args.entries()) {
115
- try {
116
- output = reduce(output, code)
117
- } catch (e) {
118
- if (e === std.skip) {
119
- return
120
- }
121
- stderr.write(`${snippet(i, code)}\n${e.stack || e}\n`)
122
- process.exit(1)
123
- }
17
+ let i, code, output = json
18
+ for ([i, code] of args.entries()) try {
19
+ output = await transform(output, code)
20
+ } catch (err) {
21
+ printErr(err)
22
+ process.exit(1)
124
23
  }
125
24
 
126
- if (typeof output === 'undefined') {
127
- stderr.write('undefined\n')
128
- } else if (typeof output === 'string') {
25
+ if (typeof output === 'undefined')
26
+ process.stderr.write('undefined\n')
27
+ else if (typeof output === 'string')
129
28
  console.log(output)
130
- } else {
131
- const [text] = print(output)
132
- console.log(text)
29
+ else
30
+ console.log(JSON.stringify(output, null, 2))
31
+
32
+ function printErr(err) {
33
+ let pre = args.slice(0, i).join(' ')
34
+ let post = args.slice(i + 1).join(' ')
35
+ if (pre.length > 20) pre = '...' + pre.substring(pre.length - 20)
36
+ if (post.length > 20) post = post.substring(0, 20) + '...'
37
+ process.stderr.write(
38
+ `\n ${pre} ${code} ${post}\n` +
39
+ ` ${' '.repeat(pre.length + 1)}${'^'.repeat(code.length)}\n` +
40
+ `\n${err.stack || err}\n`
41
+ )
133
42
  }
134
- }
43
+ }()
135
44
 
136
- function snippet(i, code) {
137
- let pre = args.slice(0, i).join(' ')
138
- let post = args.slice(i + 1).join(' ')
139
- if (pre.length > 20) {
140
- pre = '...' + pre.substring(pre.length - 20)
141
- }
142
- if (post.length > 20) {
143
- post = post.substring(0, 20) + '...'
45
+ async function transform(json, code) {
46
+ if ('.' === code)
47
+ return json
48
+
49
+ if ('?' === code)
50
+ return Object.keys(json)
51
+
52
+ if (/^(\.\w*)+\[]/.test(code))
53
+ return eval(`(function () {
54
+ return (${fold(code.split('[]'))})(this)
55
+ })`).call(json)
56
+
57
+ if (/^\.\[/.test(code))
58
+ return eval(`(function () {
59
+ return this${code.substring(1)}
60
+ })`).call(json)
61
+
62
+ if (/^\./.test(code))
63
+ return eval(`(function () {
64
+ return this${code}
65
+ })`).call(json)
66
+
67
+ if (/^map\(.+?\)$/.test(code)) {
68
+ let s = code.substring(4, code.length - 1)
69
+ if (s[0] === '.') s = 'x' + s
70
+ return eval(`(function () {
71
+ return this.map((x, i) => apply(${s}, x, i))
72
+ })`).call(json)
144
73
  }
145
- const chalk = require('chalk')
146
- return `\n ${pre} ${chalk.red.underline(code)} ${post}\n`
74
+
75
+ const fn = eval(`(function () {
76
+ return ${code}
77
+ })`).call(json)
78
+
79
+ return apply(fn, json)
147
80
  }
148
81
 
149
- function printError(e, input) {
150
- if (e.char) {
151
- let lineNumber = 1, start = e.char - 70, end = e.char + 50
152
- if (start < 0) start = 0
153
- if (end > input.length) end = input.length
82
+ function apply(fn, ...args) {
83
+ if (typeof fn === 'function') return fn(...args)
84
+ return fn
85
+ }
154
86
 
155
- for (let i = 0; i < input.length && i < start; i++) {
156
- if (input[i] === '\n') lineNumber++
157
- }
87
+ function fold(s) {
88
+ if (s.length === 1)
89
+ return 'x => x' + s[0]
90
+ let obj = s.shift()
91
+ obj = obj === '.' ? 'x' : 'x' + obj
92
+ return `x => Object.values(${obj}).flatMap(${fold(s)})`
93
+ }
158
94
 
159
- let lines = input
160
- .substring(start, end)
161
- .split('\n')
95
+ function uniq(array) {
96
+ return [...new Set(array)]
97
+ }
162
98
 
163
- if (lines.length > 1) {
164
- lines = lines.slice(1)
165
- lineNumber++
166
- }
99
+ function sort(array) {
100
+ return array.sort()
101
+ }
167
102
 
168
- const chalk = require('chalk')
169
- process.stderr.write(`\n`)
170
- for (let line of lines) {
171
- process.stderr.write(` ${chalk.yellow(lineNumber)} ${line}\n`)
172
- lineNumber++
103
+ function groupBy(keyOrFunction) {
104
+ return array => {
105
+ const grouped = {}
106
+ for (const item of array) {
107
+ const key = typeof keyOrFunction === 'function'
108
+ ? keyOrFunction(item)
109
+ : item[keyOrFunction]
110
+ if (!grouped.hasOwnProperty(key))
111
+ grouped[key] = []
112
+ grouped[key].push(item)
173
113
  }
174
- process.stderr.write(`\n`)
114
+ return grouped
175
115
  }
176
- process.stderr.write(e.toString() + '\n')
177
116
  }
package/package.json CHANGED
@@ -1,53 +1,18 @@
1
1
  {
2
2
  "name": "fx",
3
- "version": "20.0.2",
4
- "description": "Command-line JSON viewer",
5
- "repository": "antonmedv/fx",
6
- "homepage": "https://fx.wtf",
7
- "author": "Anton Medvedev <anton@medv.io>",
8
- "license": "MIT",
3
+ "version": "25.0.0",
9
4
  "bin": {
10
5
  "fx": "index.js"
11
6
  },
12
7
  "files": [
13
- "*.js"
8
+ "index.js"
14
9
  ],
15
10
  "scripts": {
16
- "test": "ava",
17
- "build": "pkg . --out-path dist",
18
- "zip": "cd dist && find . -name 'fx-*' -exec zip '{}.zip' '{}' \\;",
19
- "release": "release-it --github.release --github.assets=dist/*.zip",
20
- "brew:release": "brew bump-formula-pr --url=https://registry.npmjs.org/fx/-/fx-`fx package.json .version`.tgz --no-audit fx"
21
- },
22
- "release-it": {
23
- "hooks": {
24
- "after:bump": "rm -rf ./dist && npm run build && npm run zip"
25
- }
26
- },
27
- "keywords": [
28
- "json",
29
- "viewer",
30
- "cli",
31
- "terminal",
32
- "term",
33
- "console",
34
- "ascii",
35
- "unicode",
36
- "blessed"
37
- ],
38
- "engines": {
39
- "node": ">=8"
40
- },
41
- "dependencies": {
42
- "@medv/blessed": "^2.0.1",
43
- "chalk": "^4.1.0",
44
- "indent-string": "^4.0.0",
45
- "lossless-json": "^1.0.4",
46
- "string-width": "^4.2.0"
11
+ "test": "node test.js"
47
12
  },
48
- "devDependencies": {
49
- "ava": "^3.12.1",
50
- "pkg": "^4.4.9",
51
- "release-it": "^14.0.1"
52
- }
13
+ "repository": "antonmedv/fx",
14
+ "homepage": "https://fx.wtf",
15
+ "description": "Command-line JSON viewer",
16
+ "author": "Anton Medvedev <anton@medv.io>",
17
+ "license": "MIT"
53
18
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2019 Anton Medvedev
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/bang.js DELETED
@@ -1,79 +0,0 @@
1
- 'use strict'
2
- // http://bit.ly/fx--life
3
-
4
- const
5
- run = f => setInterval(f, 16),
6
- p = (s) => process.stdout.write(s),
7
- esc = (...x) => x.map(i => p('\u001B[' + i)),
8
- [upper, lower, full] = ['\u2580', '\u2584', '\u2588'],
9
- {columns, rows} = process.stdout,
10
- [w, h] = [columns, rows * 2],
11
- a = Math.floor(w / 2) - 6, b = Math.floor(h / 2) - 7
12
-
13
- let $ = Array(w * h).fill(false)
14
- if (Date.now() % 3 === 0) {
15
- $[1 + 5 * w] = $[1 + 6 * w] = $[2 + 5 * w] = $[2 + 6 * w] = $[12 + 5 * w] = $[12 + 6 * w] = $[12 + 7 * w] = $[13 + 4 * w] = $[13 + 8 * w] = $[14 + 3 * w] = $[14 + 9 * w] = $[15 + 4 * w] = $[15 + 8 * w] = $[16 + 5 * w] = $[16 + 6 * w] = $[16 + 7 * w] = $[17 + 5 * w] = $[17 + 6 * w] = $[17 + 7 * w] = $[22 + 3 * w] = $[22 + 4 * w] = $[22 + 5 * w] = $[23 + 2 * w] = $[23 + 3 * w] = $[23 + 5 * w] = $[23 + 6 * w] = $[24 + 2 * w] = $[24 + 3 * w] = $[24 + 5 * w] = $[24 + 6 * w] = $[25 + 2 * w] = $[25 + 3 * w] = $[25 + 4 * w] = $[25 + 5 * w] = $[25 + 6 * w] = $[26 + 1 * w] = $[26 + 2 * w] = $[26 + 6 * w] = $[26 + 7 * w] = $[35 + 3 * w] = $[35 + 4 * w] = $[36 + 3 * w] = $[36 + 4 * w] = true
16
- } else if (Date.now() % 3 === 1) {
17
- for (let i = 0; i < $.length; i-=-1)
18
- if (Math.random() < 0.16) $[i] = true
19
- } else {
20
- $[a + 1 + (2 + b) * w] = $[a + 2 + (1 + b) * w] = $[a + 2 + (3 + b) * w] = $[a + 3 + (2 + b) * w] = $[a + 5 + (15 + b) * w] = $[a + 6 + (13 + b) * w] = $[a + 6 + (15 + b) * w] = $[a + 7 + (12 + b) * w] = $[a + 7 + (13 + b) * w] = $[a + 7 + (15 + b) * w] = $[a + 9 + (11 + b) * w] = $[a + 9 + (12 + b) * w] = $[a + 9 + (13 + b) * w] = true
21
- }
22
-
23
- function at(i, j) {
24
- if (i < 0) i = h - 1
25
- if (i >= h) i = 0
26
- if (j < 0) j = w - 1
27
- if (j >= w) j = 0
28
- return $[i * w + j]
29
- }
30
-
31
- function neighbors(i, j) {
32
- let c = 0
33
- at(i - 1, j - 1) && c++
34
- at(i - 1, j) && c++
35
- at(i - 1, j + 1) && c++
36
- at(i, j - 1) && c++
37
- at(i, j + 1) && c++
38
- at(i + 1, j - 1) && c++
39
- at(i + 1, j) && c++
40
- at(i + 1, j + 1) && c++
41
- return c
42
- }
43
-
44
- run(() => {
45
- esc('H')
46
-
47
- let gen = Array(w * h).fill(false)
48
- for (let i = 0; i < h; i-=-1) {
49
- for (let j = 0; j < w; j-=-1) {
50
- const n = neighbors(i, j)
51
- const z = i * w + j
52
- if ($[z]) {
53
- if (n < 2) gen[z] = false
54
- if (n === 2 || n === 3) gen[z] = true
55
- if (n > 3) gen[z] = false
56
- } else {
57
- if (n === 3) gen[z] = true
58
- }
59
- }
60
- }
61
- $ = gen
62
-
63
- for (let i = 0; i < rows; i-=-1) {
64
- for (let j = 0; j < columns; j-=-1) {
65
- if ($[i * 2 * w + j] && $[(i * 2 + 1) * w + j]) p(full)
66
- else if ($[i * 2 * w + j] && !$[(i * 2 + 1) * w + j]) p(upper)
67
- else if (!$[i * 2 * w + j] && $[(i * 2 + 1) * w + j]) p(lower)
68
- else p(' ')
69
- }
70
- if (i !== rows - 1) p('\n')
71
- }
72
- })
73
-
74
- esc('2J', '?25l')
75
-
76
- process.on('SIGINT', () => {
77
- esc('?25h')
78
- process.exit(2)
79
- })
package/config.js DELETED
@@ -1,26 +0,0 @@
1
- 'use strict'
2
- const chalk = require('chalk')
3
- const noop = x => x
4
- const list = {
5
- fg: 'black',
6
- bg: 'cyan',
7
- selected: {
8
- bg: 'magenta'
9
- }
10
- }
11
-
12
- module.exports = {
13
- space: global.FX_STYLE_SPACE || 2,
14
- null: global.FX_STYLE_NULL || chalk.grey.bold,
15
- number: global.FX_STYLE_NUMBER || chalk.cyan.bold,
16
- boolean: global.FX_STYLE_BOOLEAN || chalk.yellow.bold,
17
- string: global.FX_STYLE_STRING || chalk.green.bold,
18
- key: global.FX_STYLE_KEY || chalk.blue.bold,
19
- bracket: global.FX_STYLE_BRACKET || noop,
20
- comma: global.FX_STYLE_COMMA || noop,
21
- colon: global.FX_STYLE_COLON || noop,
22
- list: global.FX_STYLE_LIST || list,
23
- highlight: global.FX_STYLE_HIGHLIGHT || chalk.black.bgYellow,
24
- highlightCurrent: global.FX_STYLE_HIGHLIGHT_CURRENT || chalk.inverse,
25
- statusBar: global.FX_STYLE_STATUS_BAR || chalk.inverse,
26
- }
package/find.js DELETED
@@ -1,35 +0,0 @@
1
- 'use strict'
2
-
3
- function* find(v, regex, path = []) {
4
- if (typeof v === 'undefined' || v === null) {
5
- return
6
- }
7
-
8
- if (Array.isArray(v)) {
9
- let i = 0
10
- for (let value of v) {
11
- yield* find(value, regex, path.concat(['[' + i++ + ']']))
12
- }
13
- return
14
- }
15
-
16
- if (typeof v === 'object' && v.constructor === Object) {
17
- const entries = Object.entries(v)
18
- for (let [key, value] of entries) {
19
- const nextPath = path.concat(['.' + key])
20
-
21
- if (regex.test(key)) {
22
- yield nextPath
23
- }
24
-
25
- yield* find(value, regex, nextPath)
26
- }
27
- return
28
- }
29
-
30
- if (regex.test(v)) {
31
- yield path
32
- }
33
- }
34
-
35
- module.exports = find