aontu 0.45.1 → 0.46.0

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/dist/cli.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import { Aontu } from './aontu';
3
+ type Mode = 'json' | 'canon';
4
+ declare function evalSource(aontu: Aontu, src: string, mode: Mode): {
5
+ ok: boolean;
6
+ text: string;
7
+ };
8
+ declare function main(argv: string[]): void;
9
+ export { evalSource, main };
package/dist/cli.js ADDED
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.evalSource = evalSource;
39
+ exports.main = main;
40
+ // Command-line interface for Aontu.
41
+ //
42
+ // aontu [options] [file]
43
+ //
44
+ // With a file argument, the file is evaluated and the result printed.
45
+ // With no file on an interactive terminal, a REPL is started. With no
46
+ // file and piped input, the source is read from stdin. See HELP below.
47
+ const Fs = __importStar(require("node:fs"));
48
+ const Path = __importStar(require("node:path"));
49
+ const Readline = __importStar(require("node:readline"));
50
+ const aontu_1 = require("./aontu");
51
+ const HELP = `Usage: aontu [options] [file]
52
+
53
+ Evaluate an Aontu source file and print the result as JSON.
54
+ With no file on an interactive terminal, start a REPL.
55
+ With no file and piped input, read the source from stdin.
56
+
57
+ Options:
58
+ -c, --canon Print the canonical form instead of generated JSON
59
+ -h, --help Show this help and exit
60
+ -v, --version Print the version and exit
61
+
62
+ REPL commands:
63
+ :help Show REPL help
64
+ :canon Switch to canonical-form output
65
+ :json Switch to JSON output
66
+ :quit, :exit Exit the REPL (or press Ctrl-D)
67
+ `;
68
+ function version() {
69
+ try {
70
+ const txt = Fs.readFileSync(Path.join(__dirname, '..', 'package.json'), 'utf8');
71
+ return JSON.parse(txt).version ?? '0.0.0';
72
+ }
73
+ catch {
74
+ return '0.0.0';
75
+ }
76
+ }
77
+ // Evaluate source, returning either the rendered output or the error
78
+ // message. Never throws.
79
+ function evalSource(aontu, src, mode) {
80
+ try {
81
+ const text = 'canon' === mode
82
+ ? aontu.unify(src).canon
83
+ : JSON.stringify(aontu.generate(src), null, 2);
84
+ return { ok: true, text };
85
+ }
86
+ catch (err) {
87
+ const msg = (err instanceof aontu_1.AontuError || true === err?.aontu)
88
+ ? err.message
89
+ : String(err?.message ?? err);
90
+ return { ok: false, text: msg };
91
+ }
92
+ }
93
+ function runFile(file, mode) {
94
+ let src;
95
+ try {
96
+ src = Fs.readFileSync(file, 'utf8');
97
+ }
98
+ catch (err) {
99
+ process.stderr.write(`aontu: cannot read ${file}: ${err.message}\n`);
100
+ return 1;
101
+ }
102
+ const aontu = new aontu_1.Aontu({ path: Path.resolve(file) });
103
+ const res = evalSource(aontu, src, mode);
104
+ (res.ok ? process.stdout : process.stderr).write(res.text + '\n');
105
+ return res.ok ? 0 : 1;
106
+ }
107
+ function runStdin(mode) {
108
+ return new Promise((resolve) => {
109
+ let src = '';
110
+ process.stdin.setEncoding('utf8');
111
+ process.stdin.on('data', (d) => (src += d));
112
+ process.stdin.on('end', () => {
113
+ const res = evalSource(new aontu_1.Aontu(), src, mode);
114
+ (res.ok ? process.stdout : process.stderr).write(res.text + '\n');
115
+ resolve(res.ok ? 0 : 1);
116
+ });
117
+ });
118
+ }
119
+ function runRepl(initialMode) {
120
+ let mode = initialMode;
121
+ const aontu = new aontu_1.Aontu();
122
+ const rl = Readline.createInterface({
123
+ input: process.stdin,
124
+ output: process.stdout,
125
+ prompt: 'aontu> ',
126
+ });
127
+ process.stdout.write(`Aontu v${version()} REPL — :help for commands, :quit to exit\n`);
128
+ rl.prompt();
129
+ rl.on('line', (line) => {
130
+ const s = line.trim();
131
+ if ('' === s) {
132
+ rl.prompt();
133
+ return;
134
+ }
135
+ if (s.startsWith(':')) {
136
+ switch (s) {
137
+ case ':help':
138
+ process.stdout.write(HELP);
139
+ break;
140
+ case ':canon':
141
+ mode = 'canon';
142
+ process.stdout.write('canon output\n');
143
+ break;
144
+ case ':json':
145
+ mode = 'json';
146
+ process.stdout.write('json output\n');
147
+ break;
148
+ case ':quit':
149
+ case ':exit':
150
+ rl.close();
151
+ return;
152
+ default: process.stdout.write(`unknown command: ${s} (try :help)\n`);
153
+ }
154
+ rl.prompt();
155
+ return;
156
+ }
157
+ const res = evalSource(aontu, s, mode);
158
+ process.stdout.write(res.text + '\n');
159
+ rl.prompt();
160
+ });
161
+ rl.on('close', () => {
162
+ process.stdout.write('\n');
163
+ process.exit(0);
164
+ });
165
+ }
166
+ function main(argv) {
167
+ let mode = 'json';
168
+ let file;
169
+ for (const arg of argv.slice(2)) {
170
+ if ('-c' === arg || '--canon' === arg) {
171
+ mode = 'canon';
172
+ }
173
+ else if ('-h' === arg || '--help' === arg) {
174
+ process.stdout.write(HELP);
175
+ process.exit(0);
176
+ }
177
+ else if ('-v' === arg || '--version' === arg) {
178
+ process.stdout.write(version() + '\n');
179
+ process.exit(0);
180
+ }
181
+ else if (arg.startsWith('-')) {
182
+ process.stderr.write(`aontu: unknown option ${arg} (try --help)\n`);
183
+ process.exit(2);
184
+ }
185
+ else {
186
+ file = arg;
187
+ }
188
+ }
189
+ if (null != file) {
190
+ process.exit(runFile(file, mode));
191
+ }
192
+ else if (process.stdin.isTTY) {
193
+ runRepl(mode);
194
+ }
195
+ else {
196
+ runStdin(mode).then((code) => process.exit(code));
197
+ }
198
+ }
199
+ // Only run when invoked as a program, not when imported (e.g. by tests).
200
+ if (require.main === module) {
201
+ main(process.argv);
202
+ }
203
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"root":["../src/aontu.ts","../src/ctx.ts","../src/err.ts","../src/hints.ts","../src/lang.ts","../src/site.ts","../src/type.ts","../src/unify.ts","../src/utility.ts","../src/val/bagval.ts","../src/val/booleanval.ts","../src/val/closefuncval.ts","../src/val/conjunctval.ts","../src/val/copyfuncval.ts","../src/val/disjunctval.ts","../src/val/expectval.ts","../src/val/featureval.ts","../src/val/funcbaseval.ts","../src/val/hidefuncval.ts","../src/val/integerval.ts","../src/val/junctionval.ts","../src/val/keyfuncval.ts","../src/val/listval.ts","../src/val/lowerfuncval.ts","../src/val/mapval.ts","../src/val/movefuncval.ts","../src/val/nilval.ts","../src/val/nullval.ts","../src/val/numberval.ts","../src/val/opbaseval.ts","../src/val/openfuncval.ts","../src/val/pathfuncval.ts","../src/val/plusopval.ts","../src/val/preffuncval.ts","../src/val/prefval.ts","../src/val/refval.ts","../src/val/scalarkindval.ts","../src/val/scalarval.ts","../src/val/stringval.ts","../src/val/superfuncval.ts","../src/val/topval.ts","../src/val/typefuncval.ts","../src/val/upperfuncval.ts","../src/val/val.ts","../src/val/varval.ts","../src/val/top.ts","../src/val/valutil.ts"],"version":"6.0.3"}
1
+ {"root":["../src/aontu.ts","../src/cli.ts","../src/ctx.ts","../src/err.ts","../src/hints.ts","../src/lang.ts","../src/site.ts","../src/type.ts","../src/unify.ts","../src/utility.ts","../src/val/bagval.ts","../src/val/booleanval.ts","../src/val/closefuncval.ts","../src/val/conjunctval.ts","../src/val/copyfuncval.ts","../src/val/disjunctval.ts","../src/val/expectval.ts","../src/val/featureval.ts","../src/val/funcbaseval.ts","../src/val/hidefuncval.ts","../src/val/integerval.ts","../src/val/junctionval.ts","../src/val/keyfuncval.ts","../src/val/listval.ts","../src/val/lowerfuncval.ts","../src/val/mapval.ts","../src/val/movefuncval.ts","../src/val/nilval.ts","../src/val/nullval.ts","../src/val/numberval.ts","../src/val/opbaseval.ts","../src/val/openfuncval.ts","../src/val/pathfuncval.ts","../src/val/plusopval.ts","../src/val/preffuncval.ts","../src/val/prefval.ts","../src/val/refval.ts","../src/val/scalarkindval.ts","../src/val/scalarval.ts","../src/val/stringval.ts","../src/val/superfuncval.ts","../src/val/topval.ts","../src/val/typefuncval.ts","../src/val/upperfuncval.ts","../src/val/val.ts","../src/val/varval.ts","../src/val/top.ts","../src/val/valutil.ts"],"version":"6.0.3"}
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "aontu",
3
- "version": "0.45.1",
3
+ "version": "0.46.0",
4
4
  "main": "dist/aontu.js",
5
5
  "type": "commonjs",
6
6
  "types": "dist/aontu.d.ts",
7
+ "bin": {
8
+ "aontu": "dist/cli.js"
9
+ },
7
10
  "description": "Unifier.",
8
11
  "homepage": "https://github.com/rjrodger/aontu",
9
12
  "keywords": [
@@ -16,6 +19,7 @@
16
19
  },
17
20
  "scripts": {
18
21
  "test": "node --enable-source-maps --test \"dist-test/**/*.test.js\"",
22
+ "test-cov": "node --enable-source-maps --experimental-test-coverage --test \"dist-test/**/*.test.js\"",
19
23
  "test-some": "node --enable-source-maps --test-name-pattern=\"$TEST_PATTERN\" --test \"dist-test/**/*.test.js\"",
20
24
  "watch": "tsc --build src test -w",
21
25
  "build": "tsc --build src test",
@@ -36,15 +40,15 @@
36
40
  "LICENSE"
37
41
  ],
38
42
  "dependencies": {
39
- "@jsonic/directive": "2.1.0",
40
- "@jsonic/expr": "2.1.0",
41
- "@jsonic/multisource": "2.6.0",
42
- "@jsonic/path": "2.0.0",
43
- "jsonic": "2.27.0"
43
+ "@jsonic/directive": "2.2.0",
44
+ "@jsonic/expr": "2.3.2",
45
+ "@jsonic/multisource": "2.9.1",
46
+ "@jsonic/path": "2.1.0",
47
+ "jsonic": "2.28.0"
44
48
  },
45
49
  "devDependencies": {
46
- "@types/node": "25.6.0",
47
- "memfs": "4.57.2",
50
+ "@types/node": "25.9.2",
51
+ "memfs": "4.57.6",
48
52
  "typescript": "6.0.3"
49
53
  },
50
54
  "aliasify": {
package/src/cli.ts ADDED
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env node
2
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
3
+
4
+ // Command-line interface for Aontu.
5
+ //
6
+ // aontu [options] [file]
7
+ //
8
+ // With a file argument, the file is evaluated and the result printed.
9
+ // With no file on an interactive terminal, a REPL is started. With no
10
+ // file and piped input, the source is read from stdin. See HELP below.
11
+
12
+ import * as Fs from 'node:fs'
13
+ import * as Path from 'node:path'
14
+ import * as Readline from 'node:readline'
15
+
16
+ import { Aontu, AontuError } from './aontu'
17
+
18
+
19
+ type Mode = 'json' | 'canon'
20
+
21
+
22
+ const HELP = `Usage: aontu [options] [file]
23
+
24
+ Evaluate an Aontu source file and print the result as JSON.
25
+ With no file on an interactive terminal, start a REPL.
26
+ With no file and piped input, read the source from stdin.
27
+
28
+ Options:
29
+ -c, --canon Print the canonical form instead of generated JSON
30
+ -h, --help Show this help and exit
31
+ -v, --version Print the version and exit
32
+
33
+ REPL commands:
34
+ :help Show REPL help
35
+ :canon Switch to canonical-form output
36
+ :json Switch to JSON output
37
+ :quit, :exit Exit the REPL (or press Ctrl-D)
38
+ `
39
+
40
+
41
+ function version(): string {
42
+ try {
43
+ const txt = Fs.readFileSync(Path.join(__dirname, '..', 'package.json'), 'utf8')
44
+ return JSON.parse(txt).version ?? '0.0.0'
45
+ }
46
+ catch {
47
+ return '0.0.0'
48
+ }
49
+ }
50
+
51
+
52
+ // Evaluate source, returning either the rendered output or the error
53
+ // message. Never throws.
54
+ function evalSource(
55
+ aontu: Aontu,
56
+ src: string,
57
+ mode: Mode,
58
+ ): { ok: boolean; text: string } {
59
+ try {
60
+ const text = 'canon' === mode
61
+ ? aontu.unify(src).canon
62
+ : JSON.stringify(aontu.generate(src), null, 2)
63
+ return { ok: true, text }
64
+ }
65
+ catch (err: any) {
66
+ const msg = (err instanceof AontuError || true === err?.aontu)
67
+ ? err.message
68
+ : String(err?.message ?? err)
69
+ return { ok: false, text: msg }
70
+ }
71
+ }
72
+
73
+
74
+ function runFile(file: string, mode: Mode): number {
75
+ let src: string
76
+ try {
77
+ src = Fs.readFileSync(file, 'utf8')
78
+ }
79
+ catch (err: any) {
80
+ process.stderr.write(`aontu: cannot read ${file}: ${err.message}\n`)
81
+ return 1
82
+ }
83
+
84
+ const aontu = new Aontu({ path: Path.resolve(file) })
85
+ const res = evalSource(aontu, src, mode)
86
+ ;(res.ok ? process.stdout : process.stderr).write(res.text + '\n')
87
+ return res.ok ? 0 : 1
88
+ }
89
+
90
+
91
+ function runStdin(mode: Mode): Promise<number> {
92
+ return new Promise((resolve) => {
93
+ let src = ''
94
+ process.stdin.setEncoding('utf8')
95
+ process.stdin.on('data', (d) => (src += d))
96
+ process.stdin.on('end', () => {
97
+ const res = evalSource(new Aontu(), src, mode)
98
+ ;(res.ok ? process.stdout : process.stderr).write(res.text + '\n')
99
+ resolve(res.ok ? 0 : 1)
100
+ })
101
+ })
102
+ }
103
+
104
+
105
+ function runRepl(initialMode: Mode): void {
106
+ let mode = initialMode
107
+ const aontu = new Aontu()
108
+ const rl = Readline.createInterface({
109
+ input: process.stdin,
110
+ output: process.stdout,
111
+ prompt: 'aontu> ',
112
+ })
113
+
114
+ process.stdout.write(
115
+ `Aontu v${version()} REPL — :help for commands, :quit to exit\n`)
116
+ rl.prompt()
117
+
118
+ rl.on('line', (line) => {
119
+ const s = line.trim()
120
+
121
+ if ('' === s) {
122
+ rl.prompt()
123
+ return
124
+ }
125
+
126
+ if (s.startsWith(':')) {
127
+ switch (s) {
128
+ case ':help': process.stdout.write(HELP); break
129
+ case ':canon': mode = 'canon'; process.stdout.write('canon output\n'); break
130
+ case ':json': mode = 'json'; process.stdout.write('json output\n'); break
131
+ case ':quit': case ':exit': rl.close(); return
132
+ default: process.stdout.write(`unknown command: ${s} (try :help)\n`)
133
+ }
134
+ rl.prompt()
135
+ return
136
+ }
137
+
138
+ const res = evalSource(aontu, s, mode)
139
+ process.stdout.write(res.text + '\n')
140
+ rl.prompt()
141
+ })
142
+
143
+ rl.on('close', () => {
144
+ process.stdout.write('\n')
145
+ process.exit(0)
146
+ })
147
+ }
148
+
149
+
150
+ function main(argv: string[]): void {
151
+ let mode: Mode = 'json'
152
+ let file: string | undefined
153
+
154
+ for (const arg of argv.slice(2)) {
155
+ if ('-c' === arg || '--canon' === arg) {
156
+ mode = 'canon'
157
+ }
158
+ else if ('-h' === arg || '--help' === arg) {
159
+ process.stdout.write(HELP)
160
+ process.exit(0)
161
+ }
162
+ else if ('-v' === arg || '--version' === arg) {
163
+ process.stdout.write(version() + '\n')
164
+ process.exit(0)
165
+ }
166
+ else if (arg.startsWith('-')) {
167
+ process.stderr.write(`aontu: unknown option ${arg} (try --help)\n`)
168
+ process.exit(2)
169
+ }
170
+ else {
171
+ file = arg
172
+ }
173
+ }
174
+
175
+ if (null != file) {
176
+ process.exit(runFile(file, mode))
177
+ }
178
+ else if (process.stdin.isTTY) {
179
+ runRepl(mode)
180
+ }
181
+ else {
182
+ runStdin(mode).then((code) => process.exit(code))
183
+ }
184
+ }
185
+
186
+
187
+ // Only run when invoked as a program, not when imported (e.g. by tests).
188
+ if (require.main === module) {
189
+ main(process.argv)
190
+ }
191
+
192
+
193
+ export { evalSource, main }