@calebmabry/wami 0.1.2 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +58 -26
  2. package/dist/cli.js +2780 -161
  3. package/package.json +35 -4
package/dist/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  var __create = Object.create;
3
4
  var __getProtoOf = Object.getPrototypeOf;
4
5
  var __defProp = Object.defineProperty;
@@ -16,6 +17,7 @@ var __toESM = (mod, isNodeMode, target) => {
16
17
  return to;
17
18
  };
18
19
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
20
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
21
 
20
22
  // node_modules/cli-spinners/spinners.json
21
23
  var require_spinners = __commonJS((exports, module) => {
@@ -1657,12 +1659,2001 @@ var require_cli_spinners = __commonJS((exports, module) => {
1657
1659
  module.exports = spinners;
1658
1660
  });
1659
1661
 
1662
+ // node_modules/@iarna/toml/lib/parser.js
1663
+ var require_parser = __commonJS((exports, module) => {
1664
+ var ParserEND = 1114112;
1665
+
1666
+ class ParserError extends Error {
1667
+ constructor(msg, filename, linenumber) {
1668
+ super("[ParserError] " + msg, filename, linenumber);
1669
+ this.name = "ParserError";
1670
+ this.code = "ParserError";
1671
+ if (Error.captureStackTrace)
1672
+ Error.captureStackTrace(this, ParserError);
1673
+ }
1674
+ }
1675
+
1676
+ class State {
1677
+ constructor(parser) {
1678
+ this.parser = parser;
1679
+ this.buf = "";
1680
+ this.returned = null;
1681
+ this.result = null;
1682
+ this.resultTable = null;
1683
+ this.resultArr = null;
1684
+ }
1685
+ }
1686
+
1687
+ class Parser {
1688
+ constructor() {
1689
+ this.pos = 0;
1690
+ this.col = 0;
1691
+ this.line = 0;
1692
+ this.obj = {};
1693
+ this.ctx = this.obj;
1694
+ this.stack = [];
1695
+ this._buf = "";
1696
+ this.char = null;
1697
+ this.ii = 0;
1698
+ this.state = new State(this.parseStart);
1699
+ }
1700
+ parse(str) {
1701
+ if (str.length === 0 || str.length == null)
1702
+ return;
1703
+ this._buf = String(str);
1704
+ this.ii = -1;
1705
+ this.char = -1;
1706
+ let getNext;
1707
+ while (getNext === false || this.nextChar()) {
1708
+ getNext = this.runOne();
1709
+ }
1710
+ this._buf = null;
1711
+ }
1712
+ nextChar() {
1713
+ if (this.char === 10) {
1714
+ ++this.line;
1715
+ this.col = -1;
1716
+ }
1717
+ ++this.ii;
1718
+ this.char = this._buf.codePointAt(this.ii);
1719
+ ++this.pos;
1720
+ ++this.col;
1721
+ return this.haveBuffer();
1722
+ }
1723
+ haveBuffer() {
1724
+ return this.ii < this._buf.length;
1725
+ }
1726
+ runOne() {
1727
+ return this.state.parser.call(this, this.state.returned);
1728
+ }
1729
+ finish() {
1730
+ this.char = ParserEND;
1731
+ let last;
1732
+ do {
1733
+ last = this.state.parser;
1734
+ this.runOne();
1735
+ } while (this.state.parser !== last);
1736
+ this.ctx = null;
1737
+ this.state = null;
1738
+ this._buf = null;
1739
+ return this.obj;
1740
+ }
1741
+ next(fn) {
1742
+ if (typeof fn !== "function")
1743
+ throw new ParserError("Tried to set state to non-existent state: " + JSON.stringify(fn));
1744
+ this.state.parser = fn;
1745
+ }
1746
+ goto(fn) {
1747
+ this.next(fn);
1748
+ return this.runOne();
1749
+ }
1750
+ call(fn, returnWith) {
1751
+ if (returnWith)
1752
+ this.next(returnWith);
1753
+ this.stack.push(this.state);
1754
+ this.state = new State(fn);
1755
+ }
1756
+ callNow(fn, returnWith) {
1757
+ this.call(fn, returnWith);
1758
+ return this.runOne();
1759
+ }
1760
+ return(value) {
1761
+ if (this.stack.length === 0)
1762
+ throw this.error(new ParserError("Stack underflow"));
1763
+ if (value === undefined)
1764
+ value = this.state.buf;
1765
+ this.state = this.stack.pop();
1766
+ this.state.returned = value;
1767
+ }
1768
+ returnNow(value) {
1769
+ this.return(value);
1770
+ return this.runOne();
1771
+ }
1772
+ consume() {
1773
+ if (this.char === ParserEND)
1774
+ throw this.error(new ParserError("Unexpected end-of-buffer"));
1775
+ this.state.buf += this._buf[this.ii];
1776
+ }
1777
+ error(err) {
1778
+ err.line = this.line;
1779
+ err.col = this.col;
1780
+ err.pos = this.pos;
1781
+ return err;
1782
+ }
1783
+ parseStart() {
1784
+ throw new ParserError("Must declare a parseStart method");
1785
+ }
1786
+ }
1787
+ Parser.END = ParserEND;
1788
+ Parser.Error = ParserError;
1789
+ module.exports = Parser;
1790
+ });
1791
+
1792
+ // node_modules/@iarna/toml/lib/create-datetime.js
1793
+ var require_create_datetime = __commonJS((exports, module) => {
1794
+ module.exports = (value) => {
1795
+ const date = new Date(value);
1796
+ if (isNaN(date)) {
1797
+ throw new TypeError("Invalid Datetime");
1798
+ } else {
1799
+ return date;
1800
+ }
1801
+ };
1802
+ });
1803
+
1804
+ // node_modules/@iarna/toml/lib/format-num.js
1805
+ var require_format_num = __commonJS((exports, module) => {
1806
+ module.exports = (d, num) => {
1807
+ num = String(num);
1808
+ while (num.length < d)
1809
+ num = "0" + num;
1810
+ return num;
1811
+ };
1812
+ });
1813
+
1814
+ // node_modules/@iarna/toml/lib/create-datetime-float.js
1815
+ var require_create_datetime_float = __commonJS((exports, module) => {
1816
+ var f = require_format_num();
1817
+
1818
+ class FloatingDateTime extends Date {
1819
+ constructor(value) {
1820
+ super(value + "Z");
1821
+ this.isFloating = true;
1822
+ }
1823
+ toISOString() {
1824
+ const date = `${this.getUTCFullYear()}-${f(2, this.getUTCMonth() + 1)}-${f(2, this.getUTCDate())}`;
1825
+ const time = `${f(2, this.getUTCHours())}:${f(2, this.getUTCMinutes())}:${f(2, this.getUTCSeconds())}.${f(3, this.getUTCMilliseconds())}`;
1826
+ return `${date}T${time}`;
1827
+ }
1828
+ }
1829
+ module.exports = (value) => {
1830
+ const date = new FloatingDateTime(value);
1831
+ if (isNaN(date)) {
1832
+ throw new TypeError("Invalid Datetime");
1833
+ } else {
1834
+ return date;
1835
+ }
1836
+ };
1837
+ });
1838
+
1839
+ // node_modules/@iarna/toml/lib/create-date.js
1840
+ var require_create_date = __commonJS((exports, module) => {
1841
+ var f = require_format_num();
1842
+ var DateTime = global.Date;
1843
+
1844
+ class Date2 extends DateTime {
1845
+ constructor(value) {
1846
+ super(value);
1847
+ this.isDate = true;
1848
+ }
1849
+ toISOString() {
1850
+ return `${this.getUTCFullYear()}-${f(2, this.getUTCMonth() + 1)}-${f(2, this.getUTCDate())}`;
1851
+ }
1852
+ }
1853
+ module.exports = (value) => {
1854
+ const date = new Date2(value);
1855
+ if (isNaN(date)) {
1856
+ throw new TypeError("Invalid Datetime");
1857
+ } else {
1858
+ return date;
1859
+ }
1860
+ };
1861
+ });
1862
+
1863
+ // node_modules/@iarna/toml/lib/create-time.js
1864
+ var require_create_time = __commonJS((exports, module) => {
1865
+ var f = require_format_num();
1866
+
1867
+ class Time extends Date {
1868
+ constructor(value) {
1869
+ super(`0000-01-01T${value}Z`);
1870
+ this.isTime = true;
1871
+ }
1872
+ toISOString() {
1873
+ return `${f(2, this.getUTCHours())}:${f(2, this.getUTCMinutes())}:${f(2, this.getUTCSeconds())}.${f(3, this.getUTCMilliseconds())}`;
1874
+ }
1875
+ }
1876
+ module.exports = (value) => {
1877
+ const date = new Time(value);
1878
+ if (isNaN(date)) {
1879
+ throw new TypeError("Invalid Datetime");
1880
+ } else {
1881
+ return date;
1882
+ }
1883
+ };
1884
+ });
1885
+
1886
+ // node_modules/@iarna/toml/lib/toml-parser.js
1887
+ var require_toml_parser = __commonJS((exports, module) => {
1888
+ module.exports = makeParserClass(require_parser());
1889
+ module.exports.makeParserClass = makeParserClass;
1890
+
1891
+ class TomlError extends Error {
1892
+ constructor(msg) {
1893
+ super(msg);
1894
+ this.name = "TomlError";
1895
+ if (Error.captureStackTrace)
1896
+ Error.captureStackTrace(this, TomlError);
1897
+ this.fromTOML = true;
1898
+ this.wrapped = null;
1899
+ }
1900
+ }
1901
+ TomlError.wrap = (err) => {
1902
+ const terr = new TomlError(err.message);
1903
+ terr.code = err.code;
1904
+ terr.wrapped = err;
1905
+ return terr;
1906
+ };
1907
+ module.exports.TomlError = TomlError;
1908
+ var createDateTime = require_create_datetime();
1909
+ var createDateTimeFloat = require_create_datetime_float();
1910
+ var createDate = require_create_date();
1911
+ var createTime = require_create_time();
1912
+ var CTRL_I = 9;
1913
+ var CTRL_J = 10;
1914
+ var CTRL_M = 13;
1915
+ var CTRL_CHAR_BOUNDARY = 31;
1916
+ var CHAR_SP = 32;
1917
+ var CHAR_QUOT = 34;
1918
+ var CHAR_NUM = 35;
1919
+ var CHAR_APOS = 39;
1920
+ var CHAR_PLUS = 43;
1921
+ var CHAR_COMMA = 44;
1922
+ var CHAR_HYPHEN = 45;
1923
+ var CHAR_PERIOD = 46;
1924
+ var CHAR_0 = 48;
1925
+ var CHAR_1 = 49;
1926
+ var CHAR_7 = 55;
1927
+ var CHAR_9 = 57;
1928
+ var CHAR_COLON = 58;
1929
+ var CHAR_EQUALS = 61;
1930
+ var CHAR_A = 65;
1931
+ var CHAR_E = 69;
1932
+ var CHAR_F = 70;
1933
+ var CHAR_T = 84;
1934
+ var CHAR_U = 85;
1935
+ var CHAR_Z = 90;
1936
+ var CHAR_LOWBAR = 95;
1937
+ var CHAR_a = 97;
1938
+ var CHAR_b = 98;
1939
+ var CHAR_e = 101;
1940
+ var CHAR_f = 102;
1941
+ var CHAR_i = 105;
1942
+ var CHAR_l = 108;
1943
+ var CHAR_n = 110;
1944
+ var CHAR_o = 111;
1945
+ var CHAR_r = 114;
1946
+ var CHAR_s = 115;
1947
+ var CHAR_t = 116;
1948
+ var CHAR_u = 117;
1949
+ var CHAR_x = 120;
1950
+ var CHAR_z = 122;
1951
+ var CHAR_LCUB = 123;
1952
+ var CHAR_RCUB = 125;
1953
+ var CHAR_LSQB = 91;
1954
+ var CHAR_BSOL = 92;
1955
+ var CHAR_RSQB = 93;
1956
+ var CHAR_DEL = 127;
1957
+ var SURROGATE_FIRST = 55296;
1958
+ var SURROGATE_LAST = 57343;
1959
+ var escapes = {
1960
+ [CHAR_b]: "\b",
1961
+ [CHAR_t]: "\t",
1962
+ [CHAR_n]: `
1963
+ `,
1964
+ [CHAR_f]: "\f",
1965
+ [CHAR_r]: "\r",
1966
+ [CHAR_QUOT]: '"',
1967
+ [CHAR_BSOL]: "\\"
1968
+ };
1969
+ function isDigit(cp) {
1970
+ return cp >= CHAR_0 && cp <= CHAR_9;
1971
+ }
1972
+ function isHexit(cp) {
1973
+ return cp >= CHAR_A && cp <= CHAR_F || cp >= CHAR_a && cp <= CHAR_f || cp >= CHAR_0 && cp <= CHAR_9;
1974
+ }
1975
+ function isBit(cp) {
1976
+ return cp === CHAR_1 || cp === CHAR_0;
1977
+ }
1978
+ function isOctit(cp) {
1979
+ return cp >= CHAR_0 && cp <= CHAR_7;
1980
+ }
1981
+ function isAlphaNumQuoteHyphen(cp) {
1982
+ return cp >= CHAR_A && cp <= CHAR_Z || cp >= CHAR_a && cp <= CHAR_z || cp >= CHAR_0 && cp <= CHAR_9 || cp === CHAR_APOS || cp === CHAR_QUOT || cp === CHAR_LOWBAR || cp === CHAR_HYPHEN;
1983
+ }
1984
+ function isAlphaNumHyphen(cp) {
1985
+ return cp >= CHAR_A && cp <= CHAR_Z || cp >= CHAR_a && cp <= CHAR_z || cp >= CHAR_0 && cp <= CHAR_9 || cp === CHAR_LOWBAR || cp === CHAR_HYPHEN;
1986
+ }
1987
+ var _type = Symbol("type");
1988
+ var _declared = Symbol("declared");
1989
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
1990
+ var defineProperty = Object.defineProperty;
1991
+ var descriptor = { configurable: true, enumerable: true, writable: true, value: undefined };
1992
+ function hasKey(obj, key) {
1993
+ if (hasOwnProperty.call(obj, key))
1994
+ return true;
1995
+ if (key === "__proto__")
1996
+ defineProperty(obj, "__proto__", descriptor);
1997
+ return false;
1998
+ }
1999
+ var INLINE_TABLE = Symbol("inline-table");
2000
+ function InlineTable() {
2001
+ return Object.defineProperties({}, {
2002
+ [_type]: { value: INLINE_TABLE }
2003
+ });
2004
+ }
2005
+ function isInlineTable(obj) {
2006
+ if (obj === null || typeof obj !== "object")
2007
+ return false;
2008
+ return obj[_type] === INLINE_TABLE;
2009
+ }
2010
+ var TABLE = Symbol("table");
2011
+ function Table() {
2012
+ return Object.defineProperties({}, {
2013
+ [_type]: { value: TABLE },
2014
+ [_declared]: { value: false, writable: true }
2015
+ });
2016
+ }
2017
+ function isTable(obj) {
2018
+ if (obj === null || typeof obj !== "object")
2019
+ return false;
2020
+ return obj[_type] === TABLE;
2021
+ }
2022
+ var _contentType = Symbol("content-type");
2023
+ var INLINE_LIST = Symbol("inline-list");
2024
+ function InlineList(type) {
2025
+ return Object.defineProperties([], {
2026
+ [_type]: { value: INLINE_LIST },
2027
+ [_contentType]: { value: type }
2028
+ });
2029
+ }
2030
+ function isInlineList(obj) {
2031
+ if (obj === null || typeof obj !== "object")
2032
+ return false;
2033
+ return obj[_type] === INLINE_LIST;
2034
+ }
2035
+ var LIST = Symbol("list");
2036
+ function List() {
2037
+ return Object.defineProperties([], {
2038
+ [_type]: { value: LIST }
2039
+ });
2040
+ }
2041
+ function isList(obj) {
2042
+ if (obj === null || typeof obj !== "object")
2043
+ return false;
2044
+ return obj[_type] === LIST;
2045
+ }
2046
+ var _custom;
2047
+ try {
2048
+ const utilInspect = eval("require('util').inspect");
2049
+ _custom = utilInspect.custom;
2050
+ } catch (_) {}
2051
+ var _inspect = _custom || "inspect";
2052
+
2053
+ class BoxedBigInt {
2054
+ constructor(value) {
2055
+ try {
2056
+ this.value = global.BigInt.asIntN(64, value);
2057
+ } catch (_) {
2058
+ this.value = null;
2059
+ }
2060
+ Object.defineProperty(this, _type, { value: INTEGER });
2061
+ }
2062
+ isNaN() {
2063
+ return this.value === null;
2064
+ }
2065
+ toString() {
2066
+ return String(this.value);
2067
+ }
2068
+ [_inspect]() {
2069
+ return `[BigInt: ${this.toString()}]}`;
2070
+ }
2071
+ valueOf() {
2072
+ return this.value;
2073
+ }
2074
+ }
2075
+ var INTEGER = Symbol("integer");
2076
+ function Integer(value) {
2077
+ let num = Number(value);
2078
+ if (Object.is(num, -0))
2079
+ num = 0;
2080
+ if (global.BigInt && !Number.isSafeInteger(num)) {
2081
+ return new BoxedBigInt(value);
2082
+ } else {
2083
+ return Object.defineProperties(new Number(num), {
2084
+ isNaN: { value: function() {
2085
+ return isNaN(this);
2086
+ } },
2087
+ [_type]: { value: INTEGER },
2088
+ [_inspect]: { value: () => `[Integer: ${value}]` }
2089
+ });
2090
+ }
2091
+ }
2092
+ function isInteger(obj) {
2093
+ if (obj === null || typeof obj !== "object")
2094
+ return false;
2095
+ return obj[_type] === INTEGER;
2096
+ }
2097
+ var FLOAT = Symbol("float");
2098
+ function Float(value) {
2099
+ return Object.defineProperties(new Number(value), {
2100
+ [_type]: { value: FLOAT },
2101
+ [_inspect]: { value: () => `[Float: ${value}]` }
2102
+ });
2103
+ }
2104
+ function isFloat(obj) {
2105
+ if (obj === null || typeof obj !== "object")
2106
+ return false;
2107
+ return obj[_type] === FLOAT;
2108
+ }
2109
+ function tomlType(value) {
2110
+ const type = typeof value;
2111
+ if (type === "object") {
2112
+ if (value === null)
2113
+ return "null";
2114
+ if (value instanceof Date)
2115
+ return "datetime";
2116
+ if (_type in value) {
2117
+ switch (value[_type]) {
2118
+ case INLINE_TABLE:
2119
+ return "inline-table";
2120
+ case INLINE_LIST:
2121
+ return "inline-list";
2122
+ case TABLE:
2123
+ return "table";
2124
+ case LIST:
2125
+ return "list";
2126
+ case FLOAT:
2127
+ return "float";
2128
+ case INTEGER:
2129
+ return "integer";
2130
+ }
2131
+ }
2132
+ }
2133
+ return type;
2134
+ }
2135
+ function makeParserClass(Parser) {
2136
+
2137
+ class TOMLParser extends Parser {
2138
+ constructor() {
2139
+ super();
2140
+ this.ctx = this.obj = Table();
2141
+ }
2142
+ atEndOfWord() {
2143
+ return this.char === CHAR_NUM || this.char === CTRL_I || this.char === CHAR_SP || this.atEndOfLine();
2144
+ }
2145
+ atEndOfLine() {
2146
+ return this.char === Parser.END || this.char === CTRL_J || this.char === CTRL_M;
2147
+ }
2148
+ parseStart() {
2149
+ if (this.char === Parser.END) {
2150
+ return null;
2151
+ } else if (this.char === CHAR_LSQB) {
2152
+ return this.call(this.parseTableOrList);
2153
+ } else if (this.char === CHAR_NUM) {
2154
+ return this.call(this.parseComment);
2155
+ } else if (this.char === CTRL_J || this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) {
2156
+ return null;
2157
+ } else if (isAlphaNumQuoteHyphen(this.char)) {
2158
+ return this.callNow(this.parseAssignStatement);
2159
+ } else {
2160
+ throw this.error(new TomlError(`Unknown character "${this.char}"`));
2161
+ }
2162
+ }
2163
+ parseWhitespaceToEOL() {
2164
+ if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) {
2165
+ return null;
2166
+ } else if (this.char === CHAR_NUM) {
2167
+ return this.goto(this.parseComment);
2168
+ } else if (this.char === Parser.END || this.char === CTRL_J) {
2169
+ return this.return();
2170
+ } else {
2171
+ throw this.error(new TomlError("Unexpected character, expected only whitespace or comments till end of line"));
2172
+ }
2173
+ }
2174
+ parseAssignStatement() {
2175
+ return this.callNow(this.parseAssign, this.recordAssignStatement);
2176
+ }
2177
+ recordAssignStatement(kv) {
2178
+ let target = this.ctx;
2179
+ let finalKey = kv.key.pop();
2180
+ for (let kw of kv.key) {
2181
+ if (hasKey(target, kw) && (!isTable(target[kw]) || target[kw][_declared])) {
2182
+ throw this.error(new TomlError("Can't redefine existing key"));
2183
+ }
2184
+ target = target[kw] = target[kw] || Table();
2185
+ }
2186
+ if (hasKey(target, finalKey)) {
2187
+ throw this.error(new TomlError("Can't redefine existing key"));
2188
+ }
2189
+ if (isInteger(kv.value) || isFloat(kv.value)) {
2190
+ target[finalKey] = kv.value.valueOf();
2191
+ } else {
2192
+ target[finalKey] = kv.value;
2193
+ }
2194
+ return this.goto(this.parseWhitespaceToEOL);
2195
+ }
2196
+ parseAssign() {
2197
+ return this.callNow(this.parseKeyword, this.recordAssignKeyword);
2198
+ }
2199
+ recordAssignKeyword(key) {
2200
+ if (this.state.resultTable) {
2201
+ this.state.resultTable.push(key);
2202
+ } else {
2203
+ this.state.resultTable = [key];
2204
+ }
2205
+ return this.goto(this.parseAssignKeywordPreDot);
2206
+ }
2207
+ parseAssignKeywordPreDot() {
2208
+ if (this.char === CHAR_PERIOD) {
2209
+ return this.next(this.parseAssignKeywordPostDot);
2210
+ } else if (this.char !== CHAR_SP && this.char !== CTRL_I) {
2211
+ return this.goto(this.parseAssignEqual);
2212
+ }
2213
+ }
2214
+ parseAssignKeywordPostDot() {
2215
+ if (this.char !== CHAR_SP && this.char !== CTRL_I) {
2216
+ return this.callNow(this.parseKeyword, this.recordAssignKeyword);
2217
+ }
2218
+ }
2219
+ parseAssignEqual() {
2220
+ if (this.char === CHAR_EQUALS) {
2221
+ return this.next(this.parseAssignPreValue);
2222
+ } else {
2223
+ throw this.error(new TomlError('Invalid character, expected "="'));
2224
+ }
2225
+ }
2226
+ parseAssignPreValue() {
2227
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
2228
+ return null;
2229
+ } else {
2230
+ return this.callNow(this.parseValue, this.recordAssignValue);
2231
+ }
2232
+ }
2233
+ recordAssignValue(value) {
2234
+ return this.returnNow({ key: this.state.resultTable, value });
2235
+ }
2236
+ parseComment() {
2237
+ do {
2238
+ if (this.char === Parser.END || this.char === CTRL_J) {
2239
+ return this.return();
2240
+ }
2241
+ } while (this.nextChar());
2242
+ }
2243
+ parseTableOrList() {
2244
+ if (this.char === CHAR_LSQB) {
2245
+ this.next(this.parseList);
2246
+ } else {
2247
+ return this.goto(this.parseTable);
2248
+ }
2249
+ }
2250
+ parseTable() {
2251
+ this.ctx = this.obj;
2252
+ return this.goto(this.parseTableNext);
2253
+ }
2254
+ parseTableNext() {
2255
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
2256
+ return null;
2257
+ } else {
2258
+ return this.callNow(this.parseKeyword, this.parseTableMore);
2259
+ }
2260
+ }
2261
+ parseTableMore(keyword) {
2262
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
2263
+ return null;
2264
+ } else if (this.char === CHAR_RSQB) {
2265
+ if (hasKey(this.ctx, keyword) && (!isTable(this.ctx[keyword]) || this.ctx[keyword][_declared])) {
2266
+ throw this.error(new TomlError("Can't redefine existing key"));
2267
+ } else {
2268
+ this.ctx = this.ctx[keyword] = this.ctx[keyword] || Table();
2269
+ this.ctx[_declared] = true;
2270
+ }
2271
+ return this.next(this.parseWhitespaceToEOL);
2272
+ } else if (this.char === CHAR_PERIOD) {
2273
+ if (!hasKey(this.ctx, keyword)) {
2274
+ this.ctx = this.ctx[keyword] = Table();
2275
+ } else if (isTable(this.ctx[keyword])) {
2276
+ this.ctx = this.ctx[keyword];
2277
+ } else if (isList(this.ctx[keyword])) {
2278
+ this.ctx = this.ctx[keyword][this.ctx[keyword].length - 1];
2279
+ } else {
2280
+ throw this.error(new TomlError("Can't redefine existing key"));
2281
+ }
2282
+ return this.next(this.parseTableNext);
2283
+ } else {
2284
+ throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));
2285
+ }
2286
+ }
2287
+ parseList() {
2288
+ this.ctx = this.obj;
2289
+ return this.goto(this.parseListNext);
2290
+ }
2291
+ parseListNext() {
2292
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
2293
+ return null;
2294
+ } else {
2295
+ return this.callNow(this.parseKeyword, this.parseListMore);
2296
+ }
2297
+ }
2298
+ parseListMore(keyword) {
2299
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
2300
+ return null;
2301
+ } else if (this.char === CHAR_RSQB) {
2302
+ if (!hasKey(this.ctx, keyword)) {
2303
+ this.ctx[keyword] = List();
2304
+ }
2305
+ if (isInlineList(this.ctx[keyword])) {
2306
+ throw this.error(new TomlError("Can't extend an inline array"));
2307
+ } else if (isList(this.ctx[keyword])) {
2308
+ const next = Table();
2309
+ this.ctx[keyword].push(next);
2310
+ this.ctx = next;
2311
+ } else {
2312
+ throw this.error(new TomlError("Can't redefine an existing key"));
2313
+ }
2314
+ return this.next(this.parseListEnd);
2315
+ } else if (this.char === CHAR_PERIOD) {
2316
+ if (!hasKey(this.ctx, keyword)) {
2317
+ this.ctx = this.ctx[keyword] = Table();
2318
+ } else if (isInlineList(this.ctx[keyword])) {
2319
+ throw this.error(new TomlError("Can't extend an inline array"));
2320
+ } else if (isInlineTable(this.ctx[keyword])) {
2321
+ throw this.error(new TomlError("Can't extend an inline table"));
2322
+ } else if (isList(this.ctx[keyword])) {
2323
+ this.ctx = this.ctx[keyword][this.ctx[keyword].length - 1];
2324
+ } else if (isTable(this.ctx[keyword])) {
2325
+ this.ctx = this.ctx[keyword];
2326
+ } else {
2327
+ throw this.error(new TomlError("Can't redefine an existing key"));
2328
+ }
2329
+ return this.next(this.parseListNext);
2330
+ } else {
2331
+ throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));
2332
+ }
2333
+ }
2334
+ parseListEnd(keyword) {
2335
+ if (this.char === CHAR_RSQB) {
2336
+ return this.next(this.parseWhitespaceToEOL);
2337
+ } else {
2338
+ throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));
2339
+ }
2340
+ }
2341
+ parseValue() {
2342
+ if (this.char === Parser.END) {
2343
+ throw this.error(new TomlError("Key without value"));
2344
+ } else if (this.char === CHAR_QUOT) {
2345
+ return this.next(this.parseDoubleString);
2346
+ }
2347
+ if (this.char === CHAR_APOS) {
2348
+ return this.next(this.parseSingleString);
2349
+ } else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) {
2350
+ return this.goto(this.parseNumberSign);
2351
+ } else if (this.char === CHAR_i) {
2352
+ return this.next(this.parseInf);
2353
+ } else if (this.char === CHAR_n) {
2354
+ return this.next(this.parseNan);
2355
+ } else if (isDigit(this.char)) {
2356
+ return this.goto(this.parseNumberOrDateTime);
2357
+ } else if (this.char === CHAR_t || this.char === CHAR_f) {
2358
+ return this.goto(this.parseBoolean);
2359
+ } else if (this.char === CHAR_LSQB) {
2360
+ return this.call(this.parseInlineList, this.recordValue);
2361
+ } else if (this.char === CHAR_LCUB) {
2362
+ return this.call(this.parseInlineTable, this.recordValue);
2363
+ } else {
2364
+ throw this.error(new TomlError("Unexpected character, expecting string, number, datetime, boolean, inline array or inline table"));
2365
+ }
2366
+ }
2367
+ recordValue(value) {
2368
+ return this.returnNow(value);
2369
+ }
2370
+ parseInf() {
2371
+ if (this.char === CHAR_n) {
2372
+ return this.next(this.parseInf2);
2373
+ } else {
2374
+ throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'));
2375
+ }
2376
+ }
2377
+ parseInf2() {
2378
+ if (this.char === CHAR_f) {
2379
+ if (this.state.buf === "-") {
2380
+ return this.return(-Infinity);
2381
+ } else {
2382
+ return this.return(Infinity);
2383
+ }
2384
+ } else {
2385
+ throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'));
2386
+ }
2387
+ }
2388
+ parseNan() {
2389
+ if (this.char === CHAR_a) {
2390
+ return this.next(this.parseNan2);
2391
+ } else {
2392
+ throw this.error(new TomlError('Unexpected character, expected "nan"'));
2393
+ }
2394
+ }
2395
+ parseNan2() {
2396
+ if (this.char === CHAR_n) {
2397
+ return this.return(NaN);
2398
+ } else {
2399
+ throw this.error(new TomlError('Unexpected character, expected "nan"'));
2400
+ }
2401
+ }
2402
+ parseKeyword() {
2403
+ if (this.char === CHAR_QUOT) {
2404
+ return this.next(this.parseBasicString);
2405
+ } else if (this.char === CHAR_APOS) {
2406
+ return this.next(this.parseLiteralString);
2407
+ } else {
2408
+ return this.goto(this.parseBareKey);
2409
+ }
2410
+ }
2411
+ parseBareKey() {
2412
+ do {
2413
+ if (this.char === Parser.END) {
2414
+ throw this.error(new TomlError("Key ended without value"));
2415
+ } else if (isAlphaNumHyphen(this.char)) {
2416
+ this.consume();
2417
+ } else if (this.state.buf.length === 0) {
2418
+ throw this.error(new TomlError("Empty bare keys are not allowed"));
2419
+ } else {
2420
+ return this.returnNow();
2421
+ }
2422
+ } while (this.nextChar());
2423
+ }
2424
+ parseSingleString() {
2425
+ if (this.char === CHAR_APOS) {
2426
+ return this.next(this.parseLiteralMultiStringMaybe);
2427
+ } else {
2428
+ return this.goto(this.parseLiteralString);
2429
+ }
2430
+ }
2431
+ parseLiteralString() {
2432
+ do {
2433
+ if (this.char === CHAR_APOS) {
2434
+ return this.return();
2435
+ } else if (this.atEndOfLine()) {
2436
+ throw this.error(new TomlError("Unterminated string"));
2437
+ } else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I) {
2438
+ throw this.errorControlCharInString();
2439
+ } else {
2440
+ this.consume();
2441
+ }
2442
+ } while (this.nextChar());
2443
+ }
2444
+ parseLiteralMultiStringMaybe() {
2445
+ if (this.char === CHAR_APOS) {
2446
+ return this.next(this.parseLiteralMultiString);
2447
+ } else {
2448
+ return this.returnNow();
2449
+ }
2450
+ }
2451
+ parseLiteralMultiString() {
2452
+ if (this.char === CTRL_M) {
2453
+ return null;
2454
+ } else if (this.char === CTRL_J) {
2455
+ return this.next(this.parseLiteralMultiStringContent);
2456
+ } else {
2457
+ return this.goto(this.parseLiteralMultiStringContent);
2458
+ }
2459
+ }
2460
+ parseLiteralMultiStringContent() {
2461
+ do {
2462
+ if (this.char === CHAR_APOS) {
2463
+ return this.next(this.parseLiteralMultiEnd);
2464
+ } else if (this.char === Parser.END) {
2465
+ throw this.error(new TomlError("Unterminated multi-line string"));
2466
+ } else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I && this.char !== CTRL_J && this.char !== CTRL_M) {
2467
+ throw this.errorControlCharInString();
2468
+ } else {
2469
+ this.consume();
2470
+ }
2471
+ } while (this.nextChar());
2472
+ }
2473
+ parseLiteralMultiEnd() {
2474
+ if (this.char === CHAR_APOS) {
2475
+ return this.next(this.parseLiteralMultiEnd2);
2476
+ } else {
2477
+ this.state.buf += "'";
2478
+ return this.goto(this.parseLiteralMultiStringContent);
2479
+ }
2480
+ }
2481
+ parseLiteralMultiEnd2() {
2482
+ if (this.char === CHAR_APOS) {
2483
+ return this.return();
2484
+ } else {
2485
+ this.state.buf += "''";
2486
+ return this.goto(this.parseLiteralMultiStringContent);
2487
+ }
2488
+ }
2489
+ parseDoubleString() {
2490
+ if (this.char === CHAR_QUOT) {
2491
+ return this.next(this.parseMultiStringMaybe);
2492
+ } else {
2493
+ return this.goto(this.parseBasicString);
2494
+ }
2495
+ }
2496
+ parseBasicString() {
2497
+ do {
2498
+ if (this.char === CHAR_BSOL) {
2499
+ return this.call(this.parseEscape, this.recordEscapeReplacement);
2500
+ } else if (this.char === CHAR_QUOT) {
2501
+ return this.return();
2502
+ } else if (this.atEndOfLine()) {
2503
+ throw this.error(new TomlError("Unterminated string"));
2504
+ } else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I) {
2505
+ throw this.errorControlCharInString();
2506
+ } else {
2507
+ this.consume();
2508
+ }
2509
+ } while (this.nextChar());
2510
+ }
2511
+ recordEscapeReplacement(replacement) {
2512
+ this.state.buf += replacement;
2513
+ return this.goto(this.parseBasicString);
2514
+ }
2515
+ parseMultiStringMaybe() {
2516
+ if (this.char === CHAR_QUOT) {
2517
+ return this.next(this.parseMultiString);
2518
+ } else {
2519
+ return this.returnNow();
2520
+ }
2521
+ }
2522
+ parseMultiString() {
2523
+ if (this.char === CTRL_M) {
2524
+ return null;
2525
+ } else if (this.char === CTRL_J) {
2526
+ return this.next(this.parseMultiStringContent);
2527
+ } else {
2528
+ return this.goto(this.parseMultiStringContent);
2529
+ }
2530
+ }
2531
+ parseMultiStringContent() {
2532
+ do {
2533
+ if (this.char === CHAR_BSOL) {
2534
+ return this.call(this.parseMultiEscape, this.recordMultiEscapeReplacement);
2535
+ } else if (this.char === CHAR_QUOT) {
2536
+ return this.next(this.parseMultiEnd);
2537
+ } else if (this.char === Parser.END) {
2538
+ throw this.error(new TomlError("Unterminated multi-line string"));
2539
+ } else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I && this.char !== CTRL_J && this.char !== CTRL_M) {
2540
+ throw this.errorControlCharInString();
2541
+ } else {
2542
+ this.consume();
2543
+ }
2544
+ } while (this.nextChar());
2545
+ }
2546
+ errorControlCharInString() {
2547
+ let displayCode = "\\u00";
2548
+ if (this.char < 16) {
2549
+ displayCode += "0";
2550
+ }
2551
+ displayCode += this.char.toString(16);
2552
+ return this.error(new TomlError(`Control characters (codes < 0x1f and 0x7f) are not allowed in strings, use ${displayCode} instead`));
2553
+ }
2554
+ recordMultiEscapeReplacement(replacement) {
2555
+ this.state.buf += replacement;
2556
+ return this.goto(this.parseMultiStringContent);
2557
+ }
2558
+ parseMultiEnd() {
2559
+ if (this.char === CHAR_QUOT) {
2560
+ return this.next(this.parseMultiEnd2);
2561
+ } else {
2562
+ this.state.buf += '"';
2563
+ return this.goto(this.parseMultiStringContent);
2564
+ }
2565
+ }
2566
+ parseMultiEnd2() {
2567
+ if (this.char === CHAR_QUOT) {
2568
+ return this.return();
2569
+ } else {
2570
+ this.state.buf += '""';
2571
+ return this.goto(this.parseMultiStringContent);
2572
+ }
2573
+ }
2574
+ parseMultiEscape() {
2575
+ if (this.char === CTRL_M || this.char === CTRL_J) {
2576
+ return this.next(this.parseMultiTrim);
2577
+ } else if (this.char === CHAR_SP || this.char === CTRL_I) {
2578
+ return this.next(this.parsePreMultiTrim);
2579
+ } else {
2580
+ return this.goto(this.parseEscape);
2581
+ }
2582
+ }
2583
+ parsePreMultiTrim() {
2584
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
2585
+ return null;
2586
+ } else if (this.char === CTRL_M || this.char === CTRL_J) {
2587
+ return this.next(this.parseMultiTrim);
2588
+ } else {
2589
+ throw this.error(new TomlError("Can't escape whitespace"));
2590
+ }
2591
+ }
2592
+ parseMultiTrim() {
2593
+ if (this.char === CTRL_J || this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) {
2594
+ return null;
2595
+ } else {
2596
+ return this.returnNow();
2597
+ }
2598
+ }
2599
+ parseEscape() {
2600
+ if (this.char in escapes) {
2601
+ return this.return(escapes[this.char]);
2602
+ } else if (this.char === CHAR_u) {
2603
+ return this.call(this.parseSmallUnicode, this.parseUnicodeReturn);
2604
+ } else if (this.char === CHAR_U) {
2605
+ return this.call(this.parseLargeUnicode, this.parseUnicodeReturn);
2606
+ } else {
2607
+ throw this.error(new TomlError("Unknown escape character: " + this.char));
2608
+ }
2609
+ }
2610
+ parseUnicodeReturn(char) {
2611
+ try {
2612
+ const codePoint = parseInt(char, 16);
2613
+ if (codePoint >= SURROGATE_FIRST && codePoint <= SURROGATE_LAST) {
2614
+ throw this.error(new TomlError("Invalid unicode, character in range 0xD800 - 0xDFFF is reserved"));
2615
+ }
2616
+ return this.returnNow(String.fromCodePoint(codePoint));
2617
+ } catch (err) {
2618
+ throw this.error(TomlError.wrap(err));
2619
+ }
2620
+ }
2621
+ parseSmallUnicode() {
2622
+ if (!isHexit(this.char)) {
2623
+ throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"));
2624
+ } else {
2625
+ this.consume();
2626
+ if (this.state.buf.length >= 4)
2627
+ return this.return();
2628
+ }
2629
+ }
2630
+ parseLargeUnicode() {
2631
+ if (!isHexit(this.char)) {
2632
+ throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"));
2633
+ } else {
2634
+ this.consume();
2635
+ if (this.state.buf.length >= 8)
2636
+ return this.return();
2637
+ }
2638
+ }
2639
+ parseNumberSign() {
2640
+ this.consume();
2641
+ return this.next(this.parseMaybeSignedInfOrNan);
2642
+ }
2643
+ parseMaybeSignedInfOrNan() {
2644
+ if (this.char === CHAR_i) {
2645
+ return this.next(this.parseInf);
2646
+ } else if (this.char === CHAR_n) {
2647
+ return this.next(this.parseNan);
2648
+ } else {
2649
+ return this.callNow(this.parseNoUnder, this.parseNumberIntegerStart);
2650
+ }
2651
+ }
2652
+ parseNumberIntegerStart() {
2653
+ if (this.char === CHAR_0) {
2654
+ this.consume();
2655
+ return this.next(this.parseNumberIntegerExponentOrDecimal);
2656
+ } else {
2657
+ return this.goto(this.parseNumberInteger);
2658
+ }
2659
+ }
2660
+ parseNumberIntegerExponentOrDecimal() {
2661
+ if (this.char === CHAR_PERIOD) {
2662
+ this.consume();
2663
+ return this.call(this.parseNoUnder, this.parseNumberFloat);
2664
+ } else if (this.char === CHAR_E || this.char === CHAR_e) {
2665
+ this.consume();
2666
+ return this.next(this.parseNumberExponentSign);
2667
+ } else {
2668
+ return this.returnNow(Integer(this.state.buf));
2669
+ }
2670
+ }
2671
+ parseNumberInteger() {
2672
+ if (isDigit(this.char)) {
2673
+ this.consume();
2674
+ } else if (this.char === CHAR_LOWBAR) {
2675
+ return this.call(this.parseNoUnder);
2676
+ } else if (this.char === CHAR_E || this.char === CHAR_e) {
2677
+ this.consume();
2678
+ return this.next(this.parseNumberExponentSign);
2679
+ } else if (this.char === CHAR_PERIOD) {
2680
+ this.consume();
2681
+ return this.call(this.parseNoUnder, this.parseNumberFloat);
2682
+ } else {
2683
+ const result = Integer(this.state.buf);
2684
+ if (result.isNaN()) {
2685
+ throw this.error(new TomlError("Invalid number"));
2686
+ } else {
2687
+ return this.returnNow(result);
2688
+ }
2689
+ }
2690
+ }
2691
+ parseNoUnder() {
2692
+ if (this.char === CHAR_LOWBAR || this.char === CHAR_PERIOD || this.char === CHAR_E || this.char === CHAR_e) {
2693
+ throw this.error(new TomlError("Unexpected character, expected digit"));
2694
+ } else if (this.atEndOfWord()) {
2695
+ throw this.error(new TomlError("Incomplete number"));
2696
+ }
2697
+ return this.returnNow();
2698
+ }
2699
+ parseNoUnderHexOctBinLiteral() {
2700
+ if (this.char === CHAR_LOWBAR || this.char === CHAR_PERIOD) {
2701
+ throw this.error(new TomlError("Unexpected character, expected digit"));
2702
+ } else if (this.atEndOfWord()) {
2703
+ throw this.error(new TomlError("Incomplete number"));
2704
+ }
2705
+ return this.returnNow();
2706
+ }
2707
+ parseNumberFloat() {
2708
+ if (this.char === CHAR_LOWBAR) {
2709
+ return this.call(this.parseNoUnder, this.parseNumberFloat);
2710
+ } else if (isDigit(this.char)) {
2711
+ this.consume();
2712
+ } else if (this.char === CHAR_E || this.char === CHAR_e) {
2713
+ this.consume();
2714
+ return this.next(this.parseNumberExponentSign);
2715
+ } else {
2716
+ return this.returnNow(Float(this.state.buf));
2717
+ }
2718
+ }
2719
+ parseNumberExponentSign() {
2720
+ if (isDigit(this.char)) {
2721
+ return this.goto(this.parseNumberExponent);
2722
+ } else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) {
2723
+ this.consume();
2724
+ this.call(this.parseNoUnder, this.parseNumberExponent);
2725
+ } else {
2726
+ throw this.error(new TomlError("Unexpected character, expected -, + or digit"));
2727
+ }
2728
+ }
2729
+ parseNumberExponent() {
2730
+ if (isDigit(this.char)) {
2731
+ this.consume();
2732
+ } else if (this.char === CHAR_LOWBAR) {
2733
+ return this.call(this.parseNoUnder);
2734
+ } else {
2735
+ return this.returnNow(Float(this.state.buf));
2736
+ }
2737
+ }
2738
+ parseNumberOrDateTime() {
2739
+ if (this.char === CHAR_0) {
2740
+ this.consume();
2741
+ return this.next(this.parseNumberBaseOrDateTime);
2742
+ } else {
2743
+ return this.goto(this.parseNumberOrDateTimeOnly);
2744
+ }
2745
+ }
2746
+ parseNumberOrDateTimeOnly() {
2747
+ if (this.char === CHAR_LOWBAR) {
2748
+ return this.call(this.parseNoUnder, this.parseNumberInteger);
2749
+ } else if (isDigit(this.char)) {
2750
+ this.consume();
2751
+ if (this.state.buf.length > 4)
2752
+ this.next(this.parseNumberInteger);
2753
+ } else if (this.char === CHAR_E || this.char === CHAR_e) {
2754
+ this.consume();
2755
+ return this.next(this.parseNumberExponentSign);
2756
+ } else if (this.char === CHAR_PERIOD) {
2757
+ this.consume();
2758
+ return this.call(this.parseNoUnder, this.parseNumberFloat);
2759
+ } else if (this.char === CHAR_HYPHEN) {
2760
+ return this.goto(this.parseDateTime);
2761
+ } else if (this.char === CHAR_COLON) {
2762
+ return this.goto(this.parseOnlyTimeHour);
2763
+ } else {
2764
+ return this.returnNow(Integer(this.state.buf));
2765
+ }
2766
+ }
2767
+ parseDateTimeOnly() {
2768
+ if (this.state.buf.length < 4) {
2769
+ if (isDigit(this.char)) {
2770
+ return this.consume();
2771
+ } else if (this.char === CHAR_COLON) {
2772
+ return this.goto(this.parseOnlyTimeHour);
2773
+ } else {
2774
+ throw this.error(new TomlError("Expected digit while parsing year part of a date"));
2775
+ }
2776
+ } else {
2777
+ if (this.char === CHAR_HYPHEN) {
2778
+ return this.goto(this.parseDateTime);
2779
+ } else {
2780
+ throw this.error(new TomlError("Expected hyphen (-) while parsing year part of date"));
2781
+ }
2782
+ }
2783
+ }
2784
+ parseNumberBaseOrDateTime() {
2785
+ if (this.char === CHAR_b) {
2786
+ this.consume();
2787
+ return this.call(this.parseNoUnderHexOctBinLiteral, this.parseIntegerBin);
2788
+ } else if (this.char === CHAR_o) {
2789
+ this.consume();
2790
+ return this.call(this.parseNoUnderHexOctBinLiteral, this.parseIntegerOct);
2791
+ } else if (this.char === CHAR_x) {
2792
+ this.consume();
2793
+ return this.call(this.parseNoUnderHexOctBinLiteral, this.parseIntegerHex);
2794
+ } else if (this.char === CHAR_PERIOD) {
2795
+ return this.goto(this.parseNumberInteger);
2796
+ } else if (isDigit(this.char)) {
2797
+ return this.goto(this.parseDateTimeOnly);
2798
+ } else {
2799
+ return this.returnNow(Integer(this.state.buf));
2800
+ }
2801
+ }
2802
+ parseIntegerHex() {
2803
+ if (isHexit(this.char)) {
2804
+ this.consume();
2805
+ } else if (this.char === CHAR_LOWBAR) {
2806
+ return this.call(this.parseNoUnderHexOctBinLiteral);
2807
+ } else {
2808
+ const result = Integer(this.state.buf);
2809
+ if (result.isNaN()) {
2810
+ throw this.error(new TomlError("Invalid number"));
2811
+ } else {
2812
+ return this.returnNow(result);
2813
+ }
2814
+ }
2815
+ }
2816
+ parseIntegerOct() {
2817
+ if (isOctit(this.char)) {
2818
+ this.consume();
2819
+ } else if (this.char === CHAR_LOWBAR) {
2820
+ return this.call(this.parseNoUnderHexOctBinLiteral);
2821
+ } else {
2822
+ const result = Integer(this.state.buf);
2823
+ if (result.isNaN()) {
2824
+ throw this.error(new TomlError("Invalid number"));
2825
+ } else {
2826
+ return this.returnNow(result);
2827
+ }
2828
+ }
2829
+ }
2830
+ parseIntegerBin() {
2831
+ if (isBit(this.char)) {
2832
+ this.consume();
2833
+ } else if (this.char === CHAR_LOWBAR) {
2834
+ return this.call(this.parseNoUnderHexOctBinLiteral);
2835
+ } else {
2836
+ const result = Integer(this.state.buf);
2837
+ if (result.isNaN()) {
2838
+ throw this.error(new TomlError("Invalid number"));
2839
+ } else {
2840
+ return this.returnNow(result);
2841
+ }
2842
+ }
2843
+ }
2844
+ parseDateTime() {
2845
+ if (this.state.buf.length < 4) {
2846
+ throw this.error(new TomlError("Years less than 1000 must be zero padded to four characters"));
2847
+ }
2848
+ this.state.result = this.state.buf;
2849
+ this.state.buf = "";
2850
+ return this.next(this.parseDateMonth);
2851
+ }
2852
+ parseDateMonth() {
2853
+ if (this.char === CHAR_HYPHEN) {
2854
+ if (this.state.buf.length < 2) {
2855
+ throw this.error(new TomlError("Months less than 10 must be zero padded to two characters"));
2856
+ }
2857
+ this.state.result += "-" + this.state.buf;
2858
+ this.state.buf = "";
2859
+ return this.next(this.parseDateDay);
2860
+ } else if (isDigit(this.char)) {
2861
+ this.consume();
2862
+ } else {
2863
+ throw this.error(new TomlError("Incomplete datetime"));
2864
+ }
2865
+ }
2866
+ parseDateDay() {
2867
+ if (this.char === CHAR_T || this.char === CHAR_SP) {
2868
+ if (this.state.buf.length < 2) {
2869
+ throw this.error(new TomlError("Days less than 10 must be zero padded to two characters"));
2870
+ }
2871
+ this.state.result += "-" + this.state.buf;
2872
+ this.state.buf = "";
2873
+ return this.next(this.parseStartTimeHour);
2874
+ } else if (this.atEndOfWord()) {
2875
+ return this.returnNow(createDate(this.state.result + "-" + this.state.buf));
2876
+ } else if (isDigit(this.char)) {
2877
+ this.consume();
2878
+ } else {
2879
+ throw this.error(new TomlError("Incomplete datetime"));
2880
+ }
2881
+ }
2882
+ parseStartTimeHour() {
2883
+ if (this.atEndOfWord()) {
2884
+ return this.returnNow(createDate(this.state.result));
2885
+ } else {
2886
+ return this.goto(this.parseTimeHour);
2887
+ }
2888
+ }
2889
+ parseTimeHour() {
2890
+ if (this.char === CHAR_COLON) {
2891
+ if (this.state.buf.length < 2) {
2892
+ throw this.error(new TomlError("Hours less than 10 must be zero padded to two characters"));
2893
+ }
2894
+ this.state.result += "T" + this.state.buf;
2895
+ this.state.buf = "";
2896
+ return this.next(this.parseTimeMin);
2897
+ } else if (isDigit(this.char)) {
2898
+ this.consume();
2899
+ } else {
2900
+ throw this.error(new TomlError("Incomplete datetime"));
2901
+ }
2902
+ }
2903
+ parseTimeMin() {
2904
+ if (this.state.buf.length < 2 && isDigit(this.char)) {
2905
+ this.consume();
2906
+ } else if (this.state.buf.length === 2 && this.char === CHAR_COLON) {
2907
+ this.state.result += ":" + this.state.buf;
2908
+ this.state.buf = "";
2909
+ return this.next(this.parseTimeSec);
2910
+ } else {
2911
+ throw this.error(new TomlError("Incomplete datetime"));
2912
+ }
2913
+ }
2914
+ parseTimeSec() {
2915
+ if (isDigit(this.char)) {
2916
+ this.consume();
2917
+ if (this.state.buf.length === 2) {
2918
+ this.state.result += ":" + this.state.buf;
2919
+ this.state.buf = "";
2920
+ return this.next(this.parseTimeZoneOrFraction);
2921
+ }
2922
+ } else {
2923
+ throw this.error(new TomlError("Incomplete datetime"));
2924
+ }
2925
+ }
2926
+ parseOnlyTimeHour() {
2927
+ if (this.char === CHAR_COLON) {
2928
+ if (this.state.buf.length < 2) {
2929
+ throw this.error(new TomlError("Hours less than 10 must be zero padded to two characters"));
2930
+ }
2931
+ this.state.result = this.state.buf;
2932
+ this.state.buf = "";
2933
+ return this.next(this.parseOnlyTimeMin);
2934
+ } else {
2935
+ throw this.error(new TomlError("Incomplete time"));
2936
+ }
2937
+ }
2938
+ parseOnlyTimeMin() {
2939
+ if (this.state.buf.length < 2 && isDigit(this.char)) {
2940
+ this.consume();
2941
+ } else if (this.state.buf.length === 2 && this.char === CHAR_COLON) {
2942
+ this.state.result += ":" + this.state.buf;
2943
+ this.state.buf = "";
2944
+ return this.next(this.parseOnlyTimeSec);
2945
+ } else {
2946
+ throw this.error(new TomlError("Incomplete time"));
2947
+ }
2948
+ }
2949
+ parseOnlyTimeSec() {
2950
+ if (isDigit(this.char)) {
2951
+ this.consume();
2952
+ if (this.state.buf.length === 2) {
2953
+ return this.next(this.parseOnlyTimeFractionMaybe);
2954
+ }
2955
+ } else {
2956
+ throw this.error(new TomlError("Incomplete time"));
2957
+ }
2958
+ }
2959
+ parseOnlyTimeFractionMaybe() {
2960
+ this.state.result += ":" + this.state.buf;
2961
+ if (this.char === CHAR_PERIOD) {
2962
+ this.state.buf = "";
2963
+ this.next(this.parseOnlyTimeFraction);
2964
+ } else {
2965
+ return this.return(createTime(this.state.result));
2966
+ }
2967
+ }
2968
+ parseOnlyTimeFraction() {
2969
+ if (isDigit(this.char)) {
2970
+ this.consume();
2971
+ } else if (this.atEndOfWord()) {
2972
+ if (this.state.buf.length === 0)
2973
+ throw this.error(new TomlError("Expected digit in milliseconds"));
2974
+ return this.returnNow(createTime(this.state.result + "." + this.state.buf));
2975
+ } else {
2976
+ throw this.error(new TomlError("Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z"));
2977
+ }
2978
+ }
2979
+ parseTimeZoneOrFraction() {
2980
+ if (this.char === CHAR_PERIOD) {
2981
+ this.consume();
2982
+ this.next(this.parseDateTimeFraction);
2983
+ } else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) {
2984
+ this.consume();
2985
+ this.next(this.parseTimeZoneHour);
2986
+ } else if (this.char === CHAR_Z) {
2987
+ this.consume();
2988
+ return this.return(createDateTime(this.state.result + this.state.buf));
2989
+ } else if (this.atEndOfWord()) {
2990
+ return this.returnNow(createDateTimeFloat(this.state.result + this.state.buf));
2991
+ } else {
2992
+ throw this.error(new TomlError("Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z"));
2993
+ }
2994
+ }
2995
+ parseDateTimeFraction() {
2996
+ if (isDigit(this.char)) {
2997
+ this.consume();
2998
+ } else if (this.state.buf.length === 1) {
2999
+ throw this.error(new TomlError("Expected digit in milliseconds"));
3000
+ } else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) {
3001
+ this.consume();
3002
+ this.next(this.parseTimeZoneHour);
3003
+ } else if (this.char === CHAR_Z) {
3004
+ this.consume();
3005
+ return this.return(createDateTime(this.state.result + this.state.buf));
3006
+ } else if (this.atEndOfWord()) {
3007
+ return this.returnNow(createDateTimeFloat(this.state.result + this.state.buf));
3008
+ } else {
3009
+ throw this.error(new TomlError("Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z"));
3010
+ }
3011
+ }
3012
+ parseTimeZoneHour() {
3013
+ if (isDigit(this.char)) {
3014
+ this.consume();
3015
+ if (/\d\d$/.test(this.state.buf))
3016
+ return this.next(this.parseTimeZoneSep);
3017
+ } else {
3018
+ throw this.error(new TomlError("Unexpected character in datetime, expected digit"));
3019
+ }
3020
+ }
3021
+ parseTimeZoneSep() {
3022
+ if (this.char === CHAR_COLON) {
3023
+ this.consume();
3024
+ this.next(this.parseTimeZoneMin);
3025
+ } else {
3026
+ throw this.error(new TomlError("Unexpected character in datetime, expected colon"));
3027
+ }
3028
+ }
3029
+ parseTimeZoneMin() {
3030
+ if (isDigit(this.char)) {
3031
+ this.consume();
3032
+ if (/\d\d$/.test(this.state.buf))
3033
+ return this.return(createDateTime(this.state.result + this.state.buf));
3034
+ } else {
3035
+ throw this.error(new TomlError("Unexpected character in datetime, expected digit"));
3036
+ }
3037
+ }
3038
+ parseBoolean() {
3039
+ if (this.char === CHAR_t) {
3040
+ this.consume();
3041
+ return this.next(this.parseTrue_r);
3042
+ } else if (this.char === CHAR_f) {
3043
+ this.consume();
3044
+ return this.next(this.parseFalse_a);
3045
+ }
3046
+ }
3047
+ parseTrue_r() {
3048
+ if (this.char === CHAR_r) {
3049
+ this.consume();
3050
+ return this.next(this.parseTrue_u);
3051
+ } else {
3052
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3053
+ }
3054
+ }
3055
+ parseTrue_u() {
3056
+ if (this.char === CHAR_u) {
3057
+ this.consume();
3058
+ return this.next(this.parseTrue_e);
3059
+ } else {
3060
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3061
+ }
3062
+ }
3063
+ parseTrue_e() {
3064
+ if (this.char === CHAR_e) {
3065
+ return this.return(true);
3066
+ } else {
3067
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3068
+ }
3069
+ }
3070
+ parseFalse_a() {
3071
+ if (this.char === CHAR_a) {
3072
+ this.consume();
3073
+ return this.next(this.parseFalse_l);
3074
+ } else {
3075
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3076
+ }
3077
+ }
3078
+ parseFalse_l() {
3079
+ if (this.char === CHAR_l) {
3080
+ this.consume();
3081
+ return this.next(this.parseFalse_s);
3082
+ } else {
3083
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3084
+ }
3085
+ }
3086
+ parseFalse_s() {
3087
+ if (this.char === CHAR_s) {
3088
+ this.consume();
3089
+ return this.next(this.parseFalse_e);
3090
+ } else {
3091
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3092
+ }
3093
+ }
3094
+ parseFalse_e() {
3095
+ if (this.char === CHAR_e) {
3096
+ return this.return(false);
3097
+ } else {
3098
+ throw this.error(new TomlError("Invalid boolean, expected true or false"));
3099
+ }
3100
+ }
3101
+ parseInlineList() {
3102
+ if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M || this.char === CTRL_J) {
3103
+ return null;
3104
+ } else if (this.char === Parser.END) {
3105
+ throw this.error(new TomlError("Unterminated inline array"));
3106
+ } else if (this.char === CHAR_NUM) {
3107
+ return this.call(this.parseComment);
3108
+ } else if (this.char === CHAR_RSQB) {
3109
+ return this.return(this.state.resultArr || InlineList());
3110
+ } else {
3111
+ return this.callNow(this.parseValue, this.recordInlineListValue);
3112
+ }
3113
+ }
3114
+ recordInlineListValue(value) {
3115
+ if (this.state.resultArr) {
3116
+ const listType = this.state.resultArr[_contentType];
3117
+ const valueType = tomlType(value);
3118
+ if (listType !== valueType) {
3119
+ throw this.error(new TomlError(`Inline lists must be a single type, not a mix of ${listType} and ${valueType}`));
3120
+ }
3121
+ } else {
3122
+ this.state.resultArr = InlineList(tomlType(value));
3123
+ }
3124
+ if (isFloat(value) || isInteger(value)) {
3125
+ this.state.resultArr.push(value.valueOf());
3126
+ } else {
3127
+ this.state.resultArr.push(value);
3128
+ }
3129
+ return this.goto(this.parseInlineListNext);
3130
+ }
3131
+ parseInlineListNext() {
3132
+ if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M || this.char === CTRL_J) {
3133
+ return null;
3134
+ } else if (this.char === CHAR_NUM) {
3135
+ return this.call(this.parseComment);
3136
+ } else if (this.char === CHAR_COMMA) {
3137
+ return this.next(this.parseInlineList);
3138
+ } else if (this.char === CHAR_RSQB) {
3139
+ return this.goto(this.parseInlineList);
3140
+ } else {
3141
+ throw this.error(new TomlError("Invalid character, expected whitespace, comma (,) or close bracket (])"));
3142
+ }
3143
+ }
3144
+ parseInlineTable() {
3145
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
3146
+ return null;
3147
+ } else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) {
3148
+ throw this.error(new TomlError("Unterminated inline array"));
3149
+ } else if (this.char === CHAR_RCUB) {
3150
+ return this.return(this.state.resultTable || InlineTable());
3151
+ } else {
3152
+ if (!this.state.resultTable)
3153
+ this.state.resultTable = InlineTable();
3154
+ return this.callNow(this.parseAssign, this.recordInlineTableValue);
3155
+ }
3156
+ }
3157
+ recordInlineTableValue(kv) {
3158
+ let target = this.state.resultTable;
3159
+ let finalKey = kv.key.pop();
3160
+ for (let kw of kv.key) {
3161
+ if (hasKey(target, kw) && (!isTable(target[kw]) || target[kw][_declared])) {
3162
+ throw this.error(new TomlError("Can't redefine existing key"));
3163
+ }
3164
+ target = target[kw] = target[kw] || Table();
3165
+ }
3166
+ if (hasKey(target, finalKey)) {
3167
+ throw this.error(new TomlError("Can't redefine existing key"));
3168
+ }
3169
+ if (isInteger(kv.value) || isFloat(kv.value)) {
3170
+ target[finalKey] = kv.value.valueOf();
3171
+ } else {
3172
+ target[finalKey] = kv.value;
3173
+ }
3174
+ return this.goto(this.parseInlineTableNext);
3175
+ }
3176
+ parseInlineTableNext() {
3177
+ if (this.char === CHAR_SP || this.char === CTRL_I) {
3178
+ return null;
3179
+ } else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) {
3180
+ throw this.error(new TomlError("Unterminated inline array"));
3181
+ } else if (this.char === CHAR_COMMA) {
3182
+ return this.next(this.parseInlineTable);
3183
+ } else if (this.char === CHAR_RCUB) {
3184
+ return this.goto(this.parseInlineTable);
3185
+ } else {
3186
+ throw this.error(new TomlError("Invalid character, expected whitespace, comma (,) or close bracket (])"));
3187
+ }
3188
+ }
3189
+ }
3190
+ return TOMLParser;
3191
+ }
3192
+ });
3193
+
3194
+ // node_modules/@iarna/toml/parse-pretty-error.js
3195
+ var require_parse_pretty_error = __commonJS((exports, module) => {
3196
+ module.exports = prettyError;
3197
+ function prettyError(err, buf) {
3198
+ if (err.pos == null || err.line == null)
3199
+ return err;
3200
+ let msg = err.message;
3201
+ msg += ` at row ${err.line + 1}, col ${err.col + 1}, pos ${err.pos}:
3202
+ `;
3203
+ if (buf && buf.split) {
3204
+ const lines = buf.split(/\n/);
3205
+ const lineNumWidth = String(Math.min(lines.length, err.line + 3)).length;
3206
+ let linePadding = " ";
3207
+ while (linePadding.length < lineNumWidth)
3208
+ linePadding += " ";
3209
+ for (let ii = Math.max(0, err.line - 1);ii < Math.min(lines.length, err.line + 2); ++ii) {
3210
+ let lineNum = String(ii + 1);
3211
+ if (lineNum.length < lineNumWidth)
3212
+ lineNum = " " + lineNum;
3213
+ if (err.line === ii) {
3214
+ msg += lineNum + "> " + lines[ii] + `
3215
+ `;
3216
+ msg += linePadding + " ";
3217
+ for (let hh = 0;hh < err.col; ++hh) {
3218
+ msg += " ";
3219
+ }
3220
+ msg += `^
3221
+ `;
3222
+ } else {
3223
+ msg += lineNum + ": " + lines[ii] + `
3224
+ `;
3225
+ }
3226
+ }
3227
+ }
3228
+ err.message = msg + `
3229
+ `;
3230
+ return err;
3231
+ }
3232
+ });
3233
+
3234
+ // node_modules/@iarna/toml/parse-string.js
3235
+ var require_parse_string = __commonJS((exports, module) => {
3236
+ module.exports = parseString;
3237
+ var TOMLParser = require_toml_parser();
3238
+ var prettyError = require_parse_pretty_error();
3239
+ function parseString(str) {
3240
+ if (global.Buffer && global.Buffer.isBuffer(str)) {
3241
+ str = str.toString("utf8");
3242
+ }
3243
+ const parser = new TOMLParser;
3244
+ try {
3245
+ parser.parse(str);
3246
+ return parser.finish();
3247
+ } catch (err) {
3248
+ throw prettyError(err, str);
3249
+ }
3250
+ }
3251
+ });
3252
+
3253
+ // node_modules/@iarna/toml/parse-async.js
3254
+ var require_parse_async = __commonJS((exports, module) => {
3255
+ module.exports = parseAsync;
3256
+ var TOMLParser = require_toml_parser();
3257
+ var prettyError = require_parse_pretty_error();
3258
+ function parseAsync(str, opts) {
3259
+ if (!opts)
3260
+ opts = {};
3261
+ const index = 0;
3262
+ const blocksize = opts.blocksize || 40960;
3263
+ const parser = new TOMLParser;
3264
+ return new Promise((resolve2, reject) => {
3265
+ setImmediate(parseAsyncNext, index, blocksize, resolve2, reject);
3266
+ });
3267
+ function parseAsyncNext(index2, blocksize2, resolve2, reject) {
3268
+ if (index2 >= str.length) {
3269
+ try {
3270
+ return resolve2(parser.finish());
3271
+ } catch (err) {
3272
+ return reject(prettyError(err, str));
3273
+ }
3274
+ }
3275
+ try {
3276
+ parser.parse(str.slice(index2, index2 + blocksize2));
3277
+ setImmediate(parseAsyncNext, index2 + blocksize2, blocksize2, resolve2, reject);
3278
+ } catch (err) {
3279
+ reject(prettyError(err, str));
3280
+ }
3281
+ }
3282
+ }
3283
+ });
3284
+
3285
+ // node_modules/@iarna/toml/parse-stream.js
3286
+ var require_parse_stream = __commonJS((exports, module) => {
3287
+ module.exports = parseStream;
3288
+ var stream = __require("stream");
3289
+ var TOMLParser = require_toml_parser();
3290
+ function parseStream(stm) {
3291
+ if (stm) {
3292
+ return parseReadable(stm);
3293
+ } else {
3294
+ return parseTransform(stm);
3295
+ }
3296
+ }
3297
+ function parseReadable(stm) {
3298
+ const parser = new TOMLParser;
3299
+ stm.setEncoding("utf8");
3300
+ return new Promise((resolve2, reject) => {
3301
+ let readable;
3302
+ let ended = false;
3303
+ let errored = false;
3304
+ function finish() {
3305
+ ended = true;
3306
+ if (readable)
3307
+ return;
3308
+ try {
3309
+ resolve2(parser.finish());
3310
+ } catch (err) {
3311
+ reject(err);
3312
+ }
3313
+ }
3314
+ function error(err) {
3315
+ errored = true;
3316
+ reject(err);
3317
+ }
3318
+ stm.once("end", finish);
3319
+ stm.once("error", error);
3320
+ readNext();
3321
+ function readNext() {
3322
+ readable = true;
3323
+ let data;
3324
+ while ((data = stm.read()) !== null) {
3325
+ try {
3326
+ parser.parse(data);
3327
+ } catch (err) {
3328
+ return error(err);
3329
+ }
3330
+ }
3331
+ readable = false;
3332
+ if (ended)
3333
+ return finish();
3334
+ if (errored)
3335
+ return;
3336
+ stm.once("readable", readNext);
3337
+ }
3338
+ });
3339
+ }
3340
+ function parseTransform() {
3341
+ const parser = new TOMLParser;
3342
+ return new stream.Transform({
3343
+ objectMode: true,
3344
+ transform(chunk, encoding, cb) {
3345
+ try {
3346
+ parser.parse(chunk.toString(encoding));
3347
+ } catch (err) {
3348
+ this.emit("error", err);
3349
+ }
3350
+ cb();
3351
+ },
3352
+ flush(cb) {
3353
+ try {
3354
+ this.push(parser.finish());
3355
+ } catch (err) {
3356
+ this.emit("error", err);
3357
+ }
3358
+ cb();
3359
+ }
3360
+ });
3361
+ }
3362
+ });
3363
+
3364
+ // node_modules/@iarna/toml/parse.js
3365
+ var require_parse = __commonJS((exports, module) => {
3366
+ module.exports = require_parse_string();
3367
+ module.exports.async = require_parse_async();
3368
+ module.exports.stream = require_parse_stream();
3369
+ module.exports.prettyError = require_parse_pretty_error();
3370
+ });
3371
+
3372
+ // node_modules/@iarna/toml/stringify.js
3373
+ var require_stringify = __commonJS((exports, module) => {
3374
+ module.exports = stringify;
3375
+ module.exports.value = stringifyInline;
3376
+ function stringify(obj) {
3377
+ if (obj === null)
3378
+ throw typeError("null");
3379
+ if (obj === undefined)
3380
+ throw typeError("undefined");
3381
+ if (typeof obj !== "object")
3382
+ throw typeError(typeof obj);
3383
+ if (typeof obj.toJSON === "function")
3384
+ obj = obj.toJSON();
3385
+ if (obj == null)
3386
+ return null;
3387
+ const type = tomlType(obj);
3388
+ if (type !== "table")
3389
+ throw typeError(type);
3390
+ return stringifyObject("", "", obj);
3391
+ }
3392
+ function typeError(type) {
3393
+ return new Error("Can only stringify objects, not " + type);
3394
+ }
3395
+ function arrayOneTypeError() {
3396
+ return new Error("Array values can't have mixed types");
3397
+ }
3398
+ function getInlineKeys(obj) {
3399
+ return Object.keys(obj).filter((key) => isInline(obj[key]));
3400
+ }
3401
+ function getComplexKeys(obj) {
3402
+ return Object.keys(obj).filter((key) => !isInline(obj[key]));
3403
+ }
3404
+ function toJSON(obj) {
3405
+ let nobj = Array.isArray(obj) ? [] : Object.prototype.hasOwnProperty.call(obj, "__proto__") ? { ["__proto__"]: undefined } : {};
3406
+ for (let prop of Object.keys(obj)) {
3407
+ if (obj[prop] && typeof obj[prop].toJSON === "function" && !("toISOString" in obj[prop])) {
3408
+ nobj[prop] = obj[prop].toJSON();
3409
+ } else {
3410
+ nobj[prop] = obj[prop];
3411
+ }
3412
+ }
3413
+ return nobj;
3414
+ }
3415
+ function stringifyObject(prefix, indent, obj) {
3416
+ obj = toJSON(obj);
3417
+ var inlineKeys;
3418
+ var complexKeys;
3419
+ inlineKeys = getInlineKeys(obj);
3420
+ complexKeys = getComplexKeys(obj);
3421
+ var result = [];
3422
+ var inlineIndent = indent || "";
3423
+ inlineKeys.forEach((key) => {
3424
+ var type = tomlType(obj[key]);
3425
+ if (type !== "undefined" && type !== "null") {
3426
+ result.push(inlineIndent + stringifyKey(key) + " = " + stringifyAnyInline(obj[key], true));
3427
+ }
3428
+ });
3429
+ if (result.length > 0)
3430
+ result.push("");
3431
+ var complexIndent = prefix && inlineKeys.length > 0 ? indent + " " : "";
3432
+ complexKeys.forEach((key) => {
3433
+ result.push(stringifyComplex(prefix, complexIndent, key, obj[key]));
3434
+ });
3435
+ return result.join(`
3436
+ `);
3437
+ }
3438
+ function isInline(value) {
3439
+ switch (tomlType(value)) {
3440
+ case "undefined":
3441
+ case "null":
3442
+ case "integer":
3443
+ case "nan":
3444
+ case "float":
3445
+ case "boolean":
3446
+ case "string":
3447
+ case "datetime":
3448
+ return true;
3449
+ case "array":
3450
+ return value.length === 0 || tomlType(value[0]) !== "table";
3451
+ case "table":
3452
+ return Object.keys(value).length === 0;
3453
+ default:
3454
+ return false;
3455
+ }
3456
+ }
3457
+ function tomlType(value) {
3458
+ if (value === undefined) {
3459
+ return "undefined";
3460
+ } else if (value === null) {
3461
+ return "null";
3462
+ } else if (typeof value === "bigint" || Number.isInteger(value) && !Object.is(value, -0)) {
3463
+ return "integer";
3464
+ } else if (typeof value === "number") {
3465
+ return "float";
3466
+ } else if (typeof value === "boolean") {
3467
+ return "boolean";
3468
+ } else if (typeof value === "string") {
3469
+ return "string";
3470
+ } else if ("toISOString" in value) {
3471
+ return isNaN(value) ? "undefined" : "datetime";
3472
+ } else if (Array.isArray(value)) {
3473
+ return "array";
3474
+ } else {
3475
+ return "table";
3476
+ }
3477
+ }
3478
+ function stringifyKey(key) {
3479
+ var keyStr = String(key);
3480
+ if (/^[-A-Za-z0-9_]+$/.test(keyStr)) {
3481
+ return keyStr;
3482
+ } else {
3483
+ return stringifyBasicString(keyStr);
3484
+ }
3485
+ }
3486
+ function stringifyBasicString(str) {
3487
+ return '"' + escapeString(str).replace(/"/g, "\\\"") + '"';
3488
+ }
3489
+ function stringifyLiteralString(str) {
3490
+ return "'" + str + "'";
3491
+ }
3492
+ function numpad(num, str) {
3493
+ while (str.length < num)
3494
+ str = "0" + str;
3495
+ return str;
3496
+ }
3497
+ function escapeString(str) {
3498
+ return str.replace(/\\/g, "\\\\").replace(/[\b]/g, "\\b").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\f/g, "\\f").replace(/\r/g, "\\r").replace(/([\u0000-\u001f\u007f])/, (c) => "\\u" + numpad(4, c.codePointAt(0).toString(16)));
3499
+ }
3500
+ function stringifyMultilineString(str) {
3501
+ let escaped = str.split(/\n/).map((str2) => {
3502
+ return escapeString(str2).replace(/"(?="")/g, "\\\"");
3503
+ }).join(`
3504
+ `);
3505
+ if (escaped.slice(-1) === '"')
3506
+ escaped += "\\\n";
3507
+ return `"""
3508
+ ` + escaped + '"""';
3509
+ }
3510
+ function stringifyAnyInline(value, multilineOk) {
3511
+ let type = tomlType(value);
3512
+ if (type === "string") {
3513
+ if (multilineOk && /\n/.test(value)) {
3514
+ type = "string-multiline";
3515
+ } else if (!/[\b\t\n\f\r']/.test(value) && /"/.test(value)) {
3516
+ type = "string-literal";
3517
+ }
3518
+ }
3519
+ return stringifyInline(value, type);
3520
+ }
3521
+ function stringifyInline(value, type) {
3522
+ if (!type)
3523
+ type = tomlType(value);
3524
+ switch (type) {
3525
+ case "string-multiline":
3526
+ return stringifyMultilineString(value);
3527
+ case "string":
3528
+ return stringifyBasicString(value);
3529
+ case "string-literal":
3530
+ return stringifyLiteralString(value);
3531
+ case "integer":
3532
+ return stringifyInteger(value);
3533
+ case "float":
3534
+ return stringifyFloat(value);
3535
+ case "boolean":
3536
+ return stringifyBoolean(value);
3537
+ case "datetime":
3538
+ return stringifyDatetime(value);
3539
+ case "array":
3540
+ return stringifyInlineArray(value.filter((_) => tomlType(_) !== "null" && tomlType(_) !== "undefined" && tomlType(_) !== "nan"));
3541
+ case "table":
3542
+ return stringifyInlineTable(value);
3543
+ default:
3544
+ throw typeError(type);
3545
+ }
3546
+ }
3547
+ function stringifyInteger(value) {
3548
+ return String(value).replace(/\B(?=(\d{3})+(?!\d))/g, "_");
3549
+ }
3550
+ function stringifyFloat(value) {
3551
+ if (value === Infinity) {
3552
+ return "inf";
3553
+ } else if (value === -Infinity) {
3554
+ return "-inf";
3555
+ } else if (Object.is(value, NaN)) {
3556
+ return "nan";
3557
+ } else if (Object.is(value, -0)) {
3558
+ return "-0.0";
3559
+ }
3560
+ var chunks = String(value).split(".");
3561
+ var int = chunks[0];
3562
+ var dec = chunks[1] || 0;
3563
+ return stringifyInteger(int) + "." + dec;
3564
+ }
3565
+ function stringifyBoolean(value) {
3566
+ return String(value);
3567
+ }
3568
+ function stringifyDatetime(value) {
3569
+ return value.toISOString();
3570
+ }
3571
+ function isNumber(type) {
3572
+ return type === "float" || type === "integer";
3573
+ }
3574
+ function arrayType(values) {
3575
+ var contentType = tomlType(values[0]);
3576
+ if (values.every((_) => tomlType(_) === contentType))
3577
+ return contentType;
3578
+ if (values.every((_) => isNumber(tomlType(_))))
3579
+ return "float";
3580
+ return "mixed";
3581
+ }
3582
+ function validateArray(values) {
3583
+ const type = arrayType(values);
3584
+ if (type === "mixed") {
3585
+ throw arrayOneTypeError();
3586
+ }
3587
+ return type;
3588
+ }
3589
+ function stringifyInlineArray(values) {
3590
+ values = toJSON(values);
3591
+ const type = validateArray(values);
3592
+ var result = "[";
3593
+ var stringified = values.map((_) => stringifyInline(_, type));
3594
+ if (stringified.join(", ").length > 60 || /\n/.test(stringified)) {
3595
+ result += `
3596
+ ` + stringified.join(`,
3597
+ `) + `
3598
+ `;
3599
+ } else {
3600
+ result += " " + stringified.join(", ") + (stringified.length > 0 ? " " : "");
3601
+ }
3602
+ return result + "]";
3603
+ }
3604
+ function stringifyInlineTable(value) {
3605
+ value = toJSON(value);
3606
+ var result = [];
3607
+ Object.keys(value).forEach((key) => {
3608
+ result.push(stringifyKey(key) + " = " + stringifyAnyInline(value[key], false));
3609
+ });
3610
+ return "{ " + result.join(", ") + (result.length > 0 ? " " : "") + "}";
3611
+ }
3612
+ function stringifyComplex(prefix, indent, key, value) {
3613
+ var valueType = tomlType(value);
3614
+ if (valueType === "array") {
3615
+ return stringifyArrayOfTables(prefix, indent, key, value);
3616
+ } else if (valueType === "table") {
3617
+ return stringifyComplexTable(prefix, indent, key, value);
3618
+ } else {
3619
+ throw typeError(valueType);
3620
+ }
3621
+ }
3622
+ function stringifyArrayOfTables(prefix, indent, key, values) {
3623
+ values = toJSON(values);
3624
+ validateArray(values);
3625
+ var firstValueType = tomlType(values[0]);
3626
+ if (firstValueType !== "table")
3627
+ throw typeError(firstValueType);
3628
+ var fullKey = prefix + stringifyKey(key);
3629
+ var result = "";
3630
+ values.forEach((table) => {
3631
+ if (result.length > 0)
3632
+ result += `
3633
+ `;
3634
+ result += indent + "[[" + fullKey + `]]
3635
+ `;
3636
+ result += stringifyObject(fullKey + ".", indent, table);
3637
+ });
3638
+ return result;
3639
+ }
3640
+ function stringifyComplexTable(prefix, indent, key, value) {
3641
+ var fullKey = prefix + stringifyKey(key);
3642
+ var result = "";
3643
+ if (getInlineKeys(value).length > 0) {
3644
+ result += indent + "[" + fullKey + `]
3645
+ `;
3646
+ }
3647
+ return result + stringifyObject(fullKey + ".", indent, value);
3648
+ }
3649
+ });
3650
+
1660
3651
  // src/cli.tsx
