functionalscript 0.0.186 → 0.0.187
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/btree/test.js +0 -2
- package/json/index.js +88 -0
- package/json/test.js +13 -0
- package/package.json +1 -1
- package/sequence/test.js +7 -1
- package/test.js +1 -0
package/btree/test.js
CHANGED
package/json/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const seq = require('../sequence')
|
|
2
|
+
const map = require('../map')
|
|
3
|
+
const op = require('../sequence/operator')
|
|
4
|
+
const { todo } = require('../dev')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {{
|
|
8
|
+
* readonly [k in string]: Json
|
|
9
|
+
* }} Object
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** @typedef {readonly Json[]} Array */
|
|
13
|
+
|
|
14
|
+
/** @typedef {Object|boolean|string|number|null|Array} Json */
|
|
15
|
+
|
|
16
|
+
/** @type {(value: Json) => (path: readonly string[]) => (src: Json|undefined) => Json} */
|
|
17
|
+
const addProperty = value => {
|
|
18
|
+
/** @type {(path: seq.Sequence<string>) => (src: Json|undefined) => Json} */
|
|
19
|
+
const f = path => src => {
|
|
20
|
+
const result = seq.next(path)
|
|
21
|
+
if (result === undefined) { return value }
|
|
22
|
+
const srcObject = (src === undefined || src === null || typeof src !== 'object' || src instanceof Array) ? {} : src
|
|
23
|
+
const [name, tail] = result
|
|
24
|
+
return { ...srcObject, [name]: f(tail)(srcObject[name]) }
|
|
25
|
+
}
|
|
26
|
+
return path => f(seq.fromArray(path))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @type {(kv: readonly[string, seq.Sequence<string>]) => seq.Sequence<string>} */
|
|
30
|
+
const property = ([k, v]) => {
|
|
31
|
+
let r = seq.one(JSON.stringify(k))
|
|
32
|
+
r = seq.concat(r)(seq.one(':'))
|
|
33
|
+
return seq.concat(r)(v)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
|
|
37
|
+
const commaValue = a => [seq.concat(seq.one(','))(a), commaValue]
|
|
38
|
+
|
|
39
|
+
/** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
|
|
40
|
+
const joinScan = value => [value, commaValue]
|
|
41
|
+
|
|
42
|
+
/** @type {seq.SequenceMap<seq.Sequence<string>, seq.Sequence<string>>} */
|
|
43
|
+
const join = seq.scan(joinScan)
|
|
44
|
+
|
|
45
|
+
/** @type {(object: Object) => seq.Sequence<string>} */
|
|
46
|
+
const objectStringify = object => {
|
|
47
|
+
/** @type {map.Map<seq.Sequence<string>>} */
|
|
48
|
+
let m = map.empty
|
|
49
|
+
for (const [k, v] of Object.entries(object)) {
|
|
50
|
+
m = m.set(k)(stringSeq(v))
|
|
51
|
+
}
|
|
52
|
+
const properties = join(seq.map(property)(m.entries))
|
|
53
|
+
const result = seq.concat(seq.one('{'))(seq.flat(properties))
|
|
54
|
+
return seq.concat(result)(seq.one('}'))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @type {(array: Array) => seq.Sequence<string>} */
|
|
58
|
+
const arrayStringify = array => {
|
|
59
|
+
let a = seq.flat(join(seq.map(stringSeq)(seq.fromArray(array))))
|
|
60
|
+
const s = seq.concat(seq.one('['))(a)
|
|
61
|
+
return seq.concat(s)(seq.one(']'))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** @type {(value: Json) => seq.Sequence<string>} */
|
|
65
|
+
const stringSeq = value => {
|
|
66
|
+
const x = typeof value
|
|
67
|
+
switch (typeof value) {
|
|
68
|
+
case 'boolean': { return seq.one(value ? "true" : "false") }
|
|
69
|
+
// Note: we shouldn't use JSON.stringify since it has non determenistic behavior.
|
|
70
|
+
// In particular: property order could be different.
|
|
71
|
+
case 'number': case 'string': { return seq.one(JSON.stringify(value)) }
|
|
72
|
+
default: {
|
|
73
|
+
if (value === null) { return seq.one("null") }
|
|
74
|
+
if (value instanceof Array) { return arrayStringify(value) }
|
|
75
|
+
return objectStringify(value)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @type {(value: Json) => string} */
|
|
81
|
+
const stringify = value => seq.join('')(stringSeq(value))
|
|
82
|
+
|
|
83
|
+
module.exports = {
|
|
84
|
+
/** @readonly */
|
|
85
|
+
addProperty,
|
|
86
|
+
/** @readonly */
|
|
87
|
+
stringify,
|
|
88
|
+
}
|
package/json/test.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const json = require('.')
|
|
2
|
+
|
|
3
|
+
if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
const x = json.stringify(json.addProperty("Hello")(['a'])({}))
|
|
7
|
+
if (x !== '{"a":"Hello"}') { throw x }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
const x = json.stringify(json.addProperty("Hello")(['a'])({c:[],b:12}))
|
|
12
|
+
if (x !== '{"a":"Hello","b":12,"c":[]}') { throw x }
|
|
13
|
+
}
|
package/package.json
CHANGED
package/sequence/test.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const seq = require('.')
|
|
2
2
|
const { sum } = require('./operator')
|
|
3
|
+
const op = require('./operator')
|
|
3
4
|
|
|
4
5
|
/** @type {<T>(input: seq.Sequence<T>) => void} */
|
|
5
6
|
const print = input => {
|
|
@@ -40,4 +41,9 @@ const print = input => {
|
|
|
40
41
|
const r = seq.next(x)
|
|
41
42
|
// print(x)
|
|
42
43
|
}
|
|
43
|
-
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
{
|
|
47
|
+
const x = seq.join(':')(seq.fromArray(["1", "2", "3", "4", "5", "6"]))
|
|
48
|
+
if (x !== "1:2:3:4:5:6") { throw x }
|
|
49
|
+
}
|