functionalscript 0.0.492 → 0.0.494
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/dev/module.mjs +7 -2
- package/dev/test/module.f.cjs +51 -32
- package/dev/test.mjs +41 -6
- package/package.json +1 -1
- package/text/sgr/module.f.cjs +2 -0
package/dev/module.mjs
CHANGED
|
@@ -78,9 +78,14 @@ const remove_tail = v => dif => v.slice(0, v.length - dif)
|
|
|
78
78
|
/** @type {any} */
|
|
79
79
|
const self = globalThis
|
|
80
80
|
|
|
81
|
+
/** @type {() => Promise<FsPromises>} */
|
|
82
|
+
export const fs = () => import(self.Deno ? 'https://deno.land/std/node/fs/promises.ts' : 'node:fs/promises')
|
|
83
|
+
|
|
84
|
+
/** @type {(code: number) => never} */
|
|
85
|
+
export const exit = self.Deno ? self.Deno.exit : process.exit
|
|
86
|
+
|
|
81
87
|
export const loadModuleMap = async () => {
|
|
82
|
-
|
|
83
|
-
const { readdir, readFile } = await import(self.Deno ? 'https://deno.land/std/node/fs/promises.ts' : 'node:fs/promises')
|
|
88
|
+
const { readdir, readFile } = await fs();
|
|
84
89
|
|
|
85
90
|
/** @type {() => Promise<FunctionMap>} */
|
|
86
91
|
const load = async () => {
|
package/dev/test/module.f.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const list = require('../../types/list/module.f.cjs')
|
|
2
2
|
const { fold } = list
|
|
3
|
-
const { reset, fgGreen } = require('../../text/sgr/module.f.cjs')
|
|
3
|
+
const { reset, fgGreen, fgRed, bold } = require('../../text/sgr/module.f.cjs')
|
|
4
|
+
const result = require('../../types/result/module.f.cjs')
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @typedef {{
|
|
@@ -28,7 +29,7 @@ const { reset, fgGreen } = require('../../text/sgr/module.f.cjs')
|
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* @template T
|
|
31
|
-
* @typedef {(state: T) => readonly[number, T]}
|
|
32
|
+
* @typedef {<R>(f: () => R) => (state: T) => readonly[R, number, T]} Measure
|
|
32
33
|
*/
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -36,74 +37,92 @@ const { reset, fgGreen } = require('../../text/sgr/module.f.cjs')
|
|
|
36
37
|
* @typedef {{
|
|
37
38
|
* readonly moduleMap: ModuleMap,
|
|
38
39
|
* readonly log: Log<T>,
|
|
39
|
-
* readonly
|
|
40
|
+
* readonly measure: Measure<T>,
|
|
40
41
|
* readonly state: T,
|
|
42
|
+
* readonly tryCatch: <R>(f: () => R) => result.Result<R, unknown>
|
|
41
43
|
* }} Input
|
|
42
44
|
*/
|
|
43
45
|
|
|
44
46
|
/** @type {(s: string) => boolean} */
|
|
45
47
|
const isTest = s => s.endsWith('test.f.cjs')
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @typedef {{
|
|
51
|
+
* readonly time: number,
|
|
52
|
+
* readonly pass: number,
|
|
53
|
+
* readonly fail: number,
|
|
54
|
+
* }} TestState
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/** @type {(time: number) => (testState: TestState) => TestState} */
|
|
58
|
+
const addPass = delta => ts => ({ ...ts, time: ts.time + delta, pass: ts.pass + 1 })
|
|
59
|
+
|
|
60
|
+
/** @type {(time: number) => (testState: TestState) => TestState} */
|
|
61
|
+
const addFail = delta => ts => ({ ...ts, time: ts.time + delta, fail: ts.fail + 1 })
|
|
62
|
+
|
|
47
63
|
/**
|
|
48
64
|
* @template T
|
|
49
|
-
* @typedef {readonly[
|
|
65
|
+
* @typedef {readonly[TestState, T]} FullState
|
|
50
66
|
*/
|
|
51
67
|
|
|
52
|
-
/** @type {<T>(input: Input<T>) => T} */
|
|
68
|
+
/** @type {<T>(input: Input<T>) => readonly[number, T]} */
|
|
53
69
|
const main = input => {
|
|
54
|
-
let { moduleMap, log,
|
|
70
|
+
let { moduleMap, log, measure, tryCatch, state } = input
|
|
55
71
|
/** @typedef {input extends Input<infer T> ? T : never} T */
|
|
56
|
-
/** @type {(i: string) => (v: unknown) => (
|
|
57
|
-
const test = i => v => ([
|
|
72
|
+
/** @type {(i: string) => (v: unknown) => (fs: FullState<T>) => FullState<T>} */
|
|
73
|
+
const test = i => v => ([ts, state]) => {
|
|
58
74
|
const next = test(`${i}| `)
|
|
59
75
|
switch (typeof v) {
|
|
60
76
|
case 'function': {
|
|
61
77
|
if (v.length === 0) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
const [[s, r], delta, state0] = measure(() => tryCatch(/** @type {() => unknown} */(v)))(state)
|
|
79
|
+
state = state0
|
|
80
|
+
if (s === 'error') {
|
|
81
|
+
ts = addFail(delta)(ts)
|
|
82
|
+
state = log(`${i}() ${fgRed}error${reset}, ${delta} ms`)(state)
|
|
83
|
+
state = log(`${fgRed}${r}${reset}`)(state)
|
|
84
|
+
} else {
|
|
85
|
+
ts = addPass(delta)(ts)
|
|
86
|
+
state = log(`${i}() ${fgGreen}ok${reset}, ${delta} ms`)(state)
|
|
87
|
+
}
|
|
88
|
+
[ts, state] = next(r)([ts, state])
|
|
71
89
|
}
|
|
72
90
|
break
|
|
73
91
|
}
|
|
74
92
|
case 'object': {
|
|
75
93
|
if (v !== null) {
|
|
76
|
-
/** @type {(k: readonly[string|number, unknown]) => (
|
|
94
|
+
/** @type {(k: readonly[string|number, unknown]) => (fs: FullState<T>) => FullState<T>} */
|
|
77
95
|
const f = ([k, v]) => ([time, state]) => {
|
|
78
96
|
state = log(`${i}${k}:`)(state);
|
|
79
97
|
[time, state] = next(v)([time, state])
|
|
80
98
|
return [time, state]
|
|
81
99
|
}
|
|
82
|
-
[
|
|
100
|
+
[ts, state] = fold
|
|
83
101
|
(f)
|
|
84
|
-
([
|
|
102
|
+
([ts, state])
|
|
85
103
|
(v instanceof Array ? list.entries(v) : Object.entries(v))
|
|
86
104
|
}
|
|
87
105
|
break
|
|
88
106
|
}
|
|
89
107
|
}
|
|
90
|
-
return [
|
|
108
|
+
return [ts, state]
|
|
91
109
|
}
|
|
92
110
|
const next = test('| ')
|
|
93
|
-
/** @type {(k: readonly[string, Module]) => (fs:
|
|
94
|
-
const f = ([k, v]) => ([
|
|
111
|
+
/** @type {(k: readonly[string, Module]) => (fs: FullState<T>) => FullState<T>} */
|
|
112
|
+
const f = ([k, v]) => ([ts, state]) => {
|
|
95
113
|
if (isTest(k)) {
|
|
96
114
|
state = log(`testing ${k}`)(state);
|
|
97
|
-
[
|
|
115
|
+
[ts, state] = next(v.exports)([ts, state])
|
|
98
116
|
}
|
|
99
|
-
return [
|
|
117
|
+
return [ts, state]
|
|
100
118
|
}
|
|
101
|
-
/** @type {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
state = log(
|
|
106
|
-
|
|
119
|
+
/** @type {TestState} */
|
|
120
|
+
let ts = { time: 0, pass: 0, fail: 0 };
|
|
121
|
+
[ts, state] = fold(f)([ts, state])(Object.entries(moduleMap))
|
|
122
|
+
const fgFail = ts.fail === 0 ? fgGreen : fgRed
|
|
123
|
+
state = log(`${bold}Number of tests: pass: ${fgGreen}${ts.pass}${reset}${bold}, fail: ${fgFail}${ts.fail}${reset}${bold}, total: ${ts.pass + ts.fail}${reset}`)(state)
|
|
124
|
+
state = log(`${bold}Time: ${ts.time} ms${reset}`)(state);
|
|
125
|
+
return [ts.fail !== 0 ? 1 : 0, state]
|
|
107
126
|
}
|
|
108
127
|
|
|
109
|
-
module.exports = main
|
|
128
|
+
module.exports = main
|
package/dev/test.mjs
CHANGED
|
@@ -1,13 +1,46 @@
|
|
|
1
|
-
import { loadModuleMap } from './module.mjs'
|
|
1
|
+
import { loadModuleMap, exit } from './module.mjs'
|
|
2
|
+
|
|
3
|
+
const consoleLog = console.log
|
|
2
4
|
|
|
3
5
|
/** @type {(s: string) => <T>(_: T) => T} */
|
|
4
6
|
const log = s => state => {
|
|
5
|
-
|
|
7
|
+
consoleLog(s)
|
|
6
8
|
return state
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @template T
|
|
13
|
+
* @typedef {readonly['ok', T]} Ok
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @template E
|
|
18
|
+
* @typedef {readonly['error', E]} Error
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @template T
|
|
23
|
+
* @template E
|
|
24
|
+
* @typedef {Ok<T>|Error<E>} Result
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** @type {<T>(f: () => T) => Result<T, unknown>} */
|
|
28
|
+
const tryCatch = f => {
|
|
29
|
+
// Side effect: `try catch` is not allowed in FunctionalScript.
|
|
30
|
+
try {
|
|
31
|
+
return ['ok', f()]
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return ['error', e]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** @type {<R>(f: () => R) => <T>(state: T) => readonly[R, number, T]} Measure} */
|
|
38
|
+
const measure = f => state => {
|
|
39
|
+
const b = performance.now()
|
|
40
|
+
const r = f()
|
|
41
|
+
const e = performance.now()
|
|
42
|
+
return [r, e - b, state]
|
|
43
|
+
}
|
|
11
44
|
|
|
12
45
|
// test runner.
|
|
13
46
|
const main = async() => {
|
|
@@ -15,11 +48,13 @@ const main = async() => {
|
|
|
15
48
|
|
|
16
49
|
/** @type {any} */
|
|
17
50
|
const f = moduleMap['./dev/test/module.f.cjs'].exports
|
|
18
|
-
f({
|
|
51
|
+
const r = f({
|
|
19
52
|
moduleMap,
|
|
20
53
|
log,
|
|
21
|
-
|
|
54
|
+
measure,
|
|
55
|
+
tryCatch,
|
|
22
56
|
})
|
|
57
|
+
exit(r[0])
|
|
23
58
|
}
|
|
24
59
|
|
|
25
60
|
main()
|
package/package.json
CHANGED