1661
3652
  import { render } from "ink";
1662
3653
 
1663
3654
  // src/app.tsx
1664
- import { useEffect as useEffect3, useState as useState5 } from "react";
1665
- import { Text as Text7, Box as Box6 } from "ink";
3655
+ import { useEffect as useEffect3, useState as useState7 } from "react";
3656
+ import { Text as Text9, Box as Box8 } from "ink";
1666
3657
 
1667
3658
  // node_modules/ink-spinner/build/index.js
1668
3659
  var import_cli_spinners = __toESM(require_cli_spinners(), 1);
@@ -1753,7 +3744,11 @@ class NodeJSDetector extends EcosystemDetector {
1753
3744
  const packageJson = await readJsonFile(packageJsonPath);
1754
3745
  const name = packageJson.name || path2.basename(projectRoot);
1755
3746
  const packageManager = await this.detectPackageManager(projectRoot);
1756
- const scripts = this.extractScripts(packageJson);
3747
+ let scripts = this.extractScripts(packageJson);
3748
+ const toolScripts = await this.detectToolCommands(packageJson, projectRoot);
3749
+ const existingScriptNames = new Set(scripts.map((s) => s.name));
3750
+ const uniqueToolScripts = toolScripts.filter((tool) => !existingScriptNames.has(tool.name));
3751
+ scripts = [...scripts, ...uniqueToolScripts];
1757
3752
  const workspace = await this.detectWorkspace(projectRoot);
1758
3753
  return {
1759
3754
  path: packageJsonPath,
@@ -1763,6 +3758,61 @@ class NodeJSDetector extends EcosystemDetector {
1763
3758
  workspace
1764
3759
  };
1765
3760
  }
3761
+ async detectToolCommands(packageJson, projectRoot) {
3762
+ const tools = [];
3763
+ const allDeps = {
3764
+ ...packageJson.dependencies || {},
3765
+ ...packageJson.devDependencies || {},
3766
+ ...packageJson.peerDependencies || {}
3767
+ };
3768
+ const dependencies = new Set(Object.keys(allDeps).map((dep) => dep.toLowerCase()));
3769
+ if (dependencies.has("typescript")) {
3770
+ const hasTsConfig = await fileExists(path2.join(projectRoot, "tsconfig.json"));
3771
+ if (hasTsConfig) {
3772
+ tools.push({ name: "tsc", command: "tsc --noEmit", description: "\uD83D\uDD0D Type check with TypeScript" }, { name: "tsc-build", command: "tsc", description: "\uD83C\uDFD7️ Build TypeScript project" });
3773
+ }
3774
+ }
3775
+ if (dependencies.has("eslint")) {
3776
+ tools.push({ name: "eslint", command: "eslint .", description: "\uD83D\uDD0D Lint code with ESLint" }, { name: "eslint-fix", command: "eslint . --fix", description: "\uD83D\uDD27 Lint and auto-fix issues" });
3777
+ }
3778
+ if (dependencies.has("prettier")) {
3779
+ tools.push({ name: "prettier-check", command: "prettier --check .", description: "\uD83D\uDC40 Check code formatting" }, { name: "prettier-write", command: "prettier --write .", description: "✨ Format code with Prettier" });
3780
+ }
3781
+ if (dependencies.has("@biomejs/biome") || dependencies.has("biome")) {
3782
+ tools.push({ name: "biome-check", command: "biome check .", description: "\uD83D\uDD0D Check code with Biome" }, { name: "biome-check-fix", command: "biome check --write .", description: "\uD83D\uDD27 Check and auto-fix with Biome" }, { name: "biome-format", command: "biome format --write .", description: "✨ Format code with Biome" });
3783
+ }
3784
+ if (dependencies.has("vitest")) {
3785
+ tools.push({ name: "vitest", command: "vitest", description: "\uD83E\uDDEA Run tests with Vitest" }, { name: "vitest-ui", command: "vitest --ui", description: "\uD83E\uDDEA Run tests with Vitest UI" }, { name: "vitest-run", command: "vitest run", description: "\uD83E\uDDEA Run tests once" }, { name: "vitest-coverage", command: "vitest --coverage", description: "\uD83D\uDCCA Run tests with coverage" });
3786
+ }
3787
+ if (dependencies.has("jest") || dependencies.has("@jest/core")) {
3788
+ tools.push({ name: "jest", command: "jest", description: "\uD83E\uDDEA Run tests with Jest" }, { name: "jest-watch", command: "jest --watch", description: "\uD83E\uDDEA Run tests in watch mode" }, { name: "jest-coverage", command: "jest --coverage", description: "\uD83D\uDCCA Run tests with coverage" });
3789
+ }
3790
+ if (dependencies.has("@playwright/test") || dependencies.has("playwright")) {
3791
+ tools.push({ name: "playwright-test", command: "playwright test", description: "\uD83C\uDFAD Run Playwright tests" }, { name: "playwright-ui", command: "playwright test --ui", description: "\uD83C\uDFAD Run Playwright tests with UI" }, { name: "playwright-debug", command: "playwright test --debug", description: "\uD83D\uDC1B Debug Playwright tests" });
3792
+ }
3793
+ if (dependencies.has("cypress")) {
3794
+ tools.push({ name: "cypress-open", command: "cypress open", description: "\uD83C\uDF32 Open Cypress test runner" }, { name: "cypress-run", command: "cypress run", description: "\uD83C\uDF32 Run Cypress tests headlessly" });
3795
+ }
3796
+ if (dependencies.has("vite")) {
3797
+ tools.push({ name: "vite-dev", command: "vite", description: "⚡ Start Vite dev server" }, { name: "vite-build", command: "vite build", description: "⚡ Build with Vite" }, { name: "vite-preview", command: "vite preview", description: "⚡ Preview Vite build" });
3798
+ }
3799
+ if (dependencies.has("turbo")) {
3800
+ tools.push({ name: "turbo-build", command: "turbo build", description: "\uD83D\uDE80 Build with Turbo" }, { name: "turbo-dev", command: "turbo dev", description: "\uD83D\uDE80 Start dev mode with Turbo" }, { name: "turbo-test", command: "turbo test", description: "\uD83D\uDE80 Run tests with Turbo" });
3801
+ }
3802
+ if (dependencies.has("nx") || dependencies.has("@nx/workspace")) {
3803
+ tools.push({ name: "nx-build", command: "nx build", description: "\uD83D\uDD37 Build with Nx" }, { name: "nx-test", command: "nx test", description: "\uD83D\uDD37 Run tests with Nx" }, { name: "nx-graph", command: "nx graph", description: "\uD83D\uDD37 View project graph" });
3804
+ }
3805
+ if (dependencies.has("typescript") && !packageJson.scripts?.typecheck) {
3806
+ tools.push({ name: "typecheck", command: "tsc --noEmit", description: "\uD83D\uDD0D Type check code" });
3807
+ }
3808
+ if (dependencies.has("stylelint")) {
3809
+ tools.push({ name: "stylelint", command: 'stylelint "**/*.css"', description: "\uD83D\uDC85 Lint CSS files" }, { name: "stylelint-fix", command: 'stylelint "**/*.css" --fix', description: "\uD83D\uDC85 Lint and fix CSS files" });
3810
+ }
3811
+ if (dependencies.has("@storybook/react") || dependencies.has("storybook")) {
3812
+ tools.push({ name: "storybook", command: "storybook dev", description: "\uD83D\uDCD6 Start Storybook dev server" }, { name: "storybook-build", command: "storybook build", description: "\uD83D\uDCD6 Build Storybook" });
3813
+ }
3814
+ return tools;
3815
+ }
1766
3816
  async detectPackageManager(projectRoot) {
1767
3817
  const lockFiles = [
1768
3818
  ["bun.lockb", "bun"],
@@ -1826,7 +3876,11 @@ class NodeJSDetector extends EcosystemDetector {
1826
3876
  }
1827
3877
 
1828
3878
  // src/core/python-detector.ts
1829
- import * as path4 from "path";
3879
+ import * as path5 from "path";
3880
+
3881
+ // node_modules/@iarna/toml/toml.js
3882
+ var $parse = require_parse();
3883
+ var $stringify = require_stringify();
1830
3884
 
1831
3885
  // src/utils/config.ts
1832
3886
  import * as path3 from "path";
@@ -1858,7 +3912,134 @@ async function detectVenv(projectRoot) {
1858
3912
  return venvPath;
1859
3913
  }
1860
3914
  }
1861
- return null;
3915
+ return null;
3916
+ }
3917
+
3918
+ // src/core/python/poe-parser.ts
3919
+ class PoeTaskParser {
3920
+ name = "poethepoet";
3921
+ isConfigured(toml) {
3922
+ return !!toml.tool?.poe?.tasks;
3923
+ }
3924
+ parse(toml) {
3925
+ const scripts = [];
3926
+ if (!this.isConfigured(toml)) {
3927
+ return scripts;
3928
+ }
3929
+ const tasks = toml.tool.poe.tasks;
3930
+ for (const [taskName, taskConfig] of Object.entries(tasks)) {
3931
+ let command = "";
3932
+ let description = "";
3933
+ if (typeof taskConfig === "string") {
3934
+ command = taskConfig;
3935
+ } else if (typeof taskConfig === "object" && taskConfig !== null) {
3936
+ const config = taskConfig;
3937
+ if (config.shell) {
3938
+ command = config.shell;
3939
+ } else if (config.script) {
3940
+ command = config.script;
3941
+ } else if (config.cmd) {
3942
+ command = config.cmd;
3943
+ } else if (Array.isArray(config)) {
3944
+ command = config.join(" && ");
3945
+ }
3946
+ if (config.help) {
3947
+ description = config.help;
3948
+ }
3949
+ }
3950
+ if (command) {
3951
+ scripts.push({
3952
+ name: `poe:${taskName}`,
3953
+ command: `poe ${taskName}`,
3954
+ description: description || `Run poe task: ${taskName}`
3955
+ });
3956
+ }
3957
+ }
3958
+ return scripts;
3959
+ }
3960
+ }
3961
+ var poeTaskParser = new PoeTaskParser;
3962
+
3963
+ // src/core/python/parser-registry.ts
3964
+ class PythonParserRegistry {
3965
+ parsers = [];
3966
+ constructor() {
3967
+ this.register(poeTaskParser);
3968
+ }
3969
+ register(parser) {
3970
+ this.parsers.push(parser);
3971
+ }
3972
+ getAllParsers() {
3973
+ return [...this.parsers];
3974
+ }
3975
+ parseAll(toml) {
3976
+ const allScripts = [];
3977
+ for (const parser of this.parsers) {
3978
+ if (parser.isConfigured(toml)) {
3979
+ const scripts = parser.parse(toml);
3980
+ allScripts.push(...scripts);
3981
+ }
3982
+ }
3983
+ return allScripts;
3984
+ }
3985
+ getParserNames() {
3986
+ return this.parsers.map((p) => p.name);
3987
+ }
3988
+ }
3989
+ var pythonParserRegistry = new PythonParserRegistry;
3990
+
3991
+ // src/core/python/tool-detector.ts
3992
+ import * as path4 from "path";
3993
+ async function detectPythonTools(dependencies, projectRoot) {
3994
+ const tools = [];
3995
+ if (dependencies.has("ruff")) {
3996
+ tools.push({ name: "ruff-check", command: "ruff check", description: "\uD83D\uDD0D Run ruff linter" }, { name: "ruff-check-fix", command: "ruff check --fix", description: "\uD83D\uDD27 Run ruff linter and auto-fix issues" }, { name: "ruff-format", command: "ruff format", description: "✨ Format code with ruff" }, { name: "ruff-format-check", command: "ruff format --check", description: "\uD83D\uDC40 Check if code is formatted" });
3997
+ }
3998
+ if (dependencies.has("pytest")) {
3999
+ tools.push({ name: "test", command: "pytest", description: "\uD83E\uDDEA Run all tests" }, { name: "test-verbose", command: "pytest -v", description: "\uD83E\uDDEA Run tests with verbose output" }, { name: "test-cov", command: "pytest --cov", description: "\uD83D\uDCCA Run tests with coverage report" });
4000
+ }
4001
+ if (dependencies.has("black")) {
4002
+ tools.push({ name: "black", command: "black .", description: "✨ Format code with black" }, { name: "black-check", command: "black --check .", description: "\uD83D\uDC40 Check if code is formatted" });
4003
+ }
4004
+ if (dependencies.has("mypy")) {
4005
+ tools.push({ name: "mypy", command: "mypy .", description: "\uD83D\uDD0D Run mypy type checker" });
4006
+ }
4007
+ if (dependencies.has("pyright")) {
4008
+ tools.push({ name: "pyright", command: "pyright", description: "\uD83D\uDD0D Run pyright type checker" });
4009
+ }
4010
+ if (dependencies.has("isort")) {
4011
+ tools.push({ name: "isort", command: "isort .", description: "\uD83D\uDCD1 Sort imports with isort" }, { name: "isort-check", command: "isort --check-only .", description: "\uD83D\uDC40 Check import sorting" });
4012
+ }
4013
+ if (dependencies.has("flake8")) {
4014
+ tools.push({ name: "flake8", command: "flake8", description: "\uD83D\uDD0D Run flake8 linter" });
4015
+ }
4016
+ if (dependencies.has("pylint")) {
4017
+ tools.push({ name: "pylint", command: "pylint src", description: "\uD83D\uDD0D Run pylint linter" });
4018
+ }
4019
+ if (dependencies.has("coverage")) {
4020
+ tools.push({ name: "coverage-run", command: "coverage run -m pytest", description: "\uD83D\uDCCA Run tests with coverage" }, { name: "coverage-report", command: "coverage report", description: "\uD83D\uDCCA Show coverage report" }, { name: "coverage-html", command: "coverage html", description: "\uD83D\uDCCA Generate HTML coverage report" });
4021
+ }
4022
+ if (dependencies.has("pre-commit")) {
4023
+ tools.push({ name: "pre-commit-install", command: "pre-commit install", description: "\uD83E\uDE9D Install pre-commit hooks" }, { name: "pre-commit-run", command: "pre-commit run --all-files", description: "\uD83E\uDE9D Run pre-commit on all files" });
4024
+ }
4025
+ if (dependencies.has("bandit")) {
4026
+ tools.push({ name: "bandit", command: "bandit -r .", description: "\uD83D\uDD12 Run security checks with bandit" });
4027
+ }
4028
+ if (dependencies.has("sphinx")) {
4029
+ const docsDir = await fileExists(path4.join(projectRoot, "docs")) ? "docs" : ".";
4030
+ tools.push({ name: "docs-build", command: `sphinx-build -b html ${docsDir} ${docsDir}/_build`, description: "\uD83D\uDCDA Build documentation with Sphinx" });
4031
+ }
4032
+ return tools;
4033
+ }
4034
+ function extractDependencyNames(dependencies) {
4035
+ if (Array.isArray(dependencies)) {
4036
+ return dependencies.map((dep) => {
4037
+ const match = dep.match(/^([a-zA-Z0-9_-]+)/);
4038
+ return match ? match[1].toLowerCase() : "";
4039
+ }).filter(Boolean);
4040
+ } else {
4041
+ return Object.keys(dependencies).map((dep) => dep.toLowerCase());
4042
+ }
1862
4043
  }
1863
4044
 
1864
4045
  // src/core/python-detector.ts
@@ -1883,10 +4064,10 @@ class PythonDetector extends EcosystemDetector {
1883
4064
  return null;
1884
4065
  }
1885
4066
  async parse(projectRoot) {
1886
- const pyprojectPath = path4.join(projectRoot, "pyproject.toml");
1887
- const pipfilePath = path4.join(projectRoot, "Pipfile");
1888
- const requirementsPath = path4.join(projectRoot, "requirements.txt");
1889
- let name = path4.basename(projectRoot);
4067
+ const pyprojectPath = path5.join(projectRoot, "pyproject.toml");
4068
+ const pipfilePath = path5.join(projectRoot, "Pipfile");
4069
+ const requirementsPath = path5.join(projectRoot, "requirements.txt");
4070
+ let name = path5.basename(projectRoot);
1890
4071
  let scripts = [];
1891
4072
  let packageManager = "pip";
1892
4073
  if (await fileExists(pyprojectPath)) {
@@ -1920,12 +4101,12 @@ class PythonDetector extends EcosystemDetector {
1920
4101
  async parsePyProject(pyprojectPath, projectRoot) {
1921
4102
  const content = await fs2.readFile(pyprojectPath, "utf-8");
1922
4103
  const toml = this.parseToml(content);
1923
- let name = path4.basename(projectRoot);
4104
+ let name = path5.basename(projectRoot);
1924
4105
  let scripts = [];
1925
4106
  let packageManager = "pip";
1926
- const hasUvLock = await fileExists(path4.join(projectRoot, "uv.lock"));
1927
- const hasPoetryLock = await fileExists(path4.join(projectRoot, "poetry.lock"));
1928
- const hasPdmLock = await fileExists(path4.join(projectRoot, "pdm.lock"));
4107
+ const hasUvLock = await fileExists(path5.join(projectRoot, "uv.lock"));
4108
+ const hasPoetryLock = await fileExists(path5.join(projectRoot, "poetry.lock"));
4109
+ const hasPdmLock = await fileExists(path5.join(projectRoot, "pdm.lock"));
1929
4110
  if (toml.tool?.poetry || hasPoetryLock) {
1930
4111
  packageManager = "poetry";
1931
4112
  name = toml.tool?.poetry?.name || name;
@@ -1968,10 +4149,40 @@ class PythonDetector extends EcosystemDetector {
1968
4149
  name: key,
1969
4150
  command: `python -m ${key}`
1970
4151
  }));
1971
- scripts.push({ name: "install", command: "pip install -e ." });
4152
+ scripts.push({ name: "install", command: "pip install -e .", description: "Install package in editable mode" });
1972
4153
  }
4154
+ const taskScripts = pythonParserRegistry.parseAll(toml);
4155
+ scripts.push(...taskScripts);
4156
+ const allDependencies = this.collectAllDependencies(toml);
4157
+ const toolScripts = await detectPythonTools(allDependencies, projectRoot);
4158
+ const existingScriptNames = new Set(scripts.map((s) => s.name));
4159
+ const uniqueToolScripts = toolScripts.filter((tool) => !existingScriptNames.has(tool.name));
4160
+ scripts.push(...uniqueToolScripts);
1973
4161
  return { name, scripts, packageManager };
1974
4162
  }
4163
+ collectAllDependencies(toml) {
4164
+ const dependencies = new Set;
4165
+ if (toml.project?.dependencies) {
4166
+ extractDependencyNames(toml.project.dependencies).forEach((dep) => dependencies.add(dep));
4167
+ }
4168
+ if (toml["dependency-groups"]) {
4169
+ Object.values(toml["dependency-groups"]).forEach((group) => {
4170
+ if (Array.isArray(group)) {
4171
+ extractDependencyNames(group).forEach((dep) => dependencies.add(dep));
4172
+ }
4173
+ });
4174
+ }
4175
+ if (toml.tool?.poetry?.dependencies) {
4176
+ Object.keys(toml.tool.poetry.dependencies).forEach((dep) => dependencies.add(dep.toLowerCase()));
4177
+ }
4178
+ if (toml.tool?.poetry?.["dev-dependencies"]) {
4179
+ Object.keys(toml.tool.poetry["dev-dependencies"]).forEach((dep) => dependencies.add(dep.toLowerCase()));
4180
+ }
4181
+ if (toml.tool?.pdm?.["dev-dependencies"]) {
4182
+ Object.keys(toml.tool.pdm["dev-dependencies"]).forEach((dep) => dependencies.add(dep.toLowerCase()));
4183
+ }
4184
+ return dependencies;
4185
+ }
1975
4186
  async parsePipfile(pipfilePath) {
1976
4187
  const content = await fs2.readFile(pipfilePath, "utf-8");
1977
4188
  const pipfile = this.parseToml(content);
@@ -1991,41 +4202,7 @@ class PythonDetector extends EcosystemDetector {
1991
4202
  ];
1992
4203
  }
1993
4204
  parseToml(content) {
1994
- const result = {};
1995
- let currentSection = result;
1996
- const sectionPath = [];
1997
- const lines = content.split(`
1998
- `);
1999
- for (const line of lines) {
2000
- const trimmed = line.trim();
2001
- if (!trimmed || trimmed.startsWith("#")) {
2002
- continue;
2003
- }
2004
- if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
2005
- const section = trimmed.slice(1, -1);
2006
- const parts = section.split(".");
2007
- currentSection = result;
2008
- sectionPath.length = 0;
2009
- for (const part of parts) {
2010
- sectionPath.push(part);
2011
- if (!currentSection[part]) {
2012
- currentSection[part] = {};
2013
- }
2014
- currentSection = currentSection[part];
2015
- }
2016
- continue;
2017
- }
2018
- const match = trimmed.match(/^([^=]+)=(.+)$/);
2019
- if (match && match[1] && match[2]) {
2020
- const key = match[1].trim();
2021
- let value = match[2].trim();
2022
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2023
- value = value.slice(1, -1);
2024
- }
2025
- currentSection[key] = value;
2026
- }
2027
- }
2028
- return result;
4205
+ return $parse(content);
2029
4206
  }
