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/print.js DELETED
@@ -1,117 +0,0 @@
1
- 'use strict'
2
- const indent = require('indent-string')
3
- const config = require('./config')
4
-
5
- function format(value, style, highlightStyle, regexp, transform = x => x) {
6
- if (!regexp) {
7
- return style(transform(value))
8
- }
9
- const marked = value
10
- .replace(regexp, s => '<highlight>' + s + '<highlight>')
11
-
12
- return transform(marked)
13
- .split(/<highlight>/g)
14
- .map((s, i) => i % 2 !== 0 ? highlightStyle(s) : style(s))
15
- .join('')
16
- }
17
-
18
- function print(input, options = {}) {
19
- const {expanded, highlight, currentPath} = options
20
- const index = new Map()
21
- let row = 0
22
-
23
- function doPrint(v, path = '') {
24
- index.set(row, path)
25
-
26
- // Code for highlighting parts become cumbersome.
27
- // Maybe we should refactor this part.
28
- const highlightStyle = (currentPath === path) ? config.highlightCurrent : config.highlight
29
- const formatStyle = (v, style) => format(v, style, highlightStyle, highlight)
30
- const formatText = (v, style, path) => {
31
- const highlightStyle = (currentPath === path) ? config.highlightCurrent : config.highlight
32
- return format(v, style, highlightStyle, highlight, JSON.stringify)
33
- }
34
-
35
- const eol = () => {
36
- row++
37
- return '\n'
38
- }
39
-
40
- if (typeof v === 'undefined') {
41
- return void 0
42
- }
43
-
44
- if (v === null) {
45
- return formatStyle(JSON.stringify(v), config.null)
46
- }
47
-
48
- if (typeof v === 'number' && Number.isFinite(v)) {
49
- return formatStyle(JSON.stringify(v), config.number)
50
- }
51
-
52
- if (typeof v === 'object' && v.isLosslessNumber) {
53
- return formatStyle(v.toString(), config.number)
54
- }
55
-
56
- if (typeof v === 'boolean') {
57
- return formatStyle(JSON.stringify(v), config.boolean)
58
-
59
- }
60
-
61
- if (typeof v === 'string') {
62
- return formatText(v, config.string, path)
63
- }
64
-
65
- if (Array.isArray(v)) {
66
- let output = config.bracket('[')
67
- const len = v.length
68
-
69
- if (len > 0) {
70
- if (expanded && !expanded.has(path)) {
71
- output += '\u2026'
72
- } else {
73
- output += eol()
74
- let i = 0
75
- for (let item of v) {
76
- const value = typeof item === 'undefined' ? null : item // JSON.stringify compatibility
77
- output += indent(doPrint(value, path + '[' + i + ']'), config.space)
78
- output += i++ < len - 1 ? config.comma(',') : ''
79
- output += eol()
80
- }
81
- }
82
- }
83
-
84
- return output + config.bracket(']')
85
- }
86
-
87
- if (typeof v === 'object' && v.constructor === Object) {
88
- let output = config.bracket('{')
89
-
90
- const entries = Object.entries(v).filter(([key, value]) => typeof value !== 'undefined') // JSON.stringify compatibility
91
- const len = entries.length
92
-
93
- if (len > 0) {
94
- if (expanded && !expanded.has(path)) {
95
- output += '\u2026'
96
- } else {
97
- output += eol()
98
- let i = 0
99
- for (let [key, value] of entries) {
100
- const part = formatText(key, config.key, path + '.' + key) + config.colon(':') + ' ' + doPrint(value, path + '.' + key)
101
- output += indent(part, config.space)
102
- output += i++ < len - 1 ? config.comma(',') : ''
103
- output += eol()
104
- }
105
- }
106
- }
107
-
108
- return output + config.bracket('}')
109
- }
110
-
111
- return JSON.stringify(v, null, config.space)
112
- }
113
-
114
- return [doPrint(input), index]
115
- }
116
-
117
- module.exports = print
package/reduce.js DELETED
@@ -1,51 +0,0 @@
1
- 'use strict'
2
- const JSON = require('lossless-json') // override JSON for user's code
3
-
4
- function reduce(json, code) {
5
- if (process.env.FX_APPLY) {
6
- return global[process.env.FX_APPLY](code)(json)
7
- }
8
-
9
- if ('.' === code) {
10
- return json
11
- }
12
-
13
- if ('?' === code) {
14
- return Object.keys(json)
15
- }
16
-
17
- if (/^(\.\w*)+\[]/.test(code)) {
18
- function fold(s) {
19
- if (s.length === 1) {
20
- return 'x => x' + s[0]
21
- }
22
- let obj = s.shift()
23
- obj = obj === '.' ? 'x' : 'x' + obj
24
- return `x => Object.values(${obj}).flatMap(${fold(s)})`
25
- }
26
- code = fold(code.split('[]'))
27
- }
28
-
29
- if (/^\.\[/.test(code)) {
30
- return eval(`function fn() {
31
- return this${code.substring(1)}
32
- }; fn`).call(json)
33
- }
34
-
35
- if (/^\./.test(code)) {
36
- return eval(`function fn() {
37
- return this${code}
38
- }; fn`).call(json)
39
- }
40
-
41
- const fn = eval(`function fn() {
42
- return ${code}
43
- }; fn`).call(json)
44
-
45
- if (typeof fn === 'function') {
46
- return fn(json)
47
- }
48
- return fn
49
- }
50
-
51
- module.exports = reduce
package/std.js DELETED
@@ -1,33 +0,0 @@
1
- 'use strict'
2
- const JSON = require('lossless-json')
3
- const skip = Symbol('skip')
4
-
5
- function select(cb) {
6
- return json => {
7
- if (!cb(json)) {
8
- throw skip
9
- }
10
- return json
11
- }
12
- }
13
-
14
- function filter(cb) {
15
- return json => {
16
- if (cb(json)) {
17
- throw skip
18
- }
19
- return json
20
- }
21
- }
22
-
23
- function save(json) {
24
- if (!global.FX_FILENAME) {
25
- throw "No filename provided.\nTo edit-in-place, specify JSON file as first argument."
26
- }
27
- require('fs').writeFileSync(global.FX_FILENAME, JSON.stringify(json, null, 2))
28
- return json
29
- }
30
-
31
- Object.assign(exports, {skip, select, filter, save})
32
- Object.assign(global, exports)
33
- global.std = exports
package/stream.js DELETED
@@ -1,84 +0,0 @@
1
- 'use strict'
2
- const JSON = require('lossless-json')
3
-
4
- function apply(cb, input) {
5
- let json
6
- try {
7
- json = JSON.parse(input)
8
- } catch (e) {
9
- process.stderr.write(e.toString() + '\n')
10
- return
11
- }
12
- cb(json)
13
- }
14
-
15
- function stream(from, cb) {
16
- let buff = ''
17
- let lastChar = ''
18
- let len = 0
19
- let depth = 0
20
- let isString = false
21
-
22
- let count = 0
23
- let head = ''
24
- const check = (i) => {
25
- if (depth <= 0) {
26
- const input = buff.substring(0, len + i + 1)
27
-
28
- if (count > 0) {
29
- if (head !== '') {
30
- apply(cb, head)
31
- head = ''
32
- }
33
-
34
- apply(cb, input)
35
- } else {
36
- head = input
37
- }
38
-
39
- buff = buff.substring(len + i + 1)
40
- len = -i - 1
41
- count++
42
- }
43
- }
44
-
45
- return {
46
- isStream() {
47
- return count > 1
48
- },
49
- value() {
50
- return head + buff
51
- },
52
- read() {
53
- let chunk
54
-
55
- while ((chunk = from.read())) {
56
- len = buff.length
57
- buff += chunk
58
-
59
- for (let i = 0; i < chunk.length; i++) {
60
- if (isString) {
61
- if (chunk[i] === '"' && ((i === 0 && lastChar !== '\\') || (i > 0 && chunk[i - 1] !== '\\'))) {
62
- isString = false
63
- check(i)
64
- }
65
- continue
66
- }
67
-
68
- if (chunk[i] === '{' || chunk[i] === '[') {
69
- depth++
70
- } else if (chunk[i] === '}' || chunk[i] === ']') {
71
- depth--
72
- check(i)
73
- } else if (chunk[i] === '"') {
74
- isString = true
75
- }
76
- }
77
-
78
- lastChar = chunk[chunk.length - 1]
79
- }
80
- }
81
- }
82
- }
83
-
84
- module.exports = stream
package/test.js DELETED
@@ -1,85 +0,0 @@
1
- 'use strict'
2
- const test = require('ava')
3
- const {execSync} = require('child_process')
4
- const stream = require('./stream')
5
-
6
- function fx(json, code = '') {
7
- return execSync(`echo '${JSON.stringify(json)}' | node index.js ${code}`).toString('utf8')
8
- }
9
-
10
- test('pass', t => {
11
- const r = fx([{'greeting': 'hello world'}])
12
- t.deepEqual(JSON.parse(r), [{'greeting': 'hello world'}])
13
- })
14
-
15
- test('anon func', t => {
16
- const r = fx({'key': 'value'}, '\'function (x) { return x.key }\'')
17
- t.is(r, 'value\n')
18
- })
19
-
20
- test('arrow func', t => {
21
- const r = fx({'key': 'value'}, '\'x => x.key\'')
22
- t.is(r, 'value\n')
23
- })
24
-
25
- test('arrow func ()', t => {
26
- const r = fx({'key': 'value'}, '\'(x) => x.key\'')
27
- t.is(r, 'value\n')
28
- })
29
-
30
- test('this bind', t => {
31
- const r = fx([1, 2, 3, 4, 5], '\'this.map(x => x * this.length)\'')
32
- t.deepEqual(JSON.parse(r), [5, 10, 15, 20, 25])
33
- })
34
-
35
- test('chain', t => {
36
- const r = fx({'items': ['foo', 'bar']}, '\'this.items\' \'.\' \'x => x[1]\'')
37
- t.is(r, 'bar\n')
38
- })
39
-
40
- test('file argument', t => {
41
- const r = execSync(`node index.js package.json .name`).toString('utf8')
42
- t.is(r, 'fx\n')
43
- })
44
-
45
- test('stream', t => {
46
- const input = `
47
- {"index": 0} {"index": 1}
48
- {"index": 2, "quote": "\\""}
49
- {"index": 3} "Hello" "world"
50
- {"index": 6, "key": "one \\"two\\" three"}
51
- `
52
- t.plan(7 * (input.length - 1))
53
-
54
- for (let i = 0; i < input.length; i++) {
55
- const parts = [input.substring(0, i), input.substring(i)]
56
-
57
- const reader = stream(
58
- {
59
- read() {
60
- return parts.shift()
61
- }
62
- },
63
- json => {
64
- t.pass()
65
- }
66
- )
67
-
68
- reader.read()
69
- }
70
- })
71
-
72
- test('lossless number', t => {
73
- const r = execSync(`echo '{"long": 123456789012345678901}' | node index.js .long`).toString('utf8')
74
- t.is(r, '123456789012345678901\n')
75
- })
76
-
77
- test('value iterator', t => {
78
- const r = fx({master: {foo: [{bar: [{val: 1}]}]}}, '.master.foo[].bar[].val')
79
- t.deepEqual(JSON.parse(r), [1])
80
- })
81
-
82
- test('value iterator simple', t => {
83
- const r = fx([{val:1},{val:2}], '.[].val')
84
- t.deepEqual(JSON.parse(r), [1, 2])
85
- })