functionalscript 0.0.230 → 0.0.234
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/commonjs/index.js +11 -0
- package/commonjs/package/dependencies/index.js +71 -0
- package/commonjs/package/dependencies/test.js +33 -0
- package/commonjs/package/index.js +37 -0
- package/commonjs/package/test.js +14 -0
- package/commonjs/path/index.js +66 -0
- package/commonjs/path/test.js +47 -0
- package/commonjs/run/index.js +17 -0
- package/io/commonjs/index.js +28 -0
- package/io/commonjs/test.js +72 -0
- package/io/result/index.js +15 -0
- package/json/index.js +29 -29
- package/json/test.js +9 -9
- package/package.json +23 -23
- package/test.js +6 -6
- package/{sequence → types}/array/index.js +2 -2
- package/{btree → types/btree}/README.md +0 -0
- package/{btree → types/btree}/index.js +6 -6
- package/{btree → types/btree}/test.js +1 -1
- package/{cmp → types/function/compare}/index.js +6 -6
- package/{function → types/function}/index.js +0 -0
- package/{function → types/function}/operator/index.js +15 -0
- package/{map → types/map}/index.js +3 -3
- package/{map → types/map}/test.js +0 -0
- package/{object → types/object}/index.js +1 -2
- package/{object → types/object}/test.js +0 -0
- package/{option → types/option}/index.js +0 -0
- package/types/result/index.js +36 -0
- package/{sequence → types/sequence}/README.md +0 -0
- package/{sequence → types/sequence}/index.js +96 -49
- package/{sequence → types/sequence}/test.js +138 -11
- package/version.js +6 -3
- package/module-manager/README.md +0 -35
- package/module-manager/index.js +0 -110
- package/module-manager/node/index.js +0 -18
- package/module-manager/node/test.js +0 -75
- package/module-manager/test.js +0 -120
- package/result/index.js +0 -17
- package/sequence/asyncIterable/index.js +0 -111
- package/sequence/asyncIterable/test.js +0 -24
- package/sequence/iterable/index.js +0 -109
- package/sequence/iterable/test.js +0 -51
- package/sequence/operator/index.js +0 -92
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const json = require('../../../json')
|
|
2
|
+
const { isObject } = json
|
|
3
|
+
const seq = require('../../../types/sequence')
|
|
4
|
+
const { split } = require('../../path')
|
|
5
|
+
const map = require('../../../types/map')
|
|
6
|
+
|
|
7
|
+
/** @typedef {(directoryName: string) => undefined|string|Directory} Directory */
|
|
8
|
+
|
|
9
|
+
const empty = () => undefined
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {{
|
|
13
|
+
* readonly get: (dir: string) => Item|undefined
|
|
14
|
+
* readonly set: (dir: string) => (item: Item) => Map
|
|
15
|
+
* }} Map
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** @typedef {Map|string} Item */
|
|
19
|
+
|
|
20
|
+
/** @typedef {readonly[string, Map]} Pair */
|
|
21
|
+
|
|
22
|
+
/** @type {(prior: seq.Sequence<Pair>) => (dir: string) => seq.Sequence<Pair>} */
|
|
23
|
+
const get = prior => dir => {
|
|
24
|
+
const result = seq.next(prior)
|
|
25
|
+
if (result === undefined) { throw 'panic' }
|
|
26
|
+
const { first: [,m] } = result
|
|
27
|
+
const child = m.get(dir)
|
|
28
|
+
const childMap = child === undefined || typeof child === 'string' ? map.empty : child
|
|
29
|
+
/** @type {Pair} */
|
|
30
|
+
const pair = [dir, childMap]
|
|
31
|
+
return seq.sequence(pair)(prior)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @typedef {readonly[string, Item]} Result */
|
|
35
|
+
|
|
36
|
+
/** @type {(a: Result) => (b: Pair) => Result} */
|
|
37
|
+
const set = ([aDir, item]) => ([bDir, bMap]) => [bDir, bMap.set(aDir)(item)]
|
|
38
|
+
|
|
39
|
+
/** @type {(prior: Map) => (entry: json.Entry) => Map} */
|
|
40
|
+
const addDirectory = prior => ([directory, id]) => {
|
|
41
|
+
if (typeof id !== 'string') { return prior }
|
|
42
|
+
const path = split(directory)
|
|
43
|
+
const rev = seq.reduce(get)([['', prior]])(path)
|
|
44
|
+
const result = seq.next(rev)
|
|
45
|
+
if (result === undefined) { throw 'panic' }
|
|
46
|
+
const { first: [dir], tail } = result
|
|
47
|
+
const [, m] = seq.reduce(set)([dir, id])(tail)
|
|
48
|
+
if (typeof m === 'string') { return prior }
|
|
49
|
+
return m
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @type {(m: Map) => Directory} */
|
|
53
|
+
const func = m => dir => {
|
|
54
|
+
const r = m.get(dir)
|
|
55
|
+
if (typeof r !== 'object') { return r }
|
|
56
|
+
return func(r)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @type {(packageJson: json.Unknown) => Directory} */
|
|
60
|
+
const getDirectory = packageJson => {
|
|
61
|
+
if (!isObject(packageJson)) { return empty }
|
|
62
|
+
const dep = packageJson['dependencies']
|
|
63
|
+
if (dep === undefined || !isObject(dep)) { return empty }
|
|
64
|
+
const result = seq.reduce(addDirectory)(map.empty)(Object.entries(dep))
|
|
65
|
+
return func(result)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = {
|
|
69
|
+
/** @readonly */
|
|
70
|
+
getDirectory,
|
|
71
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const _ = require('.')
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
const packageJson = { dependencies: {} }
|
|
5
|
+
const dir = _.getDirectory(packageJson)
|
|
6
|
+
const r = dir('x')
|
|
7
|
+
if (r !== undefined) { throw r }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
const packageJson = { dependencies: { 'x': 'e' } }
|
|
12
|
+
const dir = _.getDirectory(packageJson)
|
|
13
|
+
const r = dir('x')
|
|
14
|
+
if (r !== 'e') { throw r }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
const packageJson = {
|
|
19
|
+
dependencies: {
|
|
20
|
+
'x/a': 'xa',
|
|
21
|
+
'x/b': 'xb'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const dir = _.getDirectory(packageJson)
|
|
25
|
+
const x = dir('x')
|
|
26
|
+
if (typeof x !== 'function') { throw x }
|
|
27
|
+
const xa = x('a')
|
|
28
|
+
if (xa !== 'xa') { throw xa }
|
|
29
|
+
const xb = x('b')
|
|
30
|
+
if (xb !== 'xb') { throw xb }
|
|
31
|
+
const xc = x('c')
|
|
32
|
+
if (xc !== undefined) { throw xc }
|
|
33
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const json = require('../../json')
|
|
2
|
+
const seq = require('../../types/sequence')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {{
|
|
6
|
+
* readonly version: string
|
|
7
|
+
* readonly dependencies?: Dependencies
|
|
8
|
+
* }} Package
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** @type {(j: json.Unknown) => j is Package} */
|
|
12
|
+
const isPackage = j => {
|
|
13
|
+
if (!json.isObject(j)) { return false }
|
|
14
|
+
if (typeof j.version !== 'string') { return false }
|
|
15
|
+
if (j.dependencies !== undefined && !isDependencies(j.dependencies)) { return false }
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {{
|
|
21
|
+
* readonly [k in string]: string
|
|
22
|
+
* }} Dependencies
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** @type {(entry: json.Entry) => boolean} */
|
|
26
|
+
const isDependency = ([,v]) => typeof v === 'string'
|
|
27
|
+
|
|
28
|
+
/** @type {(j: json.Unknown) => j is Dependencies} */
|
|
29
|
+
const isDependencies = j => {
|
|
30
|
+
if (!json.isObject(j)) { return false }
|
|
31
|
+
return seq.every(seq.map(isDependency)(Object.entries(j)))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
/** @readonly */
|
|
36
|
+
isPackage,
|
|
37
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const _ = require('.')
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
if (_.isPackage(null)) { throw 'error' }
|
|
5
|
+
if (_.isPackage({})) { throw 'error' }
|
|
6
|
+
if (_.isPackage({version:12})) { throw 'error' }
|
|
7
|
+
if (!_.isPackage({version:"12"})) { throw 'error' }
|
|
8
|
+
if (_.isPackage({version:"",dependencies:[]})) { throw 'error' }
|
|
9
|
+
if (!_.isPackage({ version: "", dependencies: {} })) { throw 'error' }
|
|
10
|
+
if (_.isPackage({ version: "", dependencies: { x: 12} })) { throw 'error' }
|
|
11
|
+
if (!_.isPackage({ version: "", dependencies: { x: "12" } })) { throw 'error' }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = {}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const seq = require("../../types/sequence")
|
|
2
|
+
const option = require("../../types/option")
|
|
3
|
+
const { compose } = require("../../types/function")
|
|
4
|
+
|
|
5
|
+
/** @typedef {readonly string[]} Items */
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {{
|
|
9
|
+
* readonly external: boolean
|
|
10
|
+
* readonly dir: boolean
|
|
11
|
+
* readonly items: Items
|
|
12
|
+
* }} Path
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** @type {(path: string) => readonly string[]} */
|
|
16
|
+
const split = path => path.split('/')
|
|
17
|
+
|
|
18
|
+
/** @type {(s: undefined|seq.Sequence<string>) => (items: string) => undefined|seq.Sequence<string>} */
|
|
19
|
+
const normItemsOp = prior => item => {
|
|
20
|
+
if (prior === undefined) { return undefined }
|
|
21
|
+
switch (item) {
|
|
22
|
+
case '': case '.': { return prior }
|
|
23
|
+
case '..': {
|
|
24
|
+
const result = seq.next(prior)
|
|
25
|
+
if (result === undefined) { return undefined }
|
|
26
|
+
return result.tail
|
|
27
|
+
}
|
|
28
|
+
default: {
|
|
29
|
+
return seq.sequence(item)(prior)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @type {(items: seq.Sequence<string>) => seq.Sequence<string>|undefined} */
|
|
35
|
+
const normItems = compose(seq.reduce(normItemsOp)([]))(option.map(seq.reverse))
|
|
36
|
+
|
|
37
|
+
/** @type {(local: string) => (path: string) => Path|undefined} */
|
|
38
|
+
const parse = local => {
|
|
39
|
+
/** @type {(path: string) => readonly[boolean, seq.Sequence<string>]} */
|
|
40
|
+
const fSeq = path => {
|
|
41
|
+
const pathSeq = split(path)
|
|
42
|
+
switch (seq.first(undefined)(pathSeq)) {
|
|
43
|
+
case '.': case '..': { return [false, seq.flat([split(local), pathSeq])] }
|
|
44
|
+
default: { return [true, pathSeq] }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** @type {(path: string) => Path|undefined} */
|
|
48
|
+
const f = path => {
|
|
49
|
+
const [external, items] = fSeq(path)
|
|
50
|
+
const n = normItems(items)
|
|
51
|
+
if (n === undefined) { return undefined }
|
|
52
|
+
return {
|
|
53
|
+
external,
|
|
54
|
+
dir: path[path.length - 1] === '/',
|
|
55
|
+
items: seq.toArray(n)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return f
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
/** @readonly */
|
|
63
|
+
split,
|
|
64
|
+
/** @readonly */
|
|
65
|
+
parse,
|
|
66
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const _ = require('.')
|
|
2
|
+
const json = require('../../json')
|
|
3
|
+
const { identity, compose } = require('../../types/function')
|
|
4
|
+
const seq = require('../../types/sequence')
|
|
5
|
+
|
|
6
|
+
const stringify = json.stringify(identity)
|
|
7
|
+
|
|
8
|
+
{
|
|
9
|
+
const result = _.parse('')('./a')
|
|
10
|
+
if (result === undefined) { throw result }
|
|
11
|
+
if (stringify(result) !== '{"external":false,"dir":false,"items":["a"]}') { throw result }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
const result = _.parse('')('./a/')
|
|
16
|
+
if (result === undefined) { throw result }
|
|
17
|
+
if (stringify(result) !== '{"external":false,"dir":true,"items":["a"]}') { throw result }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
const result = _.parse('')('..')
|
|
22
|
+
if (result !== undefined) { throw result }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
{
|
|
26
|
+
const result = _.parse('a')('')
|
|
27
|
+
if (result === undefined) { throw result }
|
|
28
|
+
if (stringify(result) !== '{"external":true,"dir":false,"items":[]}') { throw result }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
{
|
|
32
|
+
const result = _.parse('')('./a/b/.././c')
|
|
33
|
+
if (result === undefined) { throw result }
|
|
34
|
+
if (stringify(result) !== '{"external":false,"dir":false,"items":["a","c"]}') { throw result }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
const result = _.parse('x/r')('./a/b/.././c')
|
|
39
|
+
if (result === undefined) { throw result }
|
|
40
|
+
if (stringify(result) !== '{"external":false,"dir":false,"items":["x","r","a","c"]}') { throw result }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
{
|
|
44
|
+
const result = _.parse('a')('a/b/.././c')
|
|
45
|
+
if (result === undefined) { throw result }
|
|
46
|
+
if (stringify(result) !== '{"external":true,"dir":false,"items":["a","c"]}') { throw result }
|
|
47
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const result = require('../../types/result')
|
|
2
|
+
|
|
3
|
+
/** @typedef {<T>(req: Require<T>) => (prior: T) => ModuleResult<T>} Module*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template T
|
|
7
|
+
* @typedef {readonly[result.Result<unknown, unknown>, T]} ModuleResult
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @template T
|
|
12
|
+
* @typedef {(prior: T) => (path: string) => ModuleResult<T>} Require
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** @typedef {(source: string) => result.Result<Module, unknown>} Compile */
|
|
16
|
+
|
|
17
|
+
module.exports = {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const { tryCatch } = require('../result')
|
|
2
|
+
const { unwrap } = require('../../types/result')
|
|
3
|
+
const run = require('../../commonjs/run')
|
|
4
|
+
|
|
5
|
+
/** @type {(f: Function) => run.Module} */
|
|
6
|
+
const createModule = f => req => mutableInfo => {
|
|
7
|
+
/** @type {(path: string) => unknown} */
|
|
8
|
+
const mutableRequire = path => {
|
|
9
|
+
const [result, info] = req(mutableInfo)(path)
|
|
10
|
+
mutableInfo = info
|
|
11
|
+
return unwrap(result)
|
|
12
|
+
}
|
|
13
|
+
const result = tryCatch(() => {
|
|
14
|
+
const mutableModule = { exports: {} }
|
|
15
|
+
f(mutableModule, mutableRequire)
|
|
16
|
+
return mutableModule.exports
|
|
17
|
+
})
|
|
18
|
+
return [result, mutableInfo]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @type {run.Compile} */
|
|
22
|
+
const compile = source =>
|
|
23
|
+
tryCatch(() => createModule(Function('module', 'require', `"use strict";${source}`)))
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
/** @readonly */
|
|
27
|
+
compile,
|
|
28
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const _ = require('.')
|
|
2
|
+
const run = require('../../commonjs/run')
|
|
3
|
+
|
|
4
|
+
// ok:
|
|
5
|
+
{
|
|
6
|
+
const source = 'module.exports = "Hello world!"'
|
|
7
|
+
const m = _.compile(source)
|
|
8
|
+
if (m[0] !== 'ok') { throw m }
|
|
9
|
+
const [result] = m[1](() => { throw 0 })(undefined)
|
|
10
|
+
if (result[0] !== 'ok') { throw result }
|
|
11
|
+
if (result[1] !== 'Hello world!') { throw result }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// compilation error:
|
|
15
|
+
{
|
|
16
|
+
const source = '+'
|
|
17
|
+
const m = _.compile(source)
|
|
18
|
+
if (m[0] !== 'error') { throw m }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// compilation error with "use strict;":
|
|
22
|
+
{
|
|
23
|
+
const source = 'const x = 04'
|
|
24
|
+
const m = _.compile(source)
|
|
25
|
+
if (m[0] !== 'error') { throw m }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// runtime error:
|
|
29
|
+
{
|
|
30
|
+
const source = 'a = 5'
|
|
31
|
+
const m = _.compile(source)
|
|
32
|
+
if (m[0] !== 'ok') { throw m }
|
|
33
|
+
const [result] = m[1](() => { throw 0 })(undefined)
|
|
34
|
+
if (result[0] !== 'error') { throw result }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//
|
|
38
|
+
{
|
|
39
|
+
const depSource = 'module.exports = 137'
|
|
40
|
+
const d = _.compile(depSource)
|
|
41
|
+
if (d[0] !== 'ok') { throw d }
|
|
42
|
+
|
|
43
|
+
/** @type {run.Require<number>} */
|
|
44
|
+
const req = prior => path => {
|
|
45
|
+
if (path !== 'm') { throw path }
|
|
46
|
+
return d[1](req)(prior + 1)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let info = 0
|
|
50
|
+
{
|
|
51
|
+
const source = 'module.exports = require("m") + 42'
|
|
52
|
+
const m = _.compile(source)
|
|
53
|
+
if (m[0] !== 'ok') { throw m }
|
|
54
|
+
|
|
55
|
+
const [result, newInfo] = m[1](req)(info)
|
|
56
|
+
if (result[0] !== 'ok') { throw result }
|
|
57
|
+
if (result[1] !== 179) { throw result }
|
|
58
|
+
info = newInfo
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
const source = 'module.exports = require("x") + 42'
|
|
63
|
+
const m = _.compile(source)
|
|
64
|
+
if (m[0] !== 'ok') { throw m }
|
|
65
|
+
|
|
66
|
+
const [result, infox] = m[1](req)(info)
|
|
67
|
+
if (result[0] !== 'error') { throw result }
|
|
68
|
+
if (infox !== 1) { throw info }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const result = require('../../types/result')
|
|
2
|
+
|
|
3
|
+
/** @type {<T>(f: () => T) => result.Result<T, unknown>} */
|
|
4
|
+
const tryCatch = f => {
|
|
5
|
+
try {
|
|
6
|
+
return result.ok(f())
|
|
7
|
+
} catch (e) {
|
|
8
|
+
return result.error(e)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
/** @readonly */
|
|
14
|
+
tryCatch,
|
|
15
|
+
}
|
package/json/index.js
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
const seq = require('../sequence')
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const { compose } = require('../function')
|
|
1
|
+
const seq = require('../types/sequence')
|
|
2
|
+
const object = require('../types/object')
|
|
3
|
+
const array = require('../types/array')
|
|
4
|
+
const { todo } = require('../dev')
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* @typedef {{
|
|
9
|
-
* readonly [k in string]:
|
|
8
|
+
* readonly [k in string]: Unknown
|
|
10
9
|
* }} Object
|
|
11
10
|
*/
|
|
12
11
|
|
|
13
|
-
/** @typedef {readonly
|
|
12
|
+
/** @typedef {readonly Unknown[]} Array */
|
|
14
13
|
|
|
15
|
-
/** @typedef {Object|boolean|string|number|null|Array}
|
|
14
|
+
/** @typedef {Object|boolean|string|number|null|Array} Unknown */
|
|
16
15
|
|
|
17
|
-
/** @type {(value:
|
|
18
|
-
const
|
|
19
|
-
/** @type {(path: seq.Sequence<string>) => (src:
|
|
16
|
+
/** @type {(value: Unknown) => (path: seq.Sequence<string>) => (src: Unknown|undefined) => Unknown} */
|
|
17
|
+
const setProperty = value => {
|
|
18
|
+
/** @type {(path: seq.Sequence<string>) => (src: Unknown|undefined) => Unknown} */
|
|
20
19
|
const f = path => src => {
|
|
21
20
|
const result = seq.next(path)
|
|
22
21
|
if (result === undefined) { return value }
|
|
@@ -45,11 +44,8 @@ const boolSerialize = value => value ? trueSerialize : falseSerialize
|
|
|
45
44
|
const colon = [':']
|
|
46
45
|
const comma = [',']
|
|
47
46
|
|
|
48
|
-
/** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
|
|
49
|
-
const commaValue = a => [seq.concat(comma, a), commaValue]
|
|
50
|
-
|
|
51
47
|
/** @type {seq.FoldOperator<seq.Sequence<string>>} */
|
|
52
|
-
const joinOp = a => b => seq.
|
|
48
|
+
const joinOp = a => b => seq.flat([a, comma, b])
|
|
53
49
|
|
|
54
50
|
/** @type {(input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
|
|
55
51
|
const join = seq.fold(joinOp)([])
|
|
@@ -58,26 +54,27 @@ const join = seq.fold(joinOp)([])
|
|
|
58
54
|
const list = open => close => {
|
|
59
55
|
const seqOpen = [open]
|
|
60
56
|
const seqClose = [close]
|
|
61
|
-
return input => seq.
|
|
57
|
+
return input => seq.flat([seqOpen, join(input), seqClose])
|
|
62
58
|
}
|
|
63
59
|
|
|
64
60
|
const objectList = list('{')('}')
|
|
65
61
|
|
|
66
62
|
const arrayList = list('[')(']')
|
|
67
63
|
|
|
68
|
-
/** @typedef {object.Entry<
|
|
64
|
+
/** @typedef {object.Entry<Unknown>} Entry*/
|
|
69
65
|
|
|
70
66
|
/** @typedef {(seq.Sequence<Entry>)} Entries */
|
|
71
67
|
|
|
72
68
|
/** @typedef {(entries: Entries) => Entries} MapEntries */
|
|
73
69
|
|
|
74
|
-
/** @type {(mapEntries: MapEntries) => (value:
|
|
70
|
+
/** @type {(mapEntries: MapEntries) => (value: Unknown) => seq.Sequence<string>} */
|
|
75
71
|
const serialize = sort => {
|
|
76
|
-
/** @type {(kv: readonly[string,
|
|
77
|
-
const propertySerialize = ([k, v]) => seq.
|
|
72
|
+
/** @type {(kv: readonly[string, Unknown]) => seq.Sequence<string>} */
|
|
73
|
+
const propertySerialize = ([k, v]) => seq.flat([
|
|
78
74
|
stringSerialize(k),
|
|
79
75
|
colon,
|
|
80
|
-
f(v)
|
|
76
|
+
f(v)
|
|
77
|
+
])
|
|
81
78
|
/** @type {(object: Object) => seq.Sequence<string>} */
|
|
82
79
|
const objectSerialize = input => {
|
|
83
80
|
const entries = Object.entries(input)
|
|
@@ -91,7 +88,7 @@ const serialize = sort => {
|
|
|
91
88
|
const serializedEntries = seq.map(f)(input)
|
|
92
89
|
return arrayList(serializedEntries)
|
|
93
90
|
}
|
|
94
|
-
/** @type {(value:
|
|
91
|
+
/** @type {(value: Unknown) => seq.Sequence < string >} */
|
|
95
92
|
const f = value => {
|
|
96
93
|
switch (typeof value) {
|
|
97
94
|
case 'boolean': { return boolSerialize(value) }
|
|
@@ -108,28 +105,31 @@ const serialize = sort => {
|
|
|
108
105
|
}
|
|
109
106
|
|
|
110
107
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* The standard `JSON.stringify` rules determines by
|
|
108
|
+
* The standard `JSON.stringify` rules determined by
|
|
114
109
|
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
|
|
115
110
|
*
|
|
116
|
-
* @type {(mapEntries: MapEntries) => (value:
|
|
111
|
+
* @type {(mapEntries: MapEntries) => (value: Unknown) => string}
|
|
117
112
|
*/
|
|
118
113
|
const stringify = sort => value => {
|
|
119
114
|
const _s = serialize(sort)(value)
|
|
120
115
|
return seq.join('')(_s)
|
|
121
116
|
}
|
|
122
117
|
|
|
123
|
-
/** @type {(value: string) =>
|
|
118
|
+
/** @type {(value: string) => Unknown} */
|
|
124
119
|
const parse = value => JSON.parse(value)
|
|
125
120
|
|
|
121
|
+
/** @type {(value: Unknown) => value is Object} */
|
|
122
|
+
const isObject = value => typeof value === 'object' && value !== null && !(value instanceof Array)
|
|
123
|
+
|
|
126
124
|
module.exports = {
|
|
127
125
|
/** @readonly */
|
|
128
|
-
|
|
126
|
+
setProperty,
|
|
129
127
|
/** @readonly */
|
|
130
128
|
stringify,
|
|
131
129
|
/** @readonly */
|
|
132
130
|
serialize,
|
|
133
131
|
/** @readonly */
|
|
134
132
|
parse,
|
|
135
|
-
|
|
133
|
+
/** @readonly */
|
|
134
|
+
isObject,
|
|
135
|
+
}
|
package/json/test.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
const json = require('.')
|
|
2
|
-
const { sort } = require('../object')
|
|
3
|
-
const { identity } = require('../function')
|
|
2
|
+
const { sort } = require('../types/object')
|
|
3
|
+
const { identity } = require('../types/function')
|
|
4
4
|
|
|
5
|
-
if (json.
|
|
5
|
+
if (json.setProperty("Hello")([])({}) !== "Hello") { throw 'error' }
|
|
6
6
|
|
|
7
7
|
{
|
|
8
|
-
const r = json.
|
|
8
|
+
const r = json.setProperty("Hello")(['a'])({})
|
|
9
9
|
const x = json.stringify(sort)(r)
|
|
10
10
|
if (x !== '{"a":"Hello"}') { throw x }
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
{
|
|
14
|
-
const x = json.stringify(identity)(json.
|
|
14
|
+
const x = json.stringify(identity)(json.setProperty("Hello")(['a'])({}))
|
|
15
15
|
if (x !== '{"a":"Hello"}') { throw x }
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
{
|
|
19
|
-
const x = json.stringify(sort)(json.
|
|
19
|
+
const x = json.stringify(sort)(json.setProperty("Hello")(['a'])({c:[],b:12}))
|
|
20
20
|
if (x !== '{"a":"Hello","b":12,"c":[]}') { throw x }
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
{
|
|
24
|
-
const x = json.stringify(identity)(json.
|
|
24
|
+
const x = json.stringify(identity)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }))
|
|
25
25
|
if (x !== '{"c":[],"b":12,"a":"Hello"}') { throw x }
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
{
|
|
29
29
|
const _0 = { a: { y: [24] }, c: [], b: 12 }
|
|
30
|
-
const _1 = json.
|
|
30
|
+
const _1 = json.setProperty("Hello")(['a', 'x'])(_0)
|
|
31
31
|
const _2 = json.stringify(sort)(_1)
|
|
32
32
|
if (_2 !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') { throw _2 }
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
{
|
|
36
36
|
const _0 = { a: { y: [24] }, c: [], b: 12 }
|
|
37
|
-
const _1 = json.
|
|
37
|
+
const _1 = json.setProperty("Hello")(['a', 'x'])(_0)
|
|
38
38
|
const _2 = json.stringify(identity)(_1)
|
|
39
39
|
if (_2 !== '{"a":{"y":[24],"x":"Hello"},"c":[],"b":12}') { throw _2 }
|
|
40
40
|
}
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
"name": "functionalscript",
|
|
3
|
+
"version": "0.0.234",
|
|
4
|
+
"description": "FunctionalScript is a functional subset of JavaScript",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"tsc": "tsc",
|
|
8
|
+
"test": "tsc && npm run test-only",
|
|
9
|
+
"test-only": "node --trace-uncaught ./test"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/functionalscript/functionalscript.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "Natfoam",
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/functionalscript/functionalscript/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/functionalscript/functionalscript#readme",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^16.11.11",
|
|
23
|
+
"typescript": "^4.5.2"
|
|
24
|
+
}
|
|
25
25
|
}
|
package/test.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const i = require('./')
|
|
2
2
|
|
|
3
|
-
require('./sequence/test')
|
|
4
|
-
require('./btree/test')
|
|
5
|
-
require('./sequence/iterable/test')
|
|
6
|
-
require('./sequence/asyncIterable/test')
|
|
7
|
-
require('./module-manager/test')
|
|
3
|
+
require('./types/sequence/test')
|
|
4
|
+
require('./types/btree/test')
|
|
8
5
|
require('./json/test')
|
|
9
|
-
require('./object/test')
|
|
6
|
+
require('./types/object/test')
|
|
7
|
+
require('./io/commonjs/test')
|
|
8
|
+
require('./commonjs/package/dependencies/test')
|
|
9
|
+
require('./commonjs/package/test')
|
|
10
10
|
|
|
11
11
|
/** @type {() => never} */
|
|
12
12
|
const assert = () => { throw 'assert' }
|