2030
4207
  applyConfig(scripts, config) {
2031
4208
  const configCommands = config.commands || {};
@@ -2056,9 +4233,22 @@ class PythonDetector extends EcosystemDetector {
2056
4233
  const manager = packageInfo.packageManager;
2057
4234
  const script = packageInfo.scripts.find((s) => s.name === scriptName);
2058
4235
  if (script) {
2059
- if (script.command.includes(manager) || script.command.includes("uv run")) {
4236
+ if (script.command.includes(manager) || script.command.includes("uv run") || script.command.includes("poetry run") || script.command.includes("pdm run") || script.command.includes("pipenv run")) {
2060
4237
  return script.command;
2061
4238
  }
4239
+ switch (manager) {
4240
+ case "uv":
4241
+ return `uv run ${script.command}`;
4242
+ case "poetry":
4243
+ return `poetry run ${script.command}`;
4244
+ case "pdm":
4245
+ return `pdm run ${script.command}`;
4246
+ case "pipenv":
4247
+ return `pipenv run ${script.command}`;
4248
+ case "pip":
4249
+ default:
4250
+ return script.command;
4251
+ }
2062
4252
  }
2063
4253
  switch (manager) {
2064
4254
  case "uv":
@@ -2107,6 +4297,61 @@ class DetectorRegistry {
2107
4297
  error: "No supported project found in current directory or parent directories"
2108
4298
  };
2109
4299
  }
4300
+ async detectAll(cwd) {
4301
+ const projects = [];
4302
+ const scannedPaths = new Set;
4303
+ const tryDetect = async (path7) => {
4304
+ for (const detector of this.detectors) {
4305
+ try {
4306
+ const projectRoot = await detector.detect(path7);
4307
+ if (projectRoot) {
4308
+ if (scannedPaths.has(projectRoot)) {
4309
+ break;
4310
+ }
4311
+ scannedPaths.add(projectRoot);
4312
+ const packageInfo = await detector.parse(projectRoot);
4313
+ projects.push({
4314
+ found: true,
4315
+ packageInfo,
4316
+ detector
4317
+ });
4318
+ break;
4319
+ }
4320
+ } catch (error) {}
4321
+ }
4322
+ };
4323
+ const fs3 = await import("fs/promises");
4324
+ const path6 = await import("path");
4325
+ await tryDetect(cwd);
4326
+ const parent = path6.dirname(cwd);
4327
+ try {
4328
+ const siblings = await fs3.readdir(parent, { withFileTypes: true });
4329
+ for (const sibling of siblings) {
4330
+ if (sibling.isDirectory()) {
4331
+ const siblingPath = path6.join(parent, sibling.name);
4332
+ await tryDetect(siblingPath);
4333
+ }
4334
+ }
4335
+ } catch (error) {}
4336
+ const scanChildren = async (basePath, depth, maxDepth = 2) => {
4337
+ if (depth > maxDepth)
4338
+ return;
4339
+ try {
4340
+ const entries = await fs3.readdir(basePath, { withFileTypes: true });
4341
+ for (const entry of entries) {
4342
+ if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
4343
+ const childPath = path6.join(basePath, entry.name);
4344
+ await tryDetect(childPath);
4345
+ if (depth < maxDepth) {
4346
+ await scanChildren(childPath, depth + 1, maxDepth);
4347
+ }
4348
+ }
4349
+ }
4350
+ } catch (error) {}
4351
+ };
4352
+ await scanChildren(cwd, 1);
4353
+ return projects;
4354
+ }
2110
4355
  getSupportedEcosystems() {
2111
4356
  return this.detectors.map((d) => d.name);
2112
4357
  }
@@ -2229,20 +4474,20 @@ function Header({ packageInfo, ecosystemName }) {
2229
4474
  }
2230
4475
 
2231
4476
  // src/components/ScriptList.tsx
2232
- import { useState as useState4, useEffect as useEffect2 } from "react";
2233
- import { Text as Text5, Box as Box4, useInput as useInput3, useApp } from "ink";
4477
+ import { useState as useState6, useEffect as useEffect2 } from "react";
4478
+ import { Text as Text7, Box as Box6, useInput as useInput5, useApp } from "ink";
2234
4479
 
2235
4480
  // src/utils/command.ts
2236
4481
  import { spawn } from "child_process";
2237
4482
 
2238
4483
  // src/utils/history.ts
2239
4484
  import { promises as fs3 } from "fs";
2240
- import * as path5 from "path";
4485
+ import * as path6 from "path";
2241
4486
  import * as os from "os";
2242
- var HISTORY_FILE = path5.join(os.homedir(), ".wami", "history.json");
4487
+ var HISTORY_FILE = path6.join(os.homedir(), ".wami", "history.json");
2243
4488
  var MAX_HISTORY_PER_PROJECT = 10;
2244
4489
  async function ensureWamiDir() {
2245
- const wamiDir = path5.dirname(HISTORY_FILE);
4490
+ const wamiDir = path6.dirname(HISTORY_FILE);
2246
4491
  try {
2247
4492
  await fs3.mkdir(wamiDir, { recursive: true });
2248
4493
  } catch (error) {}
@@ -2304,7 +4549,7 @@ async function getHistory(projectPath) {
2304
4549
  return history[projectPath].history.map((entry) => ({
2305
4550
  name: entry.script,
2306
4551
  command: entry.command,
2307
- description: `Run ${entry.count} time${entry.count > 1 ? "s" : ""} before`
4552
+ description: entry.command
2308
4553
  }));
2309
4554
  }
2310
4555
  async function deleteFromHistory(projectPath, command) {
@@ -2593,20 +4838,320 @@ function CommandEditor({
2593
4838
  }, undefined, true, undefined, this);
2594
4839
  }
2595
4840
 
4841
+ // src/components/CustomCommandInput.tsx
4842
+ import { useState as useState4 } from "react";
4843
+ import { Text as Text5, Box as Box4, useInput as useInput3 } from "ink";
4844
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
4845
+ function CustomCommandInput({
4846
+ onSubmit,
4847
+ onCancel
4848
+ }) {
4849
+ const [name, setName] = useState4("");
4850
+ const [command, setCommand] = useState4("");
4851
+ const [focusedField, setFocusedField] = useState4("name");
4852
+ const [nameCursorPos, setNameCursorPos] = useState4(0);
4853
+ const [commandCursorPos, setCommandCursorPos] = useState4(0);
4854
+ const currentText = focusedField === "name" ? name : command;
4855
+ const cursorPos = focusedField === "name" ? nameCursorPos : commandCursorPos;
4856
+ const setCurrentText = focusedField === "name" ? setName : setCommand;
4857
+ const setCursorPos = focusedField === "name" ? setNameCursorPos : setCommandCursorPos;
4858
+ useInput3((char, key) => {
4859
+ if (key.return) {
4860
+ if (focusedField === "name" && name.trim()) {
4861
+ setFocusedField("command");
4862
+ } else if (focusedField === "command" && command.trim()) {
4863
+ onSubmit(name.trim() || "custom", command.trim());
4864
+ }
4865
+ } else if (key.escape) {
4866
+ onCancel();
4867
+ } else if (key.tab) {
4868
+ setFocusedField(focusedField === "name" ? "command" : "name");
4869
+ } else if (key.backspace || key.delete) {
4870
+ if (cursorPos > 0) {
4871
+ setCurrentText((prev) => prev.slice(0, cursorPos - 1) + prev.slice(cursorPos));
4872
+ setCursorPos((prev) => prev - 1);
4873
+ }
4874
+ } else if (key.leftArrow) {
4875
+ setCursorPos((prev) => Math.max(0, prev - 1));
4876
+ } else if (key.rightArrow) {
4877
+ setCursorPos((prev) => Math.min(currentText.length, prev + 1));
4878
+ } else if (!key.ctrl && !key.meta && char) {
4879
+ setCurrentText((prev) => prev.slice(0, cursorPos) + char + prev.slice(cursorPos));
4880
+ setCursorPos((prev) => prev + 1);
4881
+ }
4882
+ });
4883
+ const renderField = (fieldName, value, cursor) => {
4884
+ const isFocused = focusedField === fieldName;
4885
+ return /* @__PURE__ */ jsxDEV4(Box4, {
4886
+ flexDirection: "column",
4887
+ marginBottom: 1,
4888
+ children: [
4889
+ /* @__PURE__ */ jsxDEV4(Text5, {
4890
+ color: isFocused ? "cyan" : "dim",
4891
+ bold: isFocused,
4892
+ children: [
4893
+ fieldName === "name" ? "\uD83D\uDCDD Name" : "⚡ Command",
4894
+ " ",
4895
+ isFocused && "(active)",
4896
+ ":"
4897
+ ]
4898
+ }, undefined, true, undefined, this),
4899
+ /* @__PURE__ */ jsxDEV4(Box4, {
4900
+ paddingLeft: 2,
4901
+ children: isFocused ? /* @__PURE__ */ jsxDEV4(Text5, {
4902
+ color: "green",
4903
+ children: [
4904
+ value.slice(0, cursor),
4905
+ /* @__PURE__ */ jsxDEV4(Text5, {
4906
+ inverse: true,
4907
+ children: value[cursor] || " "
4908
+ }, undefined, false, undefined, this),
4909
+ value.slice(cursor + 1)
4910
+ ]
4911
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV4(Text5, {
4912
+ dimColor: true,
4913
+ children: value || " "
4914
+ }, undefined, false, undefined, this)
4915
+ }, undefined, false, undefined, this)
4916
+ ]
4917
+ }, undefined, true, undefined, this);
4918
+ };
4919
+ return /* @__PURE__ */ jsxDEV4(Box4, {
4920
+ flexDirection: "column",
4921
+ padding: 1,
4922
+ width: "100%",
4923
+ children: [
4924
+ /* @__PURE__ */ jsxDEV4(Box4, {
4925
+ marginBottom: 1,
4926
+ borderStyle: "round",
4927
+ borderColor: "cyan",
4928
+ paddingX: 1,
4929
+ children: /* @__PURE__ */ jsxDEV4(Text5, {
4930
+ bold: true,
4931
+ color: "cyan",
4932
+ children: "✨ Create Custom Command"
4933
+ }, undefined, false, undefined, this)
4934
+ }, undefined, false, undefined, this),
4935
+ renderField("name", name, nameCursorPos),
4936
+ renderField("command", command, commandCursorPos),
4937
+ /* @__PURE__ */ jsxDEV4(Box4, {
4938
+ marginTop: 1,
4939
+ children: /* @__PURE__ */ jsxDEV4(Text5, {
4940
+ dimColor: true,
4941
+ children: [
4942
+ /* @__PURE__ */ jsxDEV4(Text5, {
4943
+ bold: true,
4944
+ children: "Enter"
4945
+ }, undefined, false, undefined, this),
4946
+ " ",
4947
+ focusedField === "name" ? "next" : "run",
4948
+ " ",
4949
+ /* @__PURE__ */ jsxDEV4(Text5, {
4950
+ bold: true,
4951
+ children: "Tab"
4952
+ }, undefined, false, undefined, this),
4953
+ " switch field ",
4954
+ /* @__PURE__ */ jsxDEV4(Text5, {
4955
+ bold: true,
4956
+ children: "Esc"
4957
+ }, undefined, false, undefined, this),
4958
+ " cancel ",
4959
+ /* @__PURE__ */ jsxDEV4(Text5, {
4960
+ bold: true,
4961
+ children: "←/→"
4962
+ }, undefined, false, undefined, this),
4963
+ " move ",
4964
+ /* @__PURE__ */ jsxDEV4(Text5, {
4965
+ bold: true,
4966
+ children: "Backspace"
4967
+ }, undefined, false, undefined, this),
4968
+ " delete"
4969
+ ]
4970
+ }, undefined, true, undefined, this)
4971
+ }, undefined, false, undefined, this)
4972
+ ]
4973
+ }, undefined, true, undefined, this);
4974
+ }
4975
+
4976
+ // src/components/ProjectSwitcher.tsx
4977
+ import { useState as useState5 } from "react";
4978
+ import { Text as Text6, Box as Box5, useInput as useInput4 } from "ink";
4979
+ import * as path7 from "path";
4980
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
4981
+ function ProjectSwitcher({
4982
+ projects,
4983
+ currentProjectPath,
4984
+ onSelect,
4985
+ onCancel
4986
+ }) {
4987
+ const [selectedIndex, setSelectedIndex] = useState5(() => {
4988
+ return projects.findIndex((p) => p.packageInfo?.path.replace(/\/(package\.json|pyproject\.toml|Pipfile|requirements\.txt)$/, "") === currentProjectPath);
4989
+ });
4990
+ useInput4((input, key) => {
4991
+ if (key.upArrow || input === "k") {
4992
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
4993
+ } else if (key.downArrow || input === "j") {
4994
+ setSelectedIndex((prev) => Math.min(projects.length - 1, prev + 1));
4995
+ } else if (key.return) {
4996
+ const selected = projects[selectedIndex];
4997
+ if (selected) {
4998
+ onSelect(selected);
4999
+ }
5000
+ } else if (key.escape || input === "q") {
5001
+ onCancel();
5002
+ }
5003
+ });
5004
+ if (projects.length === 0) {
5005
+ return /* @__PURE__ */ jsxDEV5(Box5, {
5006
+ flexDirection: "column",
5007
+ padding: 1,
5008
+ children: [
5009
+ /* @__PURE__ */ jsxDEV5(Text6, {
5010
+ bold: true,
5011
+ color: "yellow",
5012
+ children: "\uD83D\uDCC1 Project Switcher"
5013
+ }, undefined, false, undefined, this),
5014
+ /* @__PURE__ */ jsxDEV5(Box5, {
5015
+ marginTop: 1,
5016
+ children: /* @__PURE__ */ jsxDEV5(Text6, {
5017
+ dimColor: true,
5018
+ children: "No other projects detected in this mono-repo."
5019
+ }, undefined, false, undefined, this)
5020
+ }, undefined, false, undefined, this),
5021
+ /* @__PURE__ */ jsxDEV5(Box5, {
5022
+ marginTop: 1,
5023
+ children: /* @__PURE__ */ jsxDEV5(Text6, {
5024
+ dimColor: true,
5025
+ children: [
5026
+ "Press ",
5027
+ /* @__PURE__ */ jsxDEV5(Text6, {
5028
+ bold: true,
5029
+ children: "Esc"
5030
+ }, undefined, false, undefined, this),
5031
+ " to close"
5032
+ ]
5033
+ }, undefined, true, undefined, this)
5034
+ }, undefined, false, undefined, this)
5035
+ ]
5036
+ }, undefined, true, undefined, this);
5037
+ }
5038
+ return /* @__PURE__ */ jsxDEV5(Box5, {
5039
+ flexDirection: "column",
5040
+ padding: 1,
5041
+ children: [
5042
+ /* @__PURE__ */ jsxDEV5(Text6, {
5043
+ bold: true,
5044
+ color: "cyan",
5045
+ children: [
5046
+ "\uD83D\uDCC1 Switch Project (",
5047
+ projects.length,
5048
+ " found):"
5049
+ ]
5050
+ }, undefined, true, undefined, this),
5051
+ /* @__PURE__ */ jsxDEV5(Box5, {
5052
+ marginTop: 1,
5053
+ flexDirection: "column",
5054
+ children: projects.map((project, index) => {
5055
+ if (!project.packageInfo)
5056
+ return null;
5057
+ const isSelected = index === selectedIndex;
5058
+ const projectPath = project.packageInfo.path.replace(/\/(package\.json|pyproject\.toml|Pipfile|requirements\.txt)$/, "");
5059
+ const isCurrent = projectPath === currentProjectPath;
5060
+ const relativePath = path7.relative(process.cwd(), projectPath) || ".";
5061
+ return /* @__PURE__ */ jsxDEV5(Box5, {
5062
+ marginLeft: 2,
5063
+ children: isSelected ? /* @__PURE__ */ jsxDEV5(Text6, {
5064
+ color: "cyan",
5065
+ bold: true,
5066
+ children: [
5067
+ "▶ ",
5068
+ relativePath,
5069
+ " ",
5070
+ /* @__PURE__ */ jsxDEV5(Text6, {
5071
+ dimColor: true,
5072
+ children: [
5073
+ "(",
5074
+ project.detector?.name,
5075
+ " - ",
5076
+ project.packageInfo.packageManager,
5077
+ ")"
5078
+ ]
5079
+ }, undefined, true, undefined, this),
5080
+ isCurrent && /* @__PURE__ */ jsxDEV5(Text6, {
5081
+ color: "green",
5082
+ children: " [current]"
5083
+ }, undefined, false, undefined, this)
5084
+ ]
5085
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV5(Text6, {
5086
+ children: [
5087
+ " ",
5088
+ relativePath,
5089
+ " ",
5090
+ /* @__PURE__ */ jsxDEV5(Text6, {
5091
+ dimColor: true,
5092
+ children: [
5093
+ "(",
5094
+ project.detector?.name,
5095
+ " - ",
5096
+ project.packageInfo.packageManager,
5097
+ ")"
5098
+ ]
5099
+ }, undefined, true, undefined, this),
5100
+ isCurrent && /* @__PURE__ */ jsxDEV5(Text6, {
5101
+ color: "green",
5102
+ children: " [current]"
5103
+ }, undefined, false, undefined, this)
5104
+ ]
5105
+ }, undefined, true, undefined, this)
5106
+ }, projectPath, false, undefined, this);
5107
+ })
5108
+ }, undefined, false, undefined, this),
5109
+ /* @__PURE__ */ jsxDEV5(Box5, {
5110
+ marginTop: 1,
5111
+ marginLeft: 2,
5112
+ children: /* @__PURE__ */ jsxDEV5(Text6, {
5113
+ dimColor: true,
5114
+ children: [
5115
+ /* @__PURE__ */ jsxDEV5(Text6, {
5116
+ bold: true,
5117
+ children: "↑/↓/k/j"
5118
+ }, undefined, false, undefined, this),
5119
+ " navigate ",
5120
+ /* @__PURE__ */ jsxDEV5(Text6, {
5121
+ bold: true,
5122
+ children: "Enter"
5123
+ }, undefined, false, undefined, this),
5124
+ " select ",
5125
+ /* @__PURE__ */ jsxDEV5(Text6, {
5126
+ bold: true,
5127
+ children: "Esc/q"
5128
+ }, undefined, false, undefined, this),
5129
+ " cancel"
5130
+ ]
5131
+ }, undefined, true, undefined, this)
5132
+ }, undefined, false, undefined, this)
5133
+ ]
5134
+ }, undefined, true, undefined, this);
5135
+ }
5136
+
2596
5137
  // src/components/ScriptList.tsx
2597
- import { jsxDEV as jsxDEV4, Fragment as Fragment2 } from "react/jsx-dev-runtime";
5138
+ import { jsxDEV as jsxDEV6, Fragment as Fragment2 } from "react/jsx-dev-runtime";
2598
5139
  function ScriptList({
2599
5140
  packageInfo,
2600
5141
  detector,
2601
5142
  history: initialHistory,
2602
- projectPath
5143
+ projectPath,
5144
+ allProjects,
5145
+ onProjectSwitch
2603
5146
  }) {
2604
- const [selectedIndex, setSelectedIndex] = useState4(0);
2605
- const [showArgInput, setShowArgInput] = useState4(false);
2606
- const [showEditor, setShowEditor] = useState4(false);
2607
- const [history, setHistory] = useState4(initialHistory);
2608
- const [isSearching, setIsSearching] = useState4(false);
2609
- const [searchQuery, setSearchQuery] = useState4("");
5147
+ const [selectedIndex, setSelectedIndex] = useState6(0);
5148
+ const [showArgInput, setShowArgInput] = useState6(false);
5149
+ const [showEditor, setShowEditor] = useState6(false);
5150
+ const [showCustomCommand, setShowCustomCommand] = useState6(false);
5151
+ const [showProjectSwitcher, setShowProjectSwitcher] = useState6(false);
5152
+ const [history, setHistory] = useState6(initialHistory);
5153
+ const [isSearching, setIsSearching] = useState6(false);
5154
+ const [searchQuery, setSearchQuery] = useState6("");
2610
5155
  const { exit } = useApp();
2611
5156
  const allScriptsUnfiltered = [...history, ...packageInfo.scripts];
2612
5157
  const historyCount = history.length;
@@ -2625,8 +5170,8 @@ function ScriptList({
2625
5170
  setSelectedIndex(Math.max(0, allScripts.length - 1));
2626
5171
  }
2627
5172
  }, [allScripts.length, selectedIndex]);
2628
- useInput3((input, key) => {
2629
- if (showArgInput || showEditor) {
5173
+ useInput5((input, key) => {
5174
+ if (showArgInput || showEditor || showCustomCommand || showProjectSwitcher) {
2630
5175
  return;
2631
5176
  }
2632
5177
  if (isSearching) {
@@ -2647,16 +5192,16 @@ function ScriptList({
2647
5192
  }
2648
5193
  return;
2649
5194
  }
2650
- if (key.upArrow) {
5195
+ if (key.upArrow || input === "k") {
2651
5196
  setSelectedIndex((prev) => Math.max(0, prev - 1));
2652
- } else if (key.downArrow) {
5197
+ } else if (key.downArrow || input === "j") {
2653
5198
  setSelectedIndex((prev) => Math.min(allScripts.length - 1, prev + 1));
2654
5199
  } else if (key.return) {
2655
5200
  const selectedScript = allScripts[selectedIndex];
2656
5201
  if (selectedScript) {
2657
5202
  const isHistory = selectedIndex < historyCount;
2658
5203
  const command = isHistory ? selectedScript.command : detector.buildCommand(packageInfo, selectedScript.name);
2659
- executeCommand(command, exit);
5204
+ executeCommand(command, exit, projectPath, selectedScript.name, true);
2660
5205
  }
2661
5206
  } else if (input === "a") {
2662
5207
  setShowArgInput(true);
@@ -2665,9 +5210,13 @@ function ScriptList({
2665
5210
  } else if (input === "/" || input === "s") {
2666
5211
  setIsSearching(true);
2667
5212
  setSearchQuery("");
2668
- } else if (input === "c" && searchQuery) {
2669
- setSearchQuery("");
2670
- setSelectedIndex(0);
5213
+ } else if (input === "c") {
5214
+ if (searchQuery) {
5215
+ setSearchQuery("");
5216
+ setSelectedIndex(0);
5217
+ } else {
5218
+ setShowCustomCommand(true);
5219
+ }
2671
5220
  } else if (input === "d" || key.delete) {
2672
5221
  const isHistory = selectedIndex < historyCount;
2673
5222
  if (isHistory) {
@@ -2682,7 +5231,9 @@ function ScriptList({
2682
5231
  }
2683
5232
  }
2684
5233
  }
2685
- } else if (key.escape || input === "q") {
5234
+ } else if (input === "p" && allProjects.length > 1) {
5235
+ setShowProjectSwitcher(true);
5236
+ } else if (input === "q") {
2686
5237
  exit();
2687
5238
  }
2688
5239
  });
@@ -2714,12 +5265,40 @@ function ScriptList({
2714
5265
  const handleEditorCancel = () => {
2715
5266
  setShowEditor(false);
2716
5267
  };
5268
+ const handleProjectSelect = (project) => {
5269
+ setShowProjectSwitcher(false);
5270
+ onProjectSwitch(project);
5271
+ };
5272
+ const handleProjectSwitcherCancel = () => {
5273
+ setShowProjectSwitcher(false);
5274
+ };
5275
+ const handleCustomCommandSubmit = (name, command) => {
5276
+ setShowCustomCommand(false);
5277
+ executeCommand(command, exit, projectPath, name, true);
5278
+ };
5279
+ const handleCustomCommandCancel = () => {
5280
+ setShowCustomCommand(false);
5281
+ };
5282
+ if (showCustomCommand) {
5283
+ return /* @__PURE__ */ jsxDEV6(CustomCommandInput, {
5284
+ onSubmit: handleCustomCommandSubmit,
5285
+ onCancel: handleCustomCommandCancel
5286
+ }, undefined, false, undefined, this);
5287
+ }
5288
+ if (showProjectSwitcher) {
5289
+ return /* @__PURE__ */ jsxDEV6(ProjectSwitcher, {
5290
+ projects: allProjects,
5291
+ currentProjectPath: projectPath,
5292
+ onSelect: handleProjectSelect,
5293
+ onCancel: handleProjectSwitcherCancel
5294
+ }, undefined, false, undefined, this);
5295
+ }
2717
5296
  if (showArgInput) {
2718
5297
  const selectedScript = allScripts[selectedIndex];
2719
5298
  if (selectedScript) {
2720
5299
  const isHistory = selectedIndex < historyCount;
2721
5300
  const baseCommand = isHistory ? selectedScript.command : detector.buildCommand(packageInfo, selectedScript.name);
2722
- return /* @__PURE__ */ jsxDEV4(ArgumentInput, {
5301
+ return /* @__PURE__ */ jsxDEV6(ArgumentInput, {
2723
5302
  scriptName: selectedScript.name,
2724
5303
  baseCommand,
2725
5304
  onSubmit: handleArgumentSubmit,
@@ -2732,7 +5311,7 @@ function ScriptList({
2732
5311
  if (selectedScript) {
2733
5312
  const isHistory = selectedIndex < historyCount;
2734
5313
  const fullCommand = isHistory ? selectedScript.command : detector.buildCommand(packageInfo, selectedScript.name);
2735
- return /* @__PURE__ */ jsxDEV4(CommandEditor, {
5314
+ return /* @__PURE__ */ jsxDEV6(CommandEditor, {
2736
5315
  scriptName: selectedScript.name,
2737
5316
  initialCommand: fullCommand,
2738
5317
  onSubmit: handleEditorSubmit,
@@ -2741,29 +5320,29 @@ function ScriptList({
2741
5320
  }
2742
5321
  }
2743
5322
  if (allScripts.length === 0) {
2744
- return /* @__PURE__ */ jsxDEV4(Box4, {
5323
+ return /* @__PURE__ */ jsxDEV6(Box6, {
2745
5324
  flexDirection: "column",
2746
- children: searchQuery ? /* @__PURE__ */ jsxDEV4(Fragment2, {
5325
+ children: searchQuery ? /* @__PURE__ */ jsxDEV6(Fragment2, {
2747
5326
  children: [
2748
- /* @__PURE__ */ jsxDEV4(Box4, {
5327
+ /* @__PURE__ */ jsxDEV6(Box6, {
2749
5328
  marginBottom: 1,
2750
5329
  children: [
2751
- /* @__PURE__ */ jsxDEV4(Text5, {
5330
+ /* @__PURE__ */ jsxDEV6(Text7, {
2752
5331
  bold: true,
2753
5332
  color: "cyan",
2754
5333
  children: "Search: "
2755
5334
  }, undefined, false, undefined, this),
2756
- /* @__PURE__ */ jsxDEV4(Text5, {
5335
+ /* @__PURE__ */ jsxDEV6(Text7, {
2757
5336
  color: "yellow",
2758
5337
  children: searchQuery
2759
5338
  }, undefined, false, undefined, this)
2760
5339
  ]
2761
5340
  }, undefined, true, undefined, this),
2762
- /* @__PURE__ */ jsxDEV4(Text5, {
5341
+ /* @__PURE__ */ jsxDEV6(Text7, {
2763
5342
  dimColor: true,
2764
5343
  children: [
2765
5344
  "No matches found. Press ",
2766
- /* @__PURE__ */ jsxDEV4(Text5, {
5345
+ /* @__PURE__ */ jsxDEV6(Text7, {
2767
5346
  bold: true,
2768
5347
  children: "Esc"
2769
5348
  }, undefined, false, undefined, this),
@@ -2771,16 +5350,16 @@ function ScriptList({
2771
5350
  ]
2772
5351
  }, undefined, true, undefined, this)
2773
5352
  ]
2774
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV4(Fragment2, {
5353
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV6(Fragment2, {
2775
5354
  children: [
2776
- /* @__PURE__ */ jsxDEV4(Text5, {
5355
+ /* @__PURE__ */ jsxDEV6(Text7, {
2777
5356
  bold: true,
2778
5357
  color: "yellow",
2779
5358
  children: "Available Scripts:"
2780
5359
  }, undefined, false, undefined, this),
2781
- /* @__PURE__ */ jsxDEV4(Box4, {
5360
+ /* @__PURE__ */ jsxDEV6(Box6, {
2782
5361
  marginLeft: 2,
2783
- children: /* @__PURE__ */ jsxDEV4(Text5, {
5362
+ children: /* @__PURE__ */ jsxDEV6(Text7, {
2784
5363
  dimColor: true,
2785
5364
  children: "No scripts found"
2786
5365
  }, undefined, false, undefined, this)
@@ -2804,38 +5383,38 @@ function ScriptList({
2804
5383
  const visibleScripts = allScripts.slice(startIndex, endIndex);
2805
5384
  const hasMoreAbove = startIndex > 0;
2806
5385
  const hasMoreBelow = endIndex < totalItems;
2807
- return /* @__PURE__ */ jsxDEV4(Box4, {
5386
+ return /* @__PURE__ */ jsxDEV6(Box6, {
2808
5387
  flexDirection: "column",
2809
5388
  children: [
2810
- (isSearching || searchQuery) && /* @__PURE__ */ jsxDEV4(Box4, {
5389
+ (isSearching || searchQuery) && /* @__PURE__ */ jsxDEV6(Box6, {
2811
5390
  marginBottom: 1,
2812
5391
  borderStyle: "round",
2813
5392
  borderColor: "cyan",
2814
5393
  paddingX: 1,
2815
5394
  children: [
2816
- /* @__PURE__ */ jsxDEV4(Text5, {
5395
+ /* @__PURE__ */ jsxDEV6(Text7, {
2817
5396
  bold: true,
2818
5397
  color: "cyan",
2819
5398
  children: [
2820
- isSearching && /* @__PURE__ */ jsxDEV4(build_default, {
5399
+ isSearching && /* @__PURE__ */ jsxDEV6(build_default, {
2821
5400
  type: "dots"
2822
5401
  }, undefined, false, undefined, this),
2823
5402
  " Search:"
2824
5403
  ]
2825
5404
  }, undefined, true, undefined, this),
2826
- /* @__PURE__ */ jsxDEV4(Text5, {
5405
+ /* @__PURE__ */ jsxDEV6(Text7, {
2827
5406
  color: "yellow",
2828
5407
  children: searchQuery
2829
5408
  }, undefined, false, undefined, this),
2830
- isSearching && /* @__PURE__ */ jsxDEV4(Text5, {
5409
+ isSearching && /* @__PURE__ */ jsxDEV6(Text7, {
2831
5410
  inverse: true,
2832
5411
  children: " "
2833
5412
  }, undefined, false, undefined, this),
2834
- searchQuery && !isSearching && /* @__PURE__ */ jsxDEV4(Text5, {
5413
+ searchQuery && !isSearching && /* @__PURE__ */ jsxDEV6(Text7, {
2835
5414
  dimColor: true,
2836
5415
  children: [
2837
5416
  " (press ",
2838
- /* @__PURE__ */ jsxDEV4(Text5, {
5417
+ /* @__PURE__ */ jsxDEV6(Text7, {
2839
5418
  bold: true,
2840
5419
  children: "c"
2841
5420
  }, undefined, false, undefined, this),
@@ -2844,14 +5423,14 @@ function ScriptList({
2844
5423
  }, undefined, true, undefined, this)
2845
5424
  ]
2846
5425
  }, undefined, true, undefined, this),
2847
- searchQuery && allScripts.length > 0 && /* @__PURE__ */ jsxDEV4(Box4, {
5426
+ searchQuery && allScripts.length > 0 && /* @__PURE__ */ jsxDEV6(Box6, {
2848
5427
  marginBottom: 1,
2849
5428
  children: [
2850
- /* @__PURE__ */ jsxDEV4(Text5, {
5429
+ /* @__PURE__ */ jsxDEV6(Text7, {
2851
5430
  color: "green",
2852
5431
  children: "✓ "
2853
5432
  }, undefined, false, undefined, this),
2854
- /* @__PURE__ */ jsxDEV4(Text5, {
5433
+ /* @__PURE__ */ jsxDEV6(Text7, {
2855
5434
  dimColor: true,
2856
5435
  children: [
2857
5436
  allScripts.length,
@@ -2862,9 +5441,9 @@ function ScriptList({
2862
5441
  }, undefined, true, undefined, this)
2863
5442
  ]
2864
5443
  }, undefined, true, undefined, this),
2865
- hasMoreAbove && /* @__PURE__ */ jsxDEV4(Box4, {
5444
+ hasMoreAbove && /* @__PURE__ */ jsxDEV6(Box6, {
2866
5445
  marginBottom: 1,
2867
- children: /* @__PURE__ */ jsxDEV4(Text5, {
5446
+ children: /* @__PURE__ */ jsxDEV6(Text7, {
2868
5447
  dimColor: true,
2869
5448
  children: [
2870
5449
  "↑ ",
@@ -2873,9 +5452,9 @@ function ScriptList({
2873
5452
  ]
2874
5453
  }, undefined, true, undefined, this)
2875
5454
  }, undefined, false, undefined, this),
2876
- historyCount > 0 && startIndex < historyCount && /* @__PURE__ */ jsxDEV4(Fragment2, {
5455
+ historyCount > 0 && startIndex < historyCount && /* @__PURE__ */ jsxDEV6(Fragment2, {
2877
5456
  children: [
2878
- /* @__PURE__ */ jsxDEV4(Text5, {
5457
+ /* @__PURE__ */ jsxDEV6(Text7, {
2879
5458
  bold: true,
2880
5459
  color: "green",
2881
5460
  children: "⚡ Recent Commands:"
@@ -2890,27 +5469,27 @@ function ScriptList({
2890
5469
  if (displayText.length > maxLength) {
2891
5470
  displayText = displayText.substring(0, maxLength) + "... (" + displayText.length + " chars)";
2892
5471
  }
2893
- return /* @__PURE__ */ jsxDEV4(Box4, {
5472
+ return /* @__PURE__ */ jsxDEV6(Box6, {
2894
5473
  marginLeft: 2,
2895
5474
  flexDirection: "column",
2896
- children: /* @__PURE__ */ jsxDEV4(Box4, {
5475
+ children: /* @__PURE__ */ jsxDEV6(Box6, {
2897
5476
  children: [
2898
- isSelected ? /* @__PURE__ */ jsxDEV4(Text5, {
5477
+ isSelected ? /* @__PURE__ */ jsxDEV6(Text7, {
2899
5478
  color: "cyan",
2900
5479
  bold: true,
2901
5480
  children: [
2902
- /* @__PURE__ */ jsxDEV4(Text5, {
5481
+ /* @__PURE__ */ jsxDEV6(Text7, {
2903
5482
  children: "▶ "
2904
5483
  }, undefined, false, undefined, this),
2905
5484
  script.name
2906
5485
  ]
2907
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV4(Text5, {
5486
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV6(Text7, {
2908
5487
  children: [
2909
5488
  " ",
2910
5489
  script.name
2911
5490
  ]
2912
5491
  }, undefined, true, undefined, this),
2913
- /* @__PURE__ */ jsxDEV4(Text5, {
5492
+ /* @__PURE__ */ jsxDEV6(Text7, {
2914
5493
  dimColor: true,
2915
5494
  children: [
2916
5495
  " - ",
@@ -2921,14 +5500,14 @@ function ScriptList({
2921
5500
  }, undefined, true, undefined, this)
2922
5501
  }, `history-${actualIndex}`, false, undefined, this);
2923
5502
  }),
2924
- /* @__PURE__ */ jsxDEV4(Box4, {
5503
+ /* @__PURE__ */ jsxDEV6(Box6, {
2925
5504
  marginTop: 1
2926
5505
  }, undefined, false, undefined, this)
2927
5506
  ]
2928
5507
  }, undefined, true, undefined, this),
2929
- endIndex > historyCount && /* @__PURE__ */ jsxDEV4(Fragment2, {
5508
+ endIndex > historyCount && /* @__PURE__ */ jsxDEV6(Fragment2, {
2930
5509
  children: [
2931
- /* @__PURE__ */ jsxDEV4(Text5, {
5510
+ /* @__PURE__ */ jsxDEV6(Text7, {
2932
5511
  bold: true,
2933
5512
  color: "yellow",
2934
5513
  children: "\uD83D\uDCDC Available Scripts:"
@@ -2943,27 +5522,27 @@ function ScriptList({
2943
5522
  if (displayText.length > maxLength) {
2944
5523
  displayText = displayText.substring(0, maxLength) + "...";
2945
5524
  }
2946
- return /* @__PURE__ */ jsxDEV4(Box4, {
5525
+ return /* @__PURE__ */ jsxDEV6(Box6, {
2947
5526
  marginLeft: 2,
2948
5527
  flexDirection: "column",
2949
- children: /* @__PURE__ */ jsxDEV4(Box4, {
5528
+ children: /* @__PURE__ */ jsxDEV6(Box6, {
2950
5529
  children: [
2951
- isSelected ? /* @__PURE__ */ jsxDEV4(Text5, {
5530
+ isSelected ? /* @__PURE__ */ jsxDEV6(Text7, {
2952
5531
  color: "cyan",
2953
5532
  bold: true,
2954
5533
  children: [
2955
- /* @__PURE__ */ jsxDEV4(Text5, {
5534
+ /* @__PURE__ */ jsxDEV6(Text7, {
2956
5535
  children: "▶ "
2957
5536
  }, undefined, false, undefined, this),
2958
5537
  script.name
2959
5538
  ]
2960
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV4(Text5, {
5539
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV6(Text7, {
2961
5540
  children: [
2962
5541
  " ",
2963
5542
  script.name
2964
5543
  ]
2965
5544
  }, undefined, true, undefined, this),
2966
- /* @__PURE__ */ jsxDEV4(Text5, {
5545
+ /* @__PURE__ */ jsxDEV6(Text7, {
2967
5546
  dimColor: true,
2968
5547
  children: [
2969
5548
  " - ",
@@ -2976,9 +5555,9 @@ function ScriptList({
2976
5555
  })
2977
5556
  ]
2978
5557
  }, undefined, true, undefined, this),
2979
- hasMoreBelow && /* @__PURE__ */ jsxDEV4(Box4, {
5558
+ hasMoreBelow && /* @__PURE__ */ jsxDEV6(Box6, {
2980
5559
  marginTop: 1,
2981
- children: /* @__PURE__ */ jsxDEV4(Text5, {
5560
+ children: /* @__PURE__ */ jsxDEV6(Text7, {
2982
5561
  dimColor: true,
2983
5562
  children: [
2984
5563
  "↓ ",
@@ -2987,71 +5566,97 @@ function ScriptList({
2987
5566
  ]
2988
5567
  }, undefined, true, undefined, this)
2989
5568
  }, undefined, false, undefined, this),
2990
- /* @__PURE__ */ jsxDEV4(Box4, {
5569
+ /* @__PURE__ */ jsxDEV6(Box6, {
2991
5570
  marginTop: 1,
2992
5571
  marginLeft: 2,
2993
- children: /* @__PURE__ */ jsxDEV4(Text5, {
5572
+ children: /* @__PURE__ */ jsxDEV6(Text7, {
2994
5573
  dimColor: true,
2995
- children: isSearching ? /* @__PURE__ */ jsxDEV4(Fragment2, {
5574
+ children: isSearching ? /* @__PURE__ */ jsxDEV6(Fragment2, {
2996
5575
  children: [
2997
- /* @__PURE__ */ jsxDEV4(Text5, {
5576
+ /* @__PURE__ */ jsxDEV6(Text7, {
2998
5577
  bold: true,
2999
5578
  children: "Type"
3000
5579
  }, undefined, false, undefined, this),
3001
5580
  " to search ",
3002
- /* @__PURE__ */ jsxDEV4(Text5, {
5581
+ /* @__PURE__ */ jsxDEV6(Text7, {
3003
5582
  bold: true,
3004
- children: "↑/↓"
5583
+ children: "↑/↓/k/j"
3005
5584
  }, undefined, false, undefined, this),
3006
5585
  " navigate ",
3007
- /* @__PURE__ */ jsxDEV4(Text5, {
5586
+ /* @__PURE__ */ jsxDEV6(Text7, {
3008
5587
  bold: true,
3009
5588
  children: "Enter"
3010
5589
  }, undefined, false, undefined, this),
3011
5590
  " done ",
3012
- /* @__PURE__ */ jsxDEV4(Text5, {
5591
+ /* @__PURE__ */ jsxDEV6(Text7, {
3013
5592
  bold: true,
3014
5593
  children: "Esc"
3015
5594
  }, undefined, false, undefined, this),
3016
5595
  " cancel"
3017
5596
  ]
3018
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV4(Fragment2, {
5597
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV6(Fragment2, {
3019
5598
  children: [
3020
- /* @__PURE__ */ jsxDEV4(Text5, {
5599
+ /* @__PURE__ */ jsxDEV6(Text7, {
3021
5600
  bold: true,
3022
- children: "↑/↓"
5601
+ children: "↑/↓/k/j"
3023
5602
  }, undefined, false, undefined, this),
3024
5603
  " navigate ",
3025
- /* @__PURE__ */ jsxDEV4(Text5, {
5604
+ /* @__PURE__ */ jsxDEV6(Text7, {
3026
5605
  bold: true,
3027
5606
  children: "Enter"
3028
5607
  }, undefined, false, undefined, this),
3029
5608
  " run ",
3030
- /* @__PURE__ */ jsxDEV4(Text5, {
5609
+ /* @__PURE__ */ jsxDEV6(Text7, {
3031
5610
  bold: true,
3032
5611
  children: "a"
3033
5612
  }, undefined, false, undefined, this),
3034
5613
  " add args ",
3035
- /* @__PURE__ */ jsxDEV4(Text5, {
5614
+ /* @__PURE__ */ jsxDEV6(Text7, {
3036
5615
  bold: true,
3037
5616
  children: "e"
3038
5617
  }, undefined, false, undefined, this),
3039
5618
  " edit ",
3040
- /* @__PURE__ */ jsxDEV4(Text5, {
5619
+ searchQuery ? /* @__PURE__ */ jsxDEV6(Fragment2, {
5620
+ children: [
5621
+ /* @__PURE__ */ jsxDEV6(Text7, {
5622
+ bold: true,
5623
+ children: "c"
5624
+ }, undefined, false, undefined, this),
5625
+ " clear "
5626
+ ]
5627
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV6(Fragment2, {
5628
+ children: [
5629
+ /* @__PURE__ */ jsxDEV6(Text7, {
5630
+ bold: true,
5631
+ children: "c"
5632
+ }, undefined, false, undefined, this),
5633
+ " custom "
5634
+ ]
5635
+ }, undefined, true, undefined, this),
5636
+ /* @__PURE__ */ jsxDEV6(Text7, {
3041
5637
  bold: true,
3042
5638
  children: "/"
3043
5639
  }, undefined, false, undefined, this),
3044
5640
  " search ",
3045
- historyCount > 0 && /* @__PURE__ */ jsxDEV4(Fragment2, {
5641
+ historyCount > 0 && /* @__PURE__ */ jsxDEV6(Fragment2, {
3046
5642
  children: [
3047
- /* @__PURE__ */ jsxDEV4(Text5, {
5643
+ /* @__PURE__ */ jsxDEV6(Text7, {
3048
5644
  bold: true,
3049
5645
  children: "d"
3050
5646
  }, undefined, false, undefined, this),
3051
5647
  " delete "
3052
5648
  ]
3053
5649
  }, undefined, true, undefined, this),
3054
- /* @__PURE__ */ jsxDEV4(Text5, {
5650
+ allProjects.length > 1 && /* @__PURE__ */ jsxDEV6(Fragment2, {
5651
+ children: [
5652
+ /* @__PURE__ */ jsxDEV6(Text7, {
5653
+ bold: true,
5654
+ children: "p"
5655
+ }, undefined, false, undefined, this),
5656
+ " projects "
5657
+ ]
5658
+ }, undefined, true, undefined, this),
5659
+ /* @__PURE__ */ jsxDEV6(Text7, {
3055
5660
  bold: true,
3056
5661
  children: "q"
3057
5662
  }, undefined, false, undefined, this),
@@ -3065,32 +5670,32 @@ function ScriptList({
3065
5670
  }
3066
5671
 
3067
5672
  // src/components/ErrorMessage.tsx
3068
- import { Text as Text6, Box as Box5 } from "ink";
3069
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
5673
+ import { Text as Text8, Box as Box7 } from "ink";
5674
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
3070
5675
  function ErrorMessage({ error, supportedEcosystems }) {
3071
- return /* @__PURE__ */ jsxDEV5(Box5, {
5676
+ return /* @__PURE__ */ jsxDEV7(Box7, {
3072
5677
  flexDirection: "column",
3073
5678
  padding: 1,
3074
5679
  children: [
3075
- /* @__PURE__ */ jsxDEV5(Box5, {
5680
+ /* @__PURE__ */ jsxDEV7(Box7, {
3076
5681
  borderStyle: "double",
3077
5682
  borderColor: "red",
3078
5683
  padding: 1,
3079
- children: /* @__PURE__ */ jsxDEV5(Text6, {
5684
+ children: /* @__PURE__ */ jsxDEV7(Text8, {
3080
5685
  bold: true,
3081
5686
  color: "red",
3082
5687
  children: "❌ No Project Found"
3083
5688
  }, undefined, false, undefined, this)
3084
5689
  }, undefined, false, undefined, this),
3085
- /* @__PURE__ */ jsxDEV5(Box5, {
5690
+ /* @__PURE__ */ jsxDEV7(Box7, {
3086
5691
  marginTop: 1,
3087
- children: /* @__PURE__ */ jsxDEV5(Text6, {
5692
+ children: /* @__PURE__ */ jsxDEV7(Text8, {
3088
5693
  children: error
3089
5694
  }, undefined, false, undefined, this)
3090
5695
  }, undefined, false, undefined, this),
3091
- /* @__PURE__ */ jsxDEV5(Box5, {
5696
+ /* @__PURE__ */ jsxDEV7(Box7, {
3092
5697
  marginTop: 1,
3093
- children: /* @__PURE__ */ jsxDEV5(Text6, {
5698
+ children: /* @__PURE__ */ jsxDEV7(Text8, {
3094
5699
  dimColor: true,
3095
5700
  children: [
3096
5701
  "Supported ecosystems: ",
@@ -3103,16 +5708,19 @@ function ErrorMessage({ error, supportedEcosystems }) {
3103
5708
  }
3104
5709
 
3105
5710
  // src/app.tsx
3106
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
5711
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
3107
5712
  function App() {
3108
- const [result, setResult] = useState5(null);
3109
- const [history, setHistory] = useState5([]);
3110
- const [loading, setLoading] = useState5(true);
5713
+ const [result, setResult] = useState7(null);
5714
+ const [allProjects, setAllProjects] = useState7([]);
5715
+ const [history, setHistory] = useState7([]);
5716
+ const [loading, setLoading] = useState7(true);
3111
5717
  useEffect3(() => {
3112
5718
  const detectProject = async () => {
3113
5719
  const cwd = process.cwd();
3114
5720
  const detectionResult = await registry.detect(cwd);
3115
5721
  setResult(detectionResult);
5722
+ const allDetected = await registry.detectAll(cwd);
5723
+ setAllProjects(allDetected);
3116
5724
  if (detectionResult.found && detectionResult.packageInfo) {
3117
5725
  const projectPath2 = detectionResult.packageInfo.path.replace(/\/(package\.json|pyproject\.toml|Pipfile|requirements\.txt)$/, "");
3118
5726
  const projectHistory = await getHistory(projectPath2);
@@ -3122,48 +5730,58 @@ function App() {
3122
5730
  };
3123
5731
  detectProject();
3124
5732
  }, []);
5733
+ const handleProjectSwitch = async (newProject) => {
5734
+ if (!newProject.packageInfo)
5735
+ return;
5736
+ setResult(newProject);
5737
+ const projectPath2 = newProject.packageInfo.path.replace(/\/(package\.json|pyproject\.toml|Pipfile|requirements\.txt)$/, "");
5738
+ const projectHistory = await getHistory(projectPath2);
5739
+ setHistory(projectHistory);
5740
+ };
3125
5741
  if (loading) {
3126
- return /* @__PURE__ */ jsxDEV6(Box6, {
5742
+ return /* @__PURE__ */ jsxDEV8(Box8, {
3127
5743
  padding: 1,
3128
5744
  children: [
3129
- /* @__PURE__ */ jsxDEV6(Text7, {
5745
+ /* @__PURE__ */ jsxDEV8(Text9, {
3130
5746
  color: "cyan",
3131
- children: /* @__PURE__ */ jsxDEV6(build_default, {
5747
+ children: /* @__PURE__ */ jsxDEV8(build_default, {
3132
5748
  type: "dots"
3133
5749
  }, undefined, false, undefined, this)
3134
5750
  }, undefined, false, undefined, this),
3135
- /* @__PURE__ */ jsxDEV6(Text7, {
5751
+ /* @__PURE__ */ jsxDEV8(Text9, {
3136
5752
  children: " Detecting project..."
3137
5753
  }, undefined, false, undefined, this)
3138
5754
  ]
3139
5755
  }, undefined, true, undefined, this);
3140
5756
  }
3141
5757
  if (!result?.found) {
3142
- return /* @__PURE__ */ jsxDEV6(ErrorMessage, {
5758
+ return /* @__PURE__ */ jsxDEV8(ErrorMessage, {
3143
5759
  error: result?.error || "Unknown error",
3144
5760
  supportedEcosystems: registry.getSupportedEcosystems()
3145
5761
  }, undefined, false, undefined, this);
3146
5762
  }
3147
5763
  const { packageInfo, detector } = result;
3148
5764
  const projectPath = packageInfo.path.replace(/\/(package\.json|pyproject\.toml|Pipfile|requirements\.txt)$/, "");
3149
- return /* @__PURE__ */ jsxDEV6(Box6, {
5765
+ return /* @__PURE__ */ jsxDEV8(Box8, {
3150
5766
  flexDirection: "column",
3151
5767
  padding: 1,
3152
5768
  children: [
3153
- /* @__PURE__ */ jsxDEV6(Header, {
5769
+ /* @__PURE__ */ jsxDEV8(Header, {
3154
5770
  packageInfo,
3155
5771
  ecosystemName: detector.name
3156
5772
  }, undefined, false, undefined, this),
3157
- /* @__PURE__ */ jsxDEV6(Box6, {
5773
+ /* @__PURE__ */ jsxDEV8(Box8, {
3158
5774
  marginTop: 1,
3159
5775
  borderStyle: "single",
3160
5776
  borderColor: "gray",
3161
5777
  padding: 1,
3162
- children: /* @__PURE__ */ jsxDEV6(ScriptList, {
5778
+ children: /* @__PURE__ */ jsxDEV8(ScriptList, {
3163
5779
  packageInfo,
3164
5780
  detector,
3165
5781
  history,
3166
- projectPath
5782
+ projectPath,
5783
+ allProjects,
5784
+ onProjectSwitch: handleProjectSwitch
3167
5785
  }, undefined, false, undefined, this)
3168
5786
  }, undefined, false, undefined, this)
3169
5787
  ]
@@ -3171,10 +5789,11 @@ function App() {
3171
5789
  }
3172
5790
 
3173
5791
  // src/cli.tsx
3174
- import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
3175
- var { waitUntilExit, clear } = render(/* @__PURE__ */ jsxDEV7(App, {}, undefined, false, undefined, this), {
5792
+ import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
5793
+ var { waitUntilExit, clear } = render(/* @__PURE__ */ jsxDEV9(App, {}, undefined, false, undefined, this), {
3176
5794
  exitOnCtrlC: true,
3177
5795
  patchConsole: false
3178
5796
  });
3179
5797
  await waitUntilExit();
3180
5798
  clear();
5799
+ process.stdout.write("\x1Bc");