functionalscript 0.4.4 → 0.5.1
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/README.md +1 -1
- package/dev/module.f.d.ts +21 -0
- package/dev/module.f.js +81 -0
- package/dev/test/module.f.d.ts +6 -2
- package/dev/test/module.f.js +21 -1
- package/dev/test.f.d.ts +1 -0
- package/dev/test.f.js +4 -0
- package/{nodejs → dev}/version/module.f.d.ts +1 -1
- package/{nodejs → dev}/version/module.f.js +1 -1
- package/{nodejs → dev}/version/test.f.js +1 -4
- package/djs/module.f.d.ts +2 -0
- package/djs/module.f.js +26 -1
- package/djs/transpiler/module.f.js +2 -1
- package/djs/transpiler/test.f.js +9 -9
- package/fsc.js +4 -0
- package/io/module.f.d.ts +73 -0
- package/io/module.f.js +16 -1
- package/io/virtual.f.js +28 -0
- package/package.json +19 -10
- package/path/module.f.js +2 -5
- package/io/virtual-io.f.js +0 -10
- /package/{nodejs → dev}/version/test.f.d.ts +0 -0
- /package/io/{virtual-io.f.d.ts → virtual.f.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ FunctionalScript code can be used:
|
|
|
31
31
|
|
|
32
32
|
- safely in any JavaScript/TypeScript application or library;
|
|
33
33
|
- as a JSON with expressions, see [DJS](https://medium.com/@sasha.gil/bridging-the-gap-from-json-to-javascript-without-dsls-fee273573f1b);
|
|
34
|
-
- as a query language
|
|
34
|
+
- as a query language;
|
|
35
35
|
- as a smart contract programming language in DeFi.
|
|
36
36
|
|
|
37
37
|
## Design Principles
|
package/dev/module.f.d.ts
CHANGED
|
@@ -1 +1,22 @@
|
|
|
1
|
+
import type { Io } from '../io/module.f.ts';
|
|
2
|
+
import type { Sign } from '../types/function/compare/module.f.ts';
|
|
1
3
|
export declare const todo: () => never;
|
|
4
|
+
export type Module = {
|
|
5
|
+
readonly default?: unknown;
|
|
6
|
+
};
|
|
7
|
+
export type UnknownMap = {
|
|
8
|
+
readonly [k in string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
type Entry<T> = readonly [string, T];
|
|
11
|
+
export declare const cmp: ([a]: Entry<unknown>, [b]: Entry<unknown>) => Sign;
|
|
12
|
+
export type ModuleMap = {
|
|
13
|
+
readonly [k in string]: Module;
|
|
14
|
+
};
|
|
15
|
+
export declare const remove_tail: (v: readonly string[]) => (dif: number) => string[];
|
|
16
|
+
export type MutableModuleMap = {
|
|
17
|
+
[k in string]: Module;
|
|
18
|
+
};
|
|
19
|
+
export declare const env: (io: Io) => (v: string) => string | undefined;
|
|
20
|
+
export declare const loadModuleMap: ({ fs: { promises: { readdir }, existsSync }, asyncImport }: Io) => Promise<ModuleMap>;
|
|
21
|
+
export declare const index: (io: Io) => Promise<number>;
|
|
22
|
+
export {};
|
package/dev/module.f.js
CHANGED
|
@@ -1 +1,82 @@
|
|
|
1
|
+
import { updateVersion } from "./version/module.f.js";
|
|
1
2
|
export const todo = () => { throw 'not implemented'; };
|
|
3
|
+
export const cmp = ([a], [b]) => a < b ? -1 : a > b ? 1 : 0;
|
|
4
|
+
export const remove_tail = (v) => (dif) => v.slice(0, v.length - dif);
|
|
5
|
+
export const env = ({ process: { env } }) => a => {
|
|
6
|
+
const r = Object.getOwnPropertyDescriptor(env, a);
|
|
7
|
+
return r === undefined ? undefined :
|
|
8
|
+
typeof r.get === 'function' ? r.get() :
|
|
9
|
+
r.value;
|
|
10
|
+
};
|
|
11
|
+
export const loadModuleMap = async ({ fs: { promises: { readdir }, existsSync }, asyncImport }) => {
|
|
12
|
+
const load = async () => {
|
|
13
|
+
const map = [];
|
|
14
|
+
const f = async (p) => {
|
|
15
|
+
for (const i of await readdir(p, { withFileTypes: true })) {
|
|
16
|
+
const { name } = i;
|
|
17
|
+
if (!name.startsWith('.')) {
|
|
18
|
+
const file = `${p}/${name}`;
|
|
19
|
+
if (i.isDirectory()) {
|
|
20
|
+
await f(file);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (name.endsWith('.f.mjs') ||
|
|
24
|
+
name.endsWith('.f.js') ||
|
|
25
|
+
(name.endsWith('.f.ts') && !existsSync(file.substring(0, file.length - 3) + '.js'))) {
|
|
26
|
+
const source = await asyncImport(`../${file}`);
|
|
27
|
+
map.push([file, source.default]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
await f('.');
|
|
33
|
+
map.sort(cmp);
|
|
34
|
+
return Object.fromEntries(map);
|
|
35
|
+
};
|
|
36
|
+
const map = await load();
|
|
37
|
+
const build = () => {
|
|
38
|
+
const d = {};
|
|
39
|
+
const getModule = (base) => (k) => {
|
|
40
|
+
const relativePath = k.split('/');
|
|
41
|
+
const dif = relativePath.filter(v => v === '..').length;
|
|
42
|
+
const path = [remove_tail(base)(dif), relativePath.filter(v => !['..', '.'].includes(v))]
|
|
43
|
+
.flat();
|
|
44
|
+
const pathStr = path.join('/');
|
|
45
|
+
{
|
|
46
|
+
const module = d[pathStr];
|
|
47
|
+
if (module !== void 0) {
|
|
48
|
+
return [pathStr, module];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
{
|
|
52
|
+
const module = { default: map[pathStr] };
|
|
53
|
+
d[pathStr] = module;
|
|
54
|
+
return [pathStr, module];
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
{
|
|
58
|
+
const get = getModule(['.']);
|
|
59
|
+
for (const k of Object.keys(map)) {
|
|
60
|
+
get(k);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return d;
|
|
64
|
+
};
|
|
65
|
+
return build();
|
|
66
|
+
};
|
|
67
|
+
export const index = async (io) => {
|
|
68
|
+
updateVersion(io);
|
|
69
|
+
const jj = './deno.json';
|
|
70
|
+
const n = '/module.f.ts';
|
|
71
|
+
const jsr_json = JSON.parse(await io.fs.promises.readFile(jj, 'utf8'));
|
|
72
|
+
const list = Object.keys(await loadModuleMap(io)).filter(v => v.endsWith(n));
|
|
73
|
+
//console.log(list)
|
|
74
|
+
const exportsA = list.filter(v => !v.startsWith('./out')).map(v => [v.replace(n, ''), `./${v.substring(2)}`]);
|
|
75
|
+
// console.log(exportsA)
|
|
76
|
+
const exports = Object.fromEntries(exportsA);
|
|
77
|
+
// console.log(exports)
|
|
78
|
+
const json = JSON.stringify({ ...jsr_json, exports }, null, 2);
|
|
79
|
+
// console.log(json)
|
|
80
|
+
await io.fs.promises.writeFile(jj, json, 'utf8');
|
|
81
|
+
return 0;
|
|
82
|
+
};
|
package/dev/test/module.f.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as Result from '../../types/result/module.f.ts';
|
|
2
|
+
import type { Io, Performance } from '../../io/module.f.ts';
|
|
2
3
|
type Module = {
|
|
3
4
|
readonly default?: unknown;
|
|
4
5
|
};
|
|
@@ -16,5 +17,8 @@ type Input<T> = {
|
|
|
16
17
|
readonly tryCatch: <R>(f: () => R) => Result.Result<R, unknown>;
|
|
17
18
|
readonly env: (n: string) => string | undefined;
|
|
18
19
|
};
|
|
19
|
-
declare const
|
|
20
|
-
export
|
|
20
|
+
export declare const test: <T>(input: Input<T>) => readonly [number, T];
|
|
21
|
+
export declare const anyLog: (f: (s: string) => void) => (s: string) => <T>(state: T) => T;
|
|
22
|
+
export declare const measure: (p: Performance) => <R>(f: () => R) => <T>(state: T) => readonly [R, number, T];
|
|
23
|
+
export declare const main: (io: Io) => Promise<number>;
|
|
24
|
+
export {};
|
package/dev/test/module.f.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { entries, fold } from "../../types/list/module.f.js";
|
|
2
2
|
import { reset, fgGreen, fgRed, bold } from "../../text/sgr/module.f.js";
|
|
3
|
+
import { env, loadModuleMap } from "../module.f.js";
|
|
3
4
|
const isTest = (s) => s.endsWith('test.f.mjs') || s.endsWith('test.f.js') || s.endsWith('test.f.ts');
|
|
4
5
|
const addPass = (delta) => (ts) => ({ ...ts, time: ts.time + delta, pass: ts.pass + 1 });
|
|
5
6
|
const addFail = (delta) => (ts) => ({ ...ts, time: ts.time + delta, fail: ts.fail + 1 });
|
|
@@ -12,7 +13,7 @@ const timeFormat = (a) => {
|
|
|
12
13
|
const e = x.substring(s);
|
|
13
14
|
return `${b}.${e} ms`;
|
|
14
15
|
};
|
|
15
|
-
export
|
|
16
|
+
export const test = (input) => {
|
|
16
17
|
let { moduleMap, log, error, measure, tryCatch, env, state } = input;
|
|
17
18
|
const isGitHub = env('GITHUB_ACTION') !== void 0;
|
|
18
19
|
const f = ([k, v]) => {
|
|
@@ -73,3 +74,22 @@ export default (input) => {
|
|
|
73
74
|
state = log(`${bold}Time: ${timeFormat(ts.time)}${reset}`)(state);
|
|
74
75
|
return [ts.fail !== 0 ? 1 : 0, state];
|
|
75
76
|
};
|
|
77
|
+
export const anyLog = (f) => (s) => (state) => {
|
|
78
|
+
f(s);
|
|
79
|
+
return state;
|
|
80
|
+
};
|
|
81
|
+
export const measure = (p) => (f) => (state) => {
|
|
82
|
+
const b = p.now();
|
|
83
|
+
const r = f();
|
|
84
|
+
const e = p.now();
|
|
85
|
+
return [r, e - b, state];
|
|
86
|
+
};
|
|
87
|
+
export const main = async (io) => test({
|
|
88
|
+
moduleMap: await loadModuleMap(io),
|
|
89
|
+
log: anyLog(io.console.log),
|
|
90
|
+
error: anyLog(io.console.error),
|
|
91
|
+
measure: measure(io.performance),
|
|
92
|
+
tryCatch: io.tryCatch,
|
|
93
|
+
env: env(io),
|
|
94
|
+
state: void 0,
|
|
95
|
+
})[0];
|
package/dev/test.f.d.ts
CHANGED
package/dev/test.f.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { todo } from "./module.f.js";
|
|
1
2
|
export default {
|
|
2
3
|
ctor: () => {
|
|
3
4
|
const c = (() => { })['constructor'];
|
|
@@ -48,5 +49,8 @@ export default {
|
|
|
48
49
|
const x = { 'a': 12 };
|
|
49
50
|
const c = Object.getOwnPropertyDescriptor(x, 'constructor');
|
|
50
51
|
const a = Object.getOwnPropertyDescriptor(x, 'a');
|
|
52
|
+
},
|
|
53
|
+
throw: () => {
|
|
54
|
+
todo();
|
|
51
55
|
}
|
|
52
56
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { stringify, parse } = JSON;
|
|
2
2
|
export const getVersion = fs => readJson(fs)('package').version;
|
|
3
3
|
const jsonFile = (jsonFile) => `${jsonFile}.json`;
|
|
4
|
-
const readJson = fs => name => parse(fs.readFileSync(jsonFile(name))
|
|
4
|
+
const readJson = fs => name => parse(fs.readFileSync(jsonFile(name), 'utf8'));
|
|
5
5
|
export const updateVersion = ({ fs }) => {
|
|
6
6
|
const f = (name) => {
|
|
7
7
|
return fs.writeFileSync(jsonFile(name), stringify({
|
|
@@ -73,13 +73,10 @@ const e = '{\n' +
|
|
|
73
73
|
' "typescript": "^4.7.4"\n' +
|
|
74
74
|
' }\n' +
|
|
75
75
|
'}';
|
|
76
|
-
const buffer = s => ({
|
|
77
|
-
toString: () => s
|
|
78
|
-
});
|
|
79
76
|
export default () => {
|
|
80
77
|
const node = {
|
|
81
78
|
fs: {
|
|
82
|
-
readFileSync: n =>
|
|
79
|
+
readFileSync: n => JSON.stringify(x[n]),
|
|
83
80
|
writeFileSync: (_, content) => content
|
|
84
81
|
}
|
|
85
82
|
};
|
package/djs/module.f.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Io } from '../io/module.f.ts';
|
|
1
2
|
import type { Primitive as JsonPrimitive } from '../json/module.f.ts';
|
|
2
3
|
export type Object = {
|
|
3
4
|
readonly [k in string]: Unknown;
|
|
@@ -5,3 +6,4 @@ export type Object = {
|
|
|
5
6
|
export type Array = readonly Unknown[];
|
|
6
7
|
export type Primitive = JsonPrimitive | bigint | undefined;
|
|
7
8
|
export type Unknown = Primitive | Object | Array;
|
|
9
|
+
export declare const compile: ({ console: { error }, fs, process: { argv } }: Io) => Promise<number>;
|
package/djs/module.f.js
CHANGED
|
@@ -1 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
import { transpile } from "./transpiler/module.f.js";
|
|
2
|
+
import { stringify } from "./serializer/module.f.js";
|
|
3
|
+
import { sort } from "../types/object/module.f.js";
|
|
4
|
+
const stringifyUnknown = stringify(sort);
|
|
5
|
+
export const compile = ({ console: { error }, fs, process: { argv } }) => {
|
|
6
|
+
const args = argv.slice(2);
|
|
7
|
+
if (args.length < 2) {
|
|
8
|
+
error('Error: Requires 2 or more arguments');
|
|
9
|
+
return Promise.resolve(1);
|
|
10
|
+
}
|
|
11
|
+
const inputFileName = args[0];
|
|
12
|
+
const outputFileName = args[1];
|
|
13
|
+
const result = transpile(fs)(inputFileName);
|
|
14
|
+
switch (result[0]) {
|
|
15
|
+
case 'ok': {
|
|
16
|
+
const output = stringifyUnknown(result[1]);
|
|
17
|
+
fs.writeFileSync(outputFileName, output);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case 'error': {
|
|
21
|
+
error(`Parse error: ${result[1]}`);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return Promise.resolve(0);
|
|
26
|
+
};
|
|
@@ -15,7 +15,8 @@ const mapDjs = context => path => {
|
|
|
15
15
|
};
|
|
16
16
|
const transpileWithImports = path => parseModuleResult => context => {
|
|
17
17
|
if (parseModuleResult[0] === 'ok') {
|
|
18
|
-
const
|
|
18
|
+
const dir = pathConcat(path)('..');
|
|
19
|
+
const pathsCombine = listMap(pathConcat(dir))(parseModuleResult[1][0]);
|
|
19
20
|
const contextWithImports = fold(foldNextModuleOp)({ ...context, stack: { first: path, tail: context.stack } })(pathsCombine);
|
|
20
21
|
if (contextWithImports.error !== null) {
|
|
21
22
|
return contextWithImports;
|
package/djs/transpiler/test.f.js
CHANGED
|
@@ -2,7 +2,7 @@ import { sort } from "../../types/object/module.f.js";
|
|
|
2
2
|
import { setReplace } from "../../types/map/module.f.js";
|
|
3
3
|
import { transpile } from "./module.f.js";
|
|
4
4
|
import { stringify } from "../serializer/module.f.js";
|
|
5
|
-
import { createVirtualIo } from "../../io/virtual
|
|
5
|
+
import { createVirtualIo } from "../../io/virtual.f.js";
|
|
6
6
|
const virtualFs = map => {
|
|
7
7
|
return createVirtualIo(map).fs;
|
|
8
8
|
};
|
|
@@ -20,10 +20,10 @@ export default {
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
parseWithSubModule: () => {
|
|
23
|
-
const map = setReplace('a')('import
|
|
24
|
-
const map2 = setReplace('a/
|
|
23
|
+
const map = setReplace('a/b')('import c from "c"\nexport default c')(null);
|
|
24
|
+
const map2 = setReplace('a/c')('export default 2')(map);
|
|
25
25
|
const fs = virtualFs(map2);
|
|
26
|
-
const result = transpile(fs)('a');
|
|
26
|
+
const result = transpile(fs)('a/b');
|
|
27
27
|
if (result[0] === 'error') {
|
|
28
28
|
throw result[1];
|
|
29
29
|
}
|
|
@@ -34,9 +34,9 @@ export default {
|
|
|
34
34
|
},
|
|
35
35
|
parseWithSubModules: () => {
|
|
36
36
|
const map = setReplace('a')('import b from "b"\nimport c from "c"\nexport default [b,c,b]')(null);
|
|
37
|
-
const map2 = setReplace('
|
|
38
|
-
const map3 = setReplace('
|
|
39
|
-
const map4 = setReplace('
|
|
37
|
+
const map2 = setReplace('b')('import d from "d"\nexport default [0,d]')(map);
|
|
38
|
+
const map3 = setReplace('c')('import d from "d"\nexport default [1,d]')(map2);
|
|
39
|
+
const map4 = setReplace('d')('export default 2')(map3);
|
|
40
40
|
const fs = virtualFs(map4);
|
|
41
41
|
const result = transpile(fs)('a');
|
|
42
42
|
if (result[0] === 'error') {
|
|
@@ -60,8 +60,8 @@ export default {
|
|
|
60
60
|
},
|
|
61
61
|
parseWithCycleError: () => {
|
|
62
62
|
const map = setReplace('a')('import b from "b"\nimport c from "c"\nexport default [b,c,b]')(null);
|
|
63
|
-
const map2 = setReplace('
|
|
64
|
-
const map3 = setReplace('
|
|
63
|
+
const map2 = setReplace('b')('import c from "c"\nexport default c')(map);
|
|
64
|
+
const map3 = setReplace('c')('import b from "b"\nexport default b')(map2);
|
|
65
65
|
const fs = virtualFs(map3);
|
|
66
66
|
const result = transpile(fs)('a');
|
|
67
67
|
if (result[0] !== 'error') {
|
package/fsc.js
ADDED
package/io/module.f.d.ts
CHANGED
|
@@ -1,12 +1,85 @@
|
|
|
1
|
+
import type { Result } from '../types/result/module.f.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Standard Node.js buffer encoding type
|
|
4
|
+
* @see https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
|
|
5
|
+
*/
|
|
1
6
|
export type BufferEncoding = 'utf8';
|
|
7
|
+
/**
|
|
8
|
+
* Represents a directory entry (file or directory) in the filesystem
|
|
9
|
+
* @see https://nodejs.org/api/fs.html#class-fsdirent
|
|
10
|
+
*/
|
|
11
|
+
export type Dirent = {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly isDirectory: () => boolean;
|
|
14
|
+
readonly isFile: () => boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* File system operations interface
|
|
18
|
+
* @see https://nodejs.org/api/fs.html
|
|
19
|
+
*/
|
|
2
20
|
export type Fs = {
|
|
3
21
|
readonly writeFileSync: (file: string, data: string) => void;
|
|
4
22
|
readonly readFileSync: (path: string, options: BufferEncoding) => string | null;
|
|
23
|
+
readonly existsSync: (path: string) => boolean;
|
|
24
|
+
readonly promises: {
|
|
25
|
+
readonly readFile: (path: string, options: BufferEncoding) => Promise<string>;
|
|
26
|
+
readonly writeFile: (path: string, data: string, options: BufferEncoding) => Promise<void>;
|
|
27
|
+
readonly readdir: (path: string, options: {
|
|
28
|
+
withFileTypes: true;
|
|
29
|
+
}) => Promise<Dirent[]>;
|
|
30
|
+
};
|
|
5
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Console operations interface
|
|
34
|
+
* @see https://nodejs.org/api/console.html
|
|
35
|
+
*/
|
|
6
36
|
export type Console = {
|
|
7
37
|
readonly log: (...d: unknown[]) => void;
|
|
38
|
+
readonly error: (...d: unknown[]) => void;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Represents an ES module with a default export
|
|
42
|
+
*/
|
|
43
|
+
export type Module = {
|
|
44
|
+
readonly default: unknown;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* High-resolution time measurement interface
|
|
48
|
+
* @see https://nodejs.org/api/perf_hooks.html#performance-now
|
|
49
|
+
*/
|
|
50
|
+
export type Performance = {
|
|
51
|
+
readonly now: () => number;
|
|
8
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Core IO operations interface providing access to system resources
|
|
55
|
+
*/
|
|
9
56
|
export type Io = {
|
|
10
57
|
readonly console: Console;
|
|
11
58
|
readonly fs: Fs;
|
|
59
|
+
readonly process: Process;
|
|
60
|
+
readonly asyncImport: (s: string) => Promise<Module>;
|
|
61
|
+
readonly performance: Performance;
|
|
62
|
+
readonly tryCatch: <T>(f: () => T) => Result<T, unknown>;
|
|
63
|
+
readonly asyncTryCatch: <T>(f: () => Promise<T>) => Promise<Result<T, unknown>>;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Node.js Process interface
|
|
67
|
+
* @see https://nodejs.org/api/process.html
|
|
68
|
+
*/
|
|
69
|
+
export type Process = {
|
|
70
|
+
readonly argv: string[];
|
|
71
|
+
readonly env: Env;
|
|
72
|
+
readonly exit: (code: number) => never;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The environment variables.
|
|
76
|
+
*/
|
|
77
|
+
export type Env = {
|
|
78
|
+
readonly [k: string]: string | undefined;
|
|
12
79
|
};
|
|
80
|
+
export type Run = (f: (io: Io) => Promise<number>) => Promise<never>;
|
|
81
|
+
/**
|
|
82
|
+
* Runs a function and exits the process with the returned code
|
|
83
|
+
* Handles errors by exiting with code 1
|
|
84
|
+
*/
|
|
85
|
+
export declare const run: (io: Io) => Run;
|
package/io/module.f.js
CHANGED
|
@@ -1 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Runs a function and exits the process with the returned code
|
|
3
|
+
* Handles errors by exiting with code 1
|
|
4
|
+
*/
|
|
5
|
+
export const run = (io) => {
|
|
6
|
+
const code = ([x, b]) => {
|
|
7
|
+
if (x === 'error') {
|
|
8
|
+
io.console.error(x[1]);
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return b;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
return async (f) => io.process.exit(code(await io.asyncTryCatch(() => f(io))));
|
|
16
|
+
};
|
package/io/virtual.f.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { at } from "../types/map/module.f.js";
|
|
2
|
+
export const createVirtualIo = (files) => ({
|
|
3
|
+
console: {
|
|
4
|
+
log: (..._d) => { },
|
|
5
|
+
error: (..._d) => { }
|
|
6
|
+
},
|
|
7
|
+
fs: {
|
|
8
|
+
writeFileSync: (_file, _data) => { },
|
|
9
|
+
readFileSync: (path, _options) => { return at(path)(files); },
|
|
10
|
+
existsSync: (path) => { return at(path)(files) !== null; },
|
|
11
|
+
promises: {
|
|
12
|
+
readdir: (_path) => Promise.resolve([]),
|
|
13
|
+
readFile: (_path, _options) => Promise.resolve(''),
|
|
14
|
+
writeFile: (_path, _data, _options) => Promise.resolve(),
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
process: {
|
|
18
|
+
argv: [],
|
|
19
|
+
env: {},
|
|
20
|
+
exit: n => { throw n; },
|
|
21
|
+
},
|
|
22
|
+
asyncImport: () => Promise.reject(),
|
|
23
|
+
performance: {
|
|
24
|
+
now: () => 0,
|
|
25
|
+
},
|
|
26
|
+
tryCatch: f => ['ok', f()],
|
|
27
|
+
asyncTryCatch: async (f) => ['ok', await f()],
|
|
28
|
+
});
|
package/package.json
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functionalscript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
|
+
"fsc.js",
|
|
7
|
+
"io/node-io.js",
|
|
6
8
|
"**/*.f.d.ts",
|
|
7
9
|
"**/*.f.js"
|
|
8
10
|
],
|
|
9
11
|
"description": "FunctionalScript is a functional subset of JavaScript",
|
|
10
12
|
"scripts": {
|
|
11
13
|
"tsc-emit": "tsc --NoEmit false",
|
|
14
|
+
"n": "node --frozen-intrinsics --trace-uncaught",
|
|
12
15
|
"prepack": "npm run tsc-emit",
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"fsc": "
|
|
19
|
-
"update": "npm run
|
|
16
|
+
"git-clean": "git clean -xf",
|
|
17
|
+
"test20": "npm run tsc-emit && npm run n ./dev/test.js",
|
|
18
|
+
"test22": "tsc && npm run n -- --experimental-strip-types ./dev/test.ts",
|
|
19
|
+
"test": "tsc && npm run n ./dev/test.ts",
|
|
20
|
+
"index": "npm run n ./dev/index.ts",
|
|
21
|
+
"fsc": "npm run n ./fsc.ts",
|
|
22
|
+
"update": "npm run index && npm install"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=16"
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"fsc": "fsc.js"
|
|
20
29
|
},
|
|
21
30
|
"repository": {
|
|
22
31
|
"type": "git",
|
|
@@ -38,7 +47,7 @@
|
|
|
38
47
|
},
|
|
39
48
|
"homepage": "https://github.com/functionalscript/functionalscript#readme",
|
|
40
49
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^22.13.
|
|
42
|
-
"typescript": "^5.
|
|
50
|
+
"@types/node": "^22.13.14",
|
|
51
|
+
"typescript": "^5.8.2"
|
|
43
52
|
}
|
|
44
53
|
}
|
package/path/module.f.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {} from "../types/function/operator/module.f.js";
|
|
2
1
|
import { fold, last, take, length, concat as listConcat } from "../types/list/module.f.js";
|
|
3
2
|
import { join } from "../types/string/module.f.js";
|
|
4
3
|
import { concat as stringConcat } from "../types/string/module.f.js";
|
|
@@ -13,10 +12,8 @@ const foldNormalizeOp = input => state => {
|
|
|
13
12
|
case '..': {
|
|
14
13
|
return listConcat(state)([input]);
|
|
15
14
|
}
|
|
16
|
-
default: {
|
|
17
|
-
return take(length(state) - 1)(state);
|
|
18
|
-
}
|
|
19
15
|
}
|
|
16
|
+
return take(length(state) - 1)(state);
|
|
20
17
|
}
|
|
21
18
|
default: {
|
|
22
19
|
return listConcat(state)([input]);
|
|
@@ -24,7 +21,7 @@ const foldNormalizeOp = input => state => {
|
|
|
24
21
|
}
|
|
25
22
|
};
|
|
26
23
|
export const normalize = path => {
|
|
27
|
-
const split = path.split('/');
|
|
24
|
+
const split = path.replaceAll('\\', '/').split('/');
|
|
28
25
|
const foldResult = fold(foldNormalizeOp)([])(split);
|
|
29
26
|
return join('/')(foldResult);
|
|
30
27
|
};
|
package/io/virtual-io.f.js
DELETED
|
File without changes
|
|
File without changes
|