tova 0.5.0 → 0.7.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/bin/tova.js +109 -57
- package/package.json +7 -2
- package/src/analyzer/analyzer.js +315 -79
- package/src/analyzer/{client-analyzer.js → browser-analyzer.js} +20 -17
- package/src/analyzer/form-analyzer.js +113 -0
- package/src/analyzer/scope.js +2 -2
- package/src/codegen/base-codegen.js +1 -0
- package/src/codegen/{client-codegen.js → browser-codegen.js} +444 -5
- package/src/codegen/cli-codegen.js +386 -0
- package/src/codegen/codegen.js +163 -45
- package/src/codegen/edge-codegen.js +1351 -0
- package/src/codegen/form-codegen.js +553 -0
- package/src/codegen/security-codegen.js +5 -5
- package/src/codegen/server-codegen.js +88 -7
- package/src/diagnostics/error-codes.js +1 -1
- package/src/docs/generator.js +1 -1
- package/src/formatter/formatter.js +4 -4
- package/src/lexer/tokens.js +12 -2
- package/src/lsp/server.js +1 -1
- package/src/parser/ast.js +45 -5
- package/src/parser/{client-ast.js → browser-ast.js} +3 -3
- package/src/parser/{client-parser.js → browser-parser.js} +42 -15
- package/src/parser/cli-ast.js +35 -0
- package/src/parser/cli-parser.js +140 -0
- package/src/parser/edge-ast.js +83 -0
- package/src/parser/edge-parser.js +262 -0
- package/src/parser/form-ast.js +80 -0
- package/src/parser/form-parser.js +206 -0
- package/src/parser/parser.js +86 -53
- package/src/registry/block-registry.js +56 -0
- package/src/registry/plugins/bench-plugin.js +23 -0
- package/src/registry/plugins/browser-plugin.js +30 -0
- package/src/registry/plugins/cli-plugin.js +24 -0
- package/src/registry/plugins/data-plugin.js +21 -0
- package/src/registry/plugins/edge-plugin.js +32 -0
- package/src/registry/plugins/security-plugin.js +27 -0
- package/src/registry/plugins/server-plugin.js +46 -0
- package/src/registry/plugins/shared-plugin.js +17 -0
- package/src/registry/plugins/test-plugin.js +23 -0
- package/src/registry/register-all.js +25 -0
- package/src/runtime/ssr.js +2 -2
- package/src/stdlib/inline.js +178 -3
- package/src/version.js +1 -1
package/src/stdlib/inline.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Tova standard library — inline string versions for codegen
|
|
2
2
|
// Single source of truth for all inline stdlib code used in code generation.
|
|
3
|
-
// Used by: base-codegen.js,
|
|
3
|
+
// Used by: base-codegen.js, browser-codegen.js, bin/tova.js
|
|
4
4
|
|
|
5
5
|
export const RESULT_OPTION = `class _Ok { constructor(value) { this.value = value; } }
|
|
6
6
|
_Ok.prototype.__tag = "Ok";
|
|
@@ -651,6 +651,173 @@ Table.prototype = { get rows() { return this._rows.length; }, get columns() { re
|
|
|
651
651
|
bold: `function bold(text) { if (typeof process !== 'undefined' && (process.env.NO_COLOR || (process.stdout && !process.stdout.isTTY))) return String(text); return '\\x1b[1m' + text + '\\x1b[0m'; }`,
|
|
652
652
|
dim: `function dim(text) { if (typeof process !== 'undefined' && (process.env.NO_COLOR || (process.stdout && !process.stdout.isTTY))) return String(text); return '\\x1b[2m' + text + '\\x1b[0m'; }`,
|
|
653
653
|
|
|
654
|
+
// ── Scripting: Color shortcuts ────────────────────────
|
|
655
|
+
green: `function green(text) { return color(text, 'green'); }`,
|
|
656
|
+
red: `function red(text) { return color(text, 'red'); }`,
|
|
657
|
+
yellow: `function yellow(text) { return color(text, 'yellow'); }`,
|
|
658
|
+
blue: `function blue(text) { return color(text, 'blue'); }`,
|
|
659
|
+
cyan: `function cyan(text) { return color(text, 'cyan'); }`,
|
|
660
|
+
magenta: `function magenta(text) { return color(text, 'magenta'); }`,
|
|
661
|
+
gray: `function gray(text) { return color(text, 'gray'); }`,
|
|
662
|
+
underline: `function underline(text) { if (typeof process !== 'undefined' && (process.env.NO_COLOR || (process.stdout && !process.stdout.isTTY))) return String(text); return '\\x1b[4m' + text + '\\x1b[0m'; }`,
|
|
663
|
+
strikethrough: `function strikethrough(text) { if (typeof process !== 'undefined' && (process.env.NO_COLOR || (process.stdout && !process.stdout.isTTY))) return String(text); return '\\x1b[9m' + text + '\\x1b[0m'; }`,
|
|
664
|
+
|
|
665
|
+
// ── Scripting: Rich output ────────────────────────────
|
|
666
|
+
table: `function table(data, opts) {
|
|
667
|
+
if (!data || data.length === 0) { console.log("(empty)"); return; }
|
|
668
|
+
const o = opts || {};
|
|
669
|
+
const headers = o.headers || Object.keys(data[0]);
|
|
670
|
+
const rows = data.map(function(row) { return headers.map(function(h) { return String(row[h] != null ? row[h] : ''); }); });
|
|
671
|
+
const widths = headers.map(function(h, i) {
|
|
672
|
+
return Math.max(h.length, ...rows.map(function(r) { return r[i].length; }));
|
|
673
|
+
});
|
|
674
|
+
const noColor = typeof process !== 'undefined' && (process.env.NO_COLOR || (process.stdout && !process.stdout.isTTY));
|
|
675
|
+
const b = function(t) { return noColor ? t : '\\x1b[1m' + t + '\\x1b[0m'; };
|
|
676
|
+
const line = widths.map(function(w) { return '-'.repeat(w + 2); }).join('+');
|
|
677
|
+
console.log(b(headers.map(function(h, i) { return ' ' + h.padEnd(widths[i]) + ' '; }).join('|')));
|
|
678
|
+
console.log(line);
|
|
679
|
+
rows.forEach(function(r) { console.log(r.map(function(c, i) { return ' ' + c.padEnd(widths[i]) + ' '; }).join('|')); });
|
|
680
|
+
}`,
|
|
681
|
+
|
|
682
|
+
panel: `function panel(title, content) {
|
|
683
|
+
var lines = String(content).split('\\n');
|
|
684
|
+
var maxLen = Math.max(title ? title.length + 2 : 0, ...lines.map(function(l) { return l.length; }));
|
|
685
|
+
var noColor = typeof process !== 'undefined' && (process.env.NO_COLOR || (process.stdout && !process.stdout.isTTY));
|
|
686
|
+
var b = function(t) { return noColor ? t : '\\x1b[1m' + t + '\\x1b[0m'; };
|
|
687
|
+
var top = '\\u250c' + (title ? '\\u2500 ' + b(title) + ' ' + '\\u2500'.repeat(Math.max(0, maxLen - title.length - 2)) : '\\u2500'.repeat(maxLen + 2)) + '\\u2510';
|
|
688
|
+
var bot = '\\u2514' + '\\u2500'.repeat(maxLen + 2) + '\\u2518';
|
|
689
|
+
var body = lines.map(function(l) { return '\\u2502 ' + l.padEnd(maxLen) + ' \\u2502'; }).join('\\n');
|
|
690
|
+
console.log(top + '\\n' + body + '\\n' + bot);
|
|
691
|
+
}`,
|
|
692
|
+
|
|
693
|
+
progress: `function progress(items, opts) {
|
|
694
|
+
var o = opts || {};
|
|
695
|
+
var total = items.length || o.total || 0;
|
|
696
|
+
var label = o.label || '';
|
|
697
|
+
var width = o.width || 30;
|
|
698
|
+
var isTTY = typeof process !== 'undefined' && process.stderr && process.stderr.isTTY;
|
|
699
|
+
var idx = 0;
|
|
700
|
+
return { [Symbol.iterator]() {
|
|
701
|
+
var it = items[Symbol.iterator]();
|
|
702
|
+
return { next() {
|
|
703
|
+
var r = it.next();
|
|
704
|
+
if (!r.done) {
|
|
705
|
+
idx++;
|
|
706
|
+
if (isTTY) {
|
|
707
|
+
var pct = Math.round(idx / total * 100);
|
|
708
|
+
var filled = Math.round(idx / total * width);
|
|
709
|
+
var bar = '\\u2588'.repeat(filled) + '\\u2591'.repeat(width - filled);
|
|
710
|
+
process.stderr.write('\\r' + label + ' [' + bar + '] ' + pct + '% ' + idx + '/' + total);
|
|
711
|
+
}
|
|
712
|
+
} else if (isTTY) {
|
|
713
|
+
process.stderr.write('\\r' + ' '.repeat(width + label.length + 20) + '\\r');
|
|
714
|
+
}
|
|
715
|
+
return r;
|
|
716
|
+
}};
|
|
717
|
+
}};
|
|
718
|
+
}`,
|
|
719
|
+
|
|
720
|
+
spin: `async function spin(label, fn) {
|
|
721
|
+
var frames = ['\\u2838','\\u2834','\\u2826','\\u2823','\\u2831','\\u2839'];
|
|
722
|
+
var isTTY = typeof process !== 'undefined' && process.stderr && process.stderr.isTTY;
|
|
723
|
+
var i = 0;
|
|
724
|
+
var iv = isTTY ? setInterval(function() { process.stderr.write('\\r' + frames[i++ % frames.length] + ' ' + label); }, 80) : null;
|
|
725
|
+
try {
|
|
726
|
+
var result = await fn();
|
|
727
|
+
if (iv) clearInterval(iv);
|
|
728
|
+
if (isTTY) process.stderr.write('\\r\\u2714 ' + label + '\\n');
|
|
729
|
+
return result;
|
|
730
|
+
} catch (e) {
|
|
731
|
+
if (iv) clearInterval(iv);
|
|
732
|
+
if (isTTY) process.stderr.write('\\r\\u2718 ' + label + '\\n');
|
|
733
|
+
throw e;
|
|
734
|
+
}
|
|
735
|
+
}`,
|
|
736
|
+
|
|
737
|
+
// ── Scripting: Interactive prompts ─────────────────────
|
|
738
|
+
ask: `async function ask(prompt, opts) {
|
|
739
|
+
var o = opts || {};
|
|
740
|
+
var rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
|
|
741
|
+
var suffix = o.default ? ' (' + o.default + ')' : '';
|
|
742
|
+
return new Promise(function(resolve) {
|
|
743
|
+
rl.question(prompt + suffix + ' ', function(answer) {
|
|
744
|
+
rl.close();
|
|
745
|
+
resolve(answer || o.default || '');
|
|
746
|
+
});
|
|
747
|
+
});
|
|
748
|
+
}`,
|
|
749
|
+
|
|
750
|
+
confirm: `async function confirm(prompt, opts) {
|
|
751
|
+
var o = opts || {};
|
|
752
|
+
var def = o.default !== undefined ? o.default : true;
|
|
753
|
+
var hint = def ? '[Y/n]' : '[y/N]';
|
|
754
|
+
var rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
|
|
755
|
+
return new Promise(function(resolve) {
|
|
756
|
+
rl.question(prompt + ' ' + hint + ' ', function(answer) {
|
|
757
|
+
rl.close();
|
|
758
|
+
if (!answer) { resolve(def); return; }
|
|
759
|
+
resolve(answer.toLowerCase().startsWith('y'));
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
}`,
|
|
763
|
+
|
|
764
|
+
choose: `async function choose(prompt, options) {
|
|
765
|
+
console.log(prompt);
|
|
766
|
+
for (var i = 0; i < options.length; i++) console.log(' ' + (i + 1) + '. ' + options[i]);
|
|
767
|
+
var rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
|
|
768
|
+
return new Promise(function(resolve) {
|
|
769
|
+
rl.question('Select [1-' + options.length + ']: ', function(answer) {
|
|
770
|
+
rl.close();
|
|
771
|
+
var idx = parseInt(answer, 10) - 1;
|
|
772
|
+
resolve(idx >= 0 && idx < options.length ? options[idx] : options[0]);
|
|
773
|
+
});
|
|
774
|
+
});
|
|
775
|
+
}`,
|
|
776
|
+
|
|
777
|
+
choose_many: `async function choose_many(prompt, options) {
|
|
778
|
+
console.log(prompt);
|
|
779
|
+
for (var i = 0; i < options.length; i++) console.log(' ' + (i + 1) + '. ' + options[i]);
|
|
780
|
+
var rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
|
|
781
|
+
return new Promise(function(resolve) {
|
|
782
|
+
rl.question('Select (comma-separated): ', function(answer) {
|
|
783
|
+
rl.close();
|
|
784
|
+
var indices = answer.split(',').map(function(s) { return parseInt(s.trim(), 10) - 1; });
|
|
785
|
+
resolve(indices.filter(function(i) { return i >= 0 && i < options.length; }).map(function(i) { return options[i]; }));
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
}`,
|
|
789
|
+
|
|
790
|
+
secret: `async function secret(prompt) {
|
|
791
|
+
var rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
|
|
792
|
+
return new Promise(function(resolve) {
|
|
793
|
+
if (process.stdin.isTTY) {
|
|
794
|
+
process.stdout.write(prompt + ' ');
|
|
795
|
+
process.stdin.setRawMode(true);
|
|
796
|
+
process.stdin.resume();
|
|
797
|
+
var buf = '';
|
|
798
|
+
var onData = function(ch) {
|
|
799
|
+
ch = ch.toString();
|
|
800
|
+
if (ch === '\\n' || ch === '\\r' || ch === '\\u0004') {
|
|
801
|
+
process.stdin.setRawMode(false);
|
|
802
|
+
process.stdin.pause();
|
|
803
|
+
process.stdin.removeListener('data', onData);
|
|
804
|
+
process.stdout.write('\\n');
|
|
805
|
+
rl.close();
|
|
806
|
+
resolve(buf);
|
|
807
|
+
} else if (ch === '\\u007f' || ch === '\\b') {
|
|
808
|
+
if (buf.length > 0) { buf = buf.slice(0, -1); process.stdout.write('\\b \\b'); }
|
|
809
|
+
} else {
|
|
810
|
+
buf += ch;
|
|
811
|
+
process.stdout.write('*');
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
process.stdin.on('data', onData);
|
|
815
|
+
} else {
|
|
816
|
+
rl.question(prompt + ' ', function(answer) { rl.close(); resolve(answer); });
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
}`,
|
|
820
|
+
|
|
654
821
|
// ── Scripting: Signal handling ────────────────────────
|
|
655
822
|
on_signal: `function on_signal(name, callback) { process.on(name, callback); }`,
|
|
656
823
|
|
|
@@ -1169,6 +1336,14 @@ export const STDLIB_DEPS = {
|
|
|
1169
1336
|
compare_by: ['Less', 'Equal', 'Greater'],
|
|
1170
1337
|
// mock/spy
|
|
1171
1338
|
create_mock: ['create_spy'],
|
|
1339
|
+
// color shortcuts depend on color()
|
|
1340
|
+
green: ['color'],
|
|
1341
|
+
red: ['color'],
|
|
1342
|
+
yellow: ['color'],
|
|
1343
|
+
blue: ['color'],
|
|
1344
|
+
cyan: ['color'],
|
|
1345
|
+
magenta: ['color'],
|
|
1346
|
+
gray: ['color'],
|
|
1172
1347
|
};
|
|
1173
1348
|
|
|
1174
1349
|
// Resolve all transitive dependencies for a set of used names
|
|
@@ -1286,7 +1461,7 @@ export function getFullStdlib() {
|
|
|
1286
1461
|
return `${NATIVE_INIT_SYNC}\n${buildSelectiveStdlib(BUILTIN_NAMES)}\n${RESULT_OPTION}\n${PROPAGATE}`;
|
|
1287
1462
|
}
|
|
1288
1463
|
|
|
1289
|
-
// Stdlib for
|
|
1290
|
-
export function
|
|
1464
|
+
// Stdlib for browser codegen (includes builtins + result/option + propagate)
|
|
1465
|
+
export function getBrowserStdlib() {
|
|
1291
1466
|
return `${buildSelectiveStdlib(BUILTIN_NAMES)}\n${RESULT_OPTION}\n${PROPAGATE}`;
|
|
1292
1467
|
}
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/embed-runtime.js — do not edit
|
|
2
|
-
export const VERSION = "0.
|
|
2
|
+
export const VERSION = "0.7.0";
|