functionalscript 0.0.493 → 0.0.495
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/.github/workflows/{node.js.yml → ci.yml} +22 -2
- package/.github/workflows/com.yml +1 -1
- package/dev/module.mjs +17 -2
- package/dev/test/module.f.cjs +80 -49
- package/dev/test.mjs +44 -9
- package/package.json +1 -1
- package/text/sgr/module.f.cjs +2 -0
- package/.github/workflows/bun.yml +0 -17
- package/.github/workflows/deno.yml +0 -19
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
|
2
2
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
3
|
|
|
4
|
-
name:
|
|
4
|
+
name: CI
|
|
5
5
|
|
|
6
6
|
on:
|
|
7
7
|
push:
|
|
@@ -10,7 +10,7 @@ on:
|
|
|
10
10
|
pull_request:
|
|
11
11
|
|
|
12
12
|
jobs:
|
|
13
|
-
|
|
13
|
+
node:
|
|
14
14
|
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
|
|
@@ -29,3 +29,23 @@ jobs:
|
|
|
29
29
|
- run: npm test
|
|
30
30
|
- run: npm run version
|
|
31
31
|
- run: npm pack
|
|
32
|
+
|
|
33
|
+
deno:
|
|
34
|
+
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v2
|
|
39
|
+
- uses: denoland/setup-deno@v1
|
|
40
|
+
with:
|
|
41
|
+
deno-version: v1.x
|
|
42
|
+
- run: deno run --quiet --allow-read --allow-env --allow-net --allow-hrtime ./dev/test.mjs
|
|
43
|
+
|
|
44
|
+
bun:
|
|
45
|
+
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v2
|
|
50
|
+
- run: curl https://bun.sh/install | bash
|
|
51
|
+
- run: /home/runner/.bun/bin/bun ./dev/test.mjs
|
package/dev/module.mjs
CHANGED
|
@@ -78,9 +78,24 @@ 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
|
+
|
|
87
|
+
/** @type {(v: string) => string|undefined} */
|
|
88
|
+
export const env =
|
|
89
|
+
self.Deno ? self.Deno.env.get :
|
|
90
|
+
a => {
|
|
91
|
+
const r = Object.getOwnPropertyDescriptor(process.env, a)
|
|
92
|
+
return r === void 0 ? void 0 :
|
|
93
|
+
typeof r.get === 'function' ? r.get() :
|
|
94
|
+
r.value
|
|
95
|
+
}
|
|
96
|
+
|
|
81
97
|
export const loadModuleMap = async () => {
|
|
82
|
-
|
|
83
|
-
const { readdir, readFile } = await import(self.Deno ? 'https://deno.land/std/node/fs/promises.ts' : 'node:fs/promises')
|
|
98
|
+
const { readdir, readFile } = await fs();
|
|
84
99
|
|
|
85
100
|
/** @type {() => Promise<FunctionMap>} */
|
|
86
101
|
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,72 +37,102 @@ 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 error: Log<T>,
|
|
41
|
+
* readonly measure: Measure<T>,
|
|
40
42
|
* readonly state: T,
|
|
43
|
+
* readonly tryCatch: <R>(f: () => R) => result.Result<R, unknown>,
|
|
44
|
+
* readonly env: (n: string) => string|undefined
|
|
41
45
|
* }} Input
|
|
42
46
|
*/
|
|
43
47
|
|
|
44
48
|
/** @type {(s: string) => boolean} */
|
|
45
49
|
const isTest = s => s.endsWith('test.f.cjs')
|
|
46
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @typedef {{
|
|
53
|
+
* readonly time: number,
|
|
54
|
+
* readonly pass: number,
|
|
55
|
+
* readonly fail: number,
|
|
56
|
+
* }} TestState
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/** @type {(time: number) => (testState: TestState) => TestState} */
|
|
60
|
+
const addPass = delta => ts => ({ ...ts, time: ts.time + delta, pass: ts.pass + 1 })
|
|
61
|
+
|
|
62
|
+
/** @type {(time: number) => (testState: TestState) => TestState} */
|
|
63
|
+
const addFail = delta => ts => ({ ...ts, time: ts.time + delta, fail: ts.fail + 1 })
|
|
64
|
+
|
|
47
65
|
/**
|
|
48
66
|
* @template T
|
|
49
|
-
* @typedef {readonly[
|
|
67
|
+
* @typedef {readonly[TestState, T]} FullState
|
|
50
68
|
*/
|
|
51
69
|
|
|
52
|
-
/** @type {<T>(input: Input<T>) => T} */
|
|
70
|
+
/** @type {<T>(input: Input<T>) => readonly[number, T]} */
|
|
53
71
|
const main = input => {
|
|
54
|
-
let { moduleMap, log,
|
|
72
|
+
let { moduleMap, log, error, measure, tryCatch, env, state } = input
|
|
73
|
+
const isGitHub = env('GITHUB_ACTION') !== void 0
|
|
55
74
|
/** @typedef {input extends Input<infer T> ? T : never} T */
|
|
56
|
-
/** @type {(
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
/** @type {(k: readonly[string, Module]) => (fs: FullState<T>) => FullState<T>} */
|
|
76
|
+
const f = ([k, v]) => {
|
|
77
|
+
/** @type {(i: string) => (v: unknown) => (fs: FullState<T>) => FullState<T>} */
|
|
78
|
+
const test = i => v => ([ts, state]) => {
|
|
79
|
+
const next = test(`${i}| `)
|
|
80
|
+
switch (typeof v) {
|
|
81
|
+
case 'function': {
|
|
82
|
+
if (v.length === 0) {
|
|
83
|
+
const [[s, r], delta, state0] = measure(() => tryCatch(/** @type {() => unknown} */(v)))(state)
|
|
84
|
+
state = state0
|
|
85
|
+
if (s === 'error') {
|
|
86
|
+
ts = addFail(delta)(ts)
|
|
87
|
+
if (isGitHub) {
|
|
88
|
+
// https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions
|
|
89
|
+
// https://github.com/OndraM/ci-detector/blob/main/src/Ci/GitHubActions.php
|
|
90
|
+
state = error(`::error file=${k},line=1,title=[3]['a']()::${r}`)(state)
|
|
91
|
+
} else {
|
|
92
|
+
state = error(`${i}() ${fgRed}error${reset}, ${delta} ms`)(state)
|
|
93
|
+
state = error(`${fgRed}${r}${reset}`)(state)
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
ts = addPass(delta)(ts)
|
|
97
|
+
state = log(`${i}() ${fgGreen}ok${reset}, ${delta} ms`)(state)
|
|
98
|
+
}
|
|
99
|
+
[ts, state] = next(r)([ts, state])
|
|
100
|
+
}
|
|
101
|
+
break
|
|
71
102
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
103
|
+
case 'object': {
|
|
104
|
+
if (v !== null) {
|
|
105
|
+
/** @type {(k: readonly[string|number, unknown]) => (fs: FullState<T>) => FullState<T>} */
|
|
106
|
+
const f = ([k, v]) => ([time, state]) => {
|
|
107
|
+
state = log(`${i}${k}:`)(state);
|
|
108
|
+
[time, state] = next(v)([time, state])
|
|
109
|
+
return [time, state]
|
|
110
|
+
}
|
|
111
|
+
[ts, state] = fold
|
|
112
|
+
(f)
|
|
113
|
+
([ts, state])
|
|
114
|
+
(v instanceof Array ? list.entries(v) : Object.entries(v))
|
|
81
115
|
}
|
|
82
|
-
|
|
83
|
-
(f)
|
|
84
|
-
([time, state])
|
|
85
|
-
(v instanceof Array ? list.entries(v) : Object.entries(v))
|
|
116
|
+
break
|
|
86
117
|
}
|
|
87
|
-
break
|
|
88
118
|
}
|
|
119
|
+
return [ts, state]
|
|
89
120
|
}
|
|
90
|
-
return [
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
state = log(`testing ${k}`)(state);
|
|
97
|
-
[time, state] = next(v.exports)([time, state])
|
|
121
|
+
return ([ts, state]) => {
|
|
122
|
+
if (isTest(k)) {
|
|
123
|
+
state = log(`testing ${k}`)(state);
|
|
124
|
+
[ts, state] = test('| ')(v.exports)([ts, state])
|
|
125
|
+
}
|
|
126
|
+
return [ts, state]
|
|
98
127
|
}
|
|
99
|
-
return [time, state]
|
|
100
128
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
state =
|
|
104
|
-
|
|
129
|
+
/** @type {TestState} */
|
|
130
|
+
let ts = { time: 0, pass: 0, fail: 0 };
|
|
131
|
+
[ts, state] = fold(f)([ts, state])(Object.entries(moduleMap))
|
|
132
|
+
const fgFail = ts.fail === 0 ? fgGreen : fgRed
|
|
133
|
+
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)
|
|
134
|
+
state = log(`${bold}Time: ${ts.time} ms${reset}`)(state);
|
|
135
|
+
return [ts.fail !== 0 ? 1 : 0, state]
|
|
105
136
|
}
|
|
106
137
|
|
|
107
|
-
module.exports = main
|
|
138
|
+
module.exports = main
|
package/dev/test.mjs
CHANGED
|
@@ -1,13 +1,44 @@
|
|
|
1
|
-
import { loadModuleMap } from './module.mjs'
|
|
1
|
+
import { loadModuleMap, exit, env } from './module.mjs'
|
|
2
2
|
|
|
3
|
-
/** @type {(s: string) => <T>(_: T) => T} */
|
|
4
|
-
const
|
|
5
|
-
|
|
3
|
+
/** @type {(f: (s: string) => void) => (s: string) => <T>(_: T) => T} */
|
|
4
|
+
const anyLog = f => s => state => {
|
|
5
|
+
f(s)
|
|
6
6
|
return state
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* @template T
|
|
11
|
+
* @typedef {readonly['ok', T]} Ok
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @template E
|
|
16
|
+
* @typedef {readonly['error', E]} Error
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @template T
|
|
21
|
+
* @template E
|
|
22
|
+
* @typedef {Ok<T>|Error<E>} Result
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** @type {<T>(f: () => T) => Result<T, unknown>} */
|
|
26
|
+
const tryCatch = f => {
|
|
27
|
+
// Side effect: `try catch` is not allowed in FunctionalScript.
|
|
28
|
+
try {
|
|
29
|
+
return ['ok', f()]
|
|
30
|
+
} catch (e) {
|
|
31
|
+
return ['error', e]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @type {<R>(f: () => R) => <T>(state: T) => readonly[R, number, T]} Measure} */
|
|
36
|
+
const measure = f => state => {
|
|
37
|
+
const b = performance.now()
|
|
38
|
+
const r = f()
|
|
39
|
+
const e = performance.now()
|
|
40
|
+
return [r, e - b, state]
|
|
41
|
+
}
|
|
11
42
|
|
|
12
43
|
// test runner.
|
|
13
44
|
const main = async() => {
|
|
@@ -15,11 +46,15 @@ const main = async() => {
|
|
|
15
46
|
|
|
16
47
|
/** @type {any} */
|
|
17
48
|
const f = moduleMap['./dev/test/module.f.cjs'].exports
|
|
18
|
-
f({
|
|
49
|
+
const r = f({
|
|
19
50
|
moduleMap,
|
|
20
|
-
log,
|
|
21
|
-
|
|
51
|
+
log: anyLog(console.log),
|
|
52
|
+
error: anyLog(console.error),
|
|
53
|
+
measure,
|
|
54
|
+
tryCatch,
|
|
55
|
+
env,
|
|
22
56
|
})
|
|
57
|
+
exit(r[0])
|
|
23
58
|
}
|
|
24
59
|
|
|
25
60
|
main()
|
package/package.json
CHANGED
package/text/sgr/module.f.cjs
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
name: bun
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- master
|
|
7
|
-
pull_request:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v2
|
|
16
|
-
- run: curl https://bun.sh/install | bash
|
|
17
|
-
- run: /home/runner/.bun/bin/bun ./dev/test.mjs
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
name: deno
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- master
|
|
7
|
-
pull_request:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v2
|
|
16
|
-
- uses: denoland/setup-deno@v1
|
|
17
|
-
with:
|
|
18
|
-
deno-version: v1.x
|
|
19
|
-
- run: deno run --allow-read --allow-env --allow-net --allow-hrtime ./dev/test.mjs
|