solve-engine 1.0.0-beta.0 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BytecodeBuilder-3egMyuDi.d.cts +274 -0
- package/dist/BytecodeBuilder-3egMyuDi.d.ts +274 -0
- package/dist/Configuration-fVpd-HC-.d.cts +228 -0
- package/dist/Configuration-fVpd-HC-.d.ts +228 -0
- package/dist/EngineError-DvPSnhZi.d.cts +304 -0
- package/dist/EngineError-DvPSnhZi.d.ts +304 -0
- package/dist/Lexer-BJdhlnej.d.cts +531 -0
- package/dist/Lexer-D9l4Yrk2.d.ts +531 -0
- package/dist/NormalizerRule-BrVoVjmP.d.cts +163 -0
- package/dist/NormalizerRule-CEjf1FyD.d.ts +163 -0
- package/dist/PackageRegistry-D-Tv_7ca.d.cts +2572 -0
- package/dist/PackageRegistry-DaH4aIKP.d.ts +2572 -0
- package/dist/Parselet-CK8cQu2a.d.cts +299 -0
- package/dist/Parselet-ConOIdRO.d.ts +299 -0
- package/dist/ScopeManager-B5k0nk05.d.ts +559 -0
- package/dist/ScopeManager-CKfQtl7l.d.cts +559 -0
- package/dist/Token-0jpvUdPY.d.cts +245 -0
- package/dist/Token-0jpvUdPY.d.ts +245 -0
- package/dist/VMCheckpoints-BmDwIXgK.d.ts +171 -0
- package/dist/VMCheckpoints-CqFuLwrT.d.cts +171 -0
- package/dist/Value-KtAQNHur.d.cts +295 -0
- package/dist/Value-KtAQNHur.d.ts +295 -0
- package/dist/chunk-2RWAXT6O.js +3 -0
- package/dist/chunk-2RWAXT6O.js.map +1 -0
- package/dist/chunk-34RRD7PC.js +1492 -0
- package/dist/chunk-34RRD7PC.js.map +1 -0
- package/dist/chunk-3PPFLFH4.js +5097 -0
- package/dist/chunk-3PPFLFH4.js.map +1 -0
- package/dist/chunk-3VGDNEE3.js +84 -0
- package/dist/chunk-3VGDNEE3.js.map +1 -0
- package/dist/chunk-3YNVWKR2.cjs +370 -0
- package/dist/chunk-3YNVWKR2.cjs.map +1 -0
- package/dist/chunk-47LRVGOT.cjs +316 -0
- package/dist/chunk-47LRVGOT.cjs.map +1 -0
- package/dist/chunk-4MG4XKO2.js +1644 -0
- package/dist/chunk-4MG4XKO2.js.map +1 -0
- package/dist/chunk-4QADQTWS.js +2392 -0
- package/dist/chunk-4QADQTWS.js.map +1 -0
- package/dist/chunk-53B6KDDJ.cjs +1651 -0
- package/dist/chunk-53B6KDDJ.cjs.map +1 -0
- package/dist/chunk-5X2PTP6F.cjs +104 -0
- package/dist/chunk-5X2PTP6F.cjs.map +1 -0
- package/dist/chunk-5YEMOYSE.js +264 -0
- package/dist/chunk-5YEMOYSE.js.map +1 -0
- package/dist/chunk-64W6GLLZ.js +481 -0
- package/dist/chunk-64W6GLLZ.js.map +1 -0
- package/dist/chunk-6BKTCEUP.cjs +233 -0
- package/dist/chunk-6BKTCEUP.cjs.map +1 -0
- package/dist/chunk-6NTVRDQV.cjs +1642 -0
- package/dist/chunk-6NTVRDQV.cjs.map +1 -0
- package/dist/chunk-6RDSQURE.js +290 -0
- package/dist/chunk-6RDSQURE.js.map +1 -0
- package/dist/chunk-75JP4BZX.js +93 -0
- package/dist/chunk-75JP4BZX.js.map +1 -0
- package/dist/chunk-B7LXJ6LC.cjs +36 -0
- package/dist/chunk-B7LXJ6LC.cjs.map +1 -0
- package/dist/chunk-BVAR5J2F.js +257 -0
- package/dist/chunk-BVAR5J2F.js.map +1 -0
- package/dist/chunk-C4XZV6E7.cjs +269 -0
- package/dist/chunk-C4XZV6E7.cjs.map +1 -0
- package/dist/chunk-CCJPSHGI.cjs +40 -0
- package/dist/chunk-CCJPSHGI.cjs.map +1 -0
- package/dist/chunk-CLL7RUQV.cjs +316 -0
- package/dist/chunk-CLL7RUQV.cjs.map +1 -0
- package/dist/chunk-DM3LMRBC.js +329 -0
- package/dist/chunk-DM3LMRBC.js.map +1 -0
- package/dist/chunk-DUEZFTK2.js +38 -0
- package/dist/chunk-DUEZFTK2.js.map +1 -0
- package/dist/chunk-EBSPLUW4.cjs +489 -0
- package/dist/chunk-EBSPLUW4.cjs.map +1 -0
- package/dist/chunk-EHAHVROS.cjs +261 -0
- package/dist/chunk-EHAHVROS.cjs.map +1 -0
- package/dist/chunk-EIGTWK5N.js +167 -0
- package/dist/chunk-EIGTWK5N.js.map +1 -0
- package/dist/chunk-EPOXXJBK.js +96 -0
- package/dist/chunk-EPOXXJBK.js.map +1 -0
- package/dist/chunk-FEAIOR7N.cjs +91 -0
- package/dist/chunk-FEAIOR7N.cjs.map +1 -0
- package/dist/chunk-G535KJEG.js +312 -0
- package/dist/chunk-G535KJEG.js.map +1 -0
- package/dist/chunk-GCM5JHMX.js +88 -0
- package/dist/chunk-GCM5JHMX.js.map +1 -0
- package/dist/chunk-GOLDJNMZ.js +368 -0
- package/dist/chunk-GOLDJNMZ.js.map +1 -0
- package/dist/chunk-GW32KPCU.cjs +360 -0
- package/dist/chunk-GW32KPCU.cjs.map +1 -0
- package/dist/chunk-HTXVVJRA.cjs +1549 -0
- package/dist/chunk-HTXVVJRA.cjs.map +1 -0
- package/dist/chunk-HWSZJQCI.js +311 -0
- package/dist/chunk-HWSZJQCI.js.map +1 -0
- package/dist/chunk-IF532O7C.js +101 -0
- package/dist/chunk-IF532O7C.js.map +1 -0
- package/dist/chunk-J73SJHR3.cjs +2415 -0
- package/dist/chunk-J73SJHR3.cjs.map +1 -0
- package/dist/chunk-JBSYC7BB.cjs +7473 -0
- package/dist/chunk-JBSYC7BB.cjs.map +1 -0
- package/dist/chunk-KVILKGMS.js +228 -0
- package/dist/chunk-KVILKGMS.js.map +1 -0
- package/dist/chunk-LIPPNDBE.js +258 -0
- package/dist/chunk-LIPPNDBE.js.map +1 -0
- package/dist/chunk-LR7YASZF.cjs +172 -0
- package/dist/chunk-LR7YASZF.cjs.map +1 -0
- package/dist/chunk-M4N5GA5Z.cjs +309 -0
- package/dist/chunk-M4N5GA5Z.cjs.map +1 -0
- package/dist/chunk-M5LX5AOO.js +7459 -0
- package/dist/chunk-M5LX5AOO.js.map +1 -0
- package/dist/chunk-MZOVP3WI.cjs +96 -0
- package/dist/chunk-MZOVP3WI.cjs.map +1 -0
- package/dist/chunk-N5YFR4UP.cjs +10 -0
- package/dist/chunk-N5YFR4UP.cjs.map +1 -0
- package/dist/chunk-NGBBNL4K.cjs +4 -0
- package/dist/chunk-NGBBNL4K.cjs.map +1 -0
- package/dist/chunk-NH2O2AUR.js +146 -0
- package/dist/chunk-NH2O2AUR.js.map +1 -0
- package/dist/chunk-NLNDMWZC.js +31 -0
- package/dist/chunk-NLNDMWZC.js.map +1 -0
- package/dist/chunk-NMCRQP3Z.cjs +778 -0
- package/dist/chunk-NMCRQP3Z.cjs.map +1 -0
- package/dist/chunk-NMD5VRN4.cjs +1327 -0
- package/dist/chunk-NMD5VRN4.cjs.map +1 -0
- package/dist/chunk-OC6LTXYS.cjs +286 -0
- package/dist/chunk-OC6LTXYS.cjs.map +1 -0
- package/dist/chunk-OT6OJY7C.cjs +114 -0
- package/dist/chunk-OT6OJY7C.cjs.map +1 -0
- package/dist/chunk-PFSDGGYL.js +8 -0
- package/dist/chunk-PFSDGGYL.js.map +1 -0
- package/dist/chunk-QNJ4ACRT.cjs +155 -0
- package/dist/chunk-QNJ4ACRT.cjs.map +1 -0
- package/dist/chunk-QWY3VEZN.js +1637 -0
- package/dist/chunk-QWY3VEZN.js.map +1 -0
- package/dist/chunk-RFYD5TJE.js +111 -0
- package/dist/chunk-RFYD5TJE.js.map +1 -0
- package/dist/chunk-RIN643A3.js +354 -0
- package/dist/chunk-RIN643A3.js.map +1 -0
- package/dist/chunk-RZCWSXTA.cjs +5122 -0
- package/dist/chunk-RZCWSXTA.cjs.map +1 -0
- package/dist/chunk-SDGRK7EP.js +774 -0
- package/dist/chunk-SDGRK7EP.js.map +1 -0
- package/dist/chunk-VEKIWQ3F.cjs +39 -0
- package/dist/chunk-VEKIWQ3F.cjs.map +1 -0
- package/dist/chunk-WQTTOGXC.cjs +99 -0
- package/dist/chunk-WQTTOGXC.cjs.map +1 -0
- package/dist/chunk-X6K3HUOY.cjs +86 -0
- package/dist/chunk-X6K3HUOY.cjs.map +1 -0
- package/dist/chunk-XJCMXB2E.cjs +333 -0
- package/dist/chunk-XJCMXB2E.cjs.map +1 -0
- package/dist/chunk-XVWCOTR6.js +1324 -0
- package/dist/chunk-XVWCOTR6.js.map +1 -0
- package/dist/chunk-YLJ4XMA6.js +33 -0
- package/dist/chunk-YLJ4XMA6.js.map +1 -0
- package/dist/chunk-Z2XP767T.cjs +35 -0
- package/dist/chunk-Z2XP767T.cjs.map +1 -0
- package/dist/chunk-Z4X2RWOF.js +37 -0
- package/dist/chunk-Z4X2RWOF.js.map +1 -0
- package/dist/constants.cjs +22 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +12 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/engine.cjs +79 -0
- package/dist/engine.cjs.map +1 -0
- package/dist/engine.d.cts +587 -0
- package/dist/engine.d.ts +587 -0
- package/dist/engine.js +34 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.cjs +81 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +95 -0
- package/dist/errors.d.ts +95 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/format.cjs +171 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.cts +51 -0
- package/dist/format.d.ts +51 -0
- package/dist/format.js +168 -0
- package/dist/format.js.map +1 -0
- package/dist/index.cjs +97 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +152 -0
- package/dist/index.d.ts +152 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/language.cjs +308 -0
- package/dist/language.cjs.map +1 -0
- package/dist/language.d.cts +110 -0
- package/dist/language.d.ts +110 -0
- package/dist/language.js +287 -0
- package/dist/language.js.map +1 -0
- package/dist/lexer.cjs +64 -0
- package/dist/lexer.cjs.map +1 -0
- package/dist/lexer.d.cts +56 -0
- package/dist/lexer.d.ts +56 -0
- package/dist/lexer.js +11 -0
- package/dist/lexer.js.map +1 -0
- package/dist/normalizer.cjs +40 -0
- package/dist/normalizer.cjs.map +1 -0
- package/dist/normalizer.d.cts +364 -0
- package/dist/normalizer.d.ts +364 -0
- package/dist/normalizer.js +11 -0
- package/dist/normalizer.js.map +1 -0
- package/dist/packages.cjs +121 -0
- package/dist/packages.cjs.map +1 -0
- package/dist/packages.d.cts +691 -0
- package/dist/packages.d.ts +691 -0
- package/dist/packages.js +24 -0
- package/dist/packages.js.map +1 -0
- package/dist/parser.cjs +55 -0
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +46 -0
- package/dist/parser.d.ts +46 -0
- package/dist/parser.js +10 -0
- package/dist/parser.js.map +1 -0
- package/dist/pipeline-CrsRPmsv.d.ts +285 -0
- package/dist/pipeline-DPUQt7yL.d.cts +285 -0
- package/dist/resolvers.cjs +13 -0
- package/dist/resolvers.cjs.map +1 -0
- package/dist/resolvers.d.cts +111 -0
- package/dist/resolvers.d.ts +111 -0
- package/dist/resolvers.js +4 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/services.cjs +21 -0
- package/dist/services.cjs.map +1 -0
- package/dist/services.d.cts +30 -0
- package/dist/services.d.ts +30 -0
- package/dist/services.js +4 -0
- package/dist/services.js.map +1 -0
- package/dist/uom.cjs +56 -0
- package/dist/uom.cjs.map +1 -0
- package/dist/uom.d.cts +224 -0
- package/dist/uom.d.ts +224 -0
- package/dist/uom.js +11 -0
- package/dist/uom.js.map +1 -0
- package/dist/utilities.cjs +32 -0
- package/dist/utilities.cjs.map +1 -0
- package/dist/utilities.d.cts +113 -0
- package/dist/utilities.d.ts +113 -0
- package/dist/utilities.js +7 -0
- package/dist/utilities.js.map +1 -0
- package/dist/variables.cjs +17 -0
- package/dist/variables.cjs.map +1 -0
- package/dist/variables.d.cts +87 -0
- package/dist/variables.d.ts +87 -0
- package/dist/variables.js +4 -0
- package/dist/variables.js.map +1 -0
- package/dist/vm.cjs +284 -0
- package/dist/vm.cjs.map +1 -0
- package/dist/vm.d.cts +68 -0
- package/dist/vm.d.ts +68 -0
- package/dist/vm.js +194 -0
- package/dist/vm.js.map +1 -0
- package/package.json +4 -4
package/dist/format.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { autoFormatIntegerOrFloat } from './chunk-DUEZFTK2.js';
|
|
2
|
+
import { CURRENCY_DISPLAY } from './chunk-RFYD5TJE.js';
|
|
3
|
+
import { formatSymbolic, columnMajorToRowMajor } from './chunk-34RRD7PC.js';
|
|
4
|
+
import './chunk-BVAR5J2F.js';
|
|
5
|
+
import { getLocale } from './chunk-GOLDJNMZ.js';
|
|
6
|
+
import './chunk-6RDSQURE.js';
|
|
7
|
+
import './chunk-YLJ4XMA6.js';
|
|
8
|
+
|
|
9
|
+
// src/format/FormattingSettings.ts
|
|
10
|
+
var DEFAULT_FORMATTING_SETTINGS = {
|
|
11
|
+
floatResult: {
|
|
12
|
+
decimalPlaces: 2,
|
|
13
|
+
enableSeperator: true
|
|
14
|
+
},
|
|
15
|
+
numberResult: {
|
|
16
|
+
decimalSeparatorLocale: "en-US"
|
|
17
|
+
},
|
|
18
|
+
hexResult: {
|
|
19
|
+
enablePadding: false,
|
|
20
|
+
paddingZeros: 0
|
|
21
|
+
},
|
|
22
|
+
unitOfMeasurementResult: {
|
|
23
|
+
decimalPlaces: 2,
|
|
24
|
+
unitNames: true
|
|
25
|
+
},
|
|
26
|
+
percentageResult: {
|
|
27
|
+
decimalPlaces: 2
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// src/format/FormatEngine.ts
|
|
32
|
+
function formatNumber(value, locale, settings) {
|
|
33
|
+
const dp = settings.floatResult.decimalPlaces;
|
|
34
|
+
const sep = settings.floatResult.enableSeperator;
|
|
35
|
+
const loc = settings.numberResult.decimalSeparatorLocale;
|
|
36
|
+
const formatted = autoFormatIntegerOrFloat(value, dp, sep, loc);
|
|
37
|
+
return `${locale.display.resultPrefix}${formatted}`;
|
|
38
|
+
}
|
|
39
|
+
function formatHex(value, settings, base) {
|
|
40
|
+
const truncated = Math.trunc(value);
|
|
41
|
+
const sign = truncated < 0 ? "-" : "";
|
|
42
|
+
const magnitude = Math.abs(truncated);
|
|
43
|
+
if (base === "bin") return `= ${sign}0b${magnitude.toString(2)}`;
|
|
44
|
+
if (base === "oct") return `= ${sign}0o${magnitude.toString(8)}`;
|
|
45
|
+
const padding = settings.hexResult.enablePadding ? settings.hexResult.paddingZeros : 0;
|
|
46
|
+
const hex = magnitude.toString(16).toUpperCase().padStart(padding, "0");
|
|
47
|
+
return `= ${sign}0x${hex}`;
|
|
48
|
+
}
|
|
49
|
+
function formatBigInt(value) {
|
|
50
|
+
return `= ${value}`;
|
|
51
|
+
}
|
|
52
|
+
function formatString(value) {
|
|
53
|
+
return `= ${value}`;
|
|
54
|
+
}
|
|
55
|
+
function formatBoolean(value) {
|
|
56
|
+
return `= ${value}`;
|
|
57
|
+
}
|
|
58
|
+
function formatDatetime(value, locale) {
|
|
59
|
+
const d = new Date(value);
|
|
60
|
+
const dateStr = d.toLocaleDateString(locale.code, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
|
61
|
+
const isMidnight = d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;
|
|
62
|
+
if (isMidnight) return `= ${dateStr}`;
|
|
63
|
+
return `= ${dateStr}, ${d.toLocaleTimeString(locale.code)}`;
|
|
64
|
+
}
|
|
65
|
+
function formatMsDuration(ms) {
|
|
66
|
+
const sign = ms < 0 ? "-" : "";
|
|
67
|
+
const totalSeconds = Math.round(Math.abs(ms) / 1e3);
|
|
68
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
69
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
70
|
+
const seconds = totalSeconds % 60;
|
|
71
|
+
const mm = String(minutes).padStart(2, "0");
|
|
72
|
+
if (seconds === 0) return `${sign}${hours}:${mm}`;
|
|
73
|
+
const ss = String(seconds).padStart(2, "0");
|
|
74
|
+
return `${sign}${hours}:${mm}:${ss}`;
|
|
75
|
+
}
|
|
76
|
+
function formatUom(value, unit, locale, settings) {
|
|
77
|
+
if (unit === "ms") return `= ${formatMsDuration(value)}`;
|
|
78
|
+
const dp = settings.unitOfMeasurementResult.decimalPlaces;
|
|
79
|
+
const useUnitNames = settings.unitOfMeasurementResult.unitNames;
|
|
80
|
+
const timeSpanUnits = ["days", "weeks", "hours", "minutes", "seconds", "day", "week", "hour", "minute", "second"];
|
|
81
|
+
const isTimeSpan = unit && timeSpanUnits.includes(unit);
|
|
82
|
+
let formatted;
|
|
83
|
+
if (isTimeSpan && value === Math.floor(value)) {
|
|
84
|
+
formatted = value.toString();
|
|
85
|
+
} else {
|
|
86
|
+
formatted = value.toFixed(dp);
|
|
87
|
+
}
|
|
88
|
+
const currencyDisplay = unit ? CURRENCY_DISPLAY[unit.toUpperCase()] : void 0;
|
|
89
|
+
if (currencyDisplay) {
|
|
90
|
+
const sep = currencyDisplay.spaced ? " " : "";
|
|
91
|
+
const withSymbol = currencyDisplay.position === "prefix" ? `${currencyDisplay.symbol}${sep}${formatted}` : `${formatted}${sep}${currencyDisplay.symbol}`;
|
|
92
|
+
return `= ${withSymbol}`;
|
|
93
|
+
}
|
|
94
|
+
const unitLabel = useUnitNames ? unit || "" : unit || "";
|
|
95
|
+
return `= ${formatted} ${unitLabel}`.trim();
|
|
96
|
+
}
|
|
97
|
+
function formatMatrixEntry(entry, settings) {
|
|
98
|
+
if (typeof entry === "boolean") return entry ? "true" : "false";
|
|
99
|
+
if (typeof entry === "object" && entry !== null) return formatSymbolic(entry);
|
|
100
|
+
const dp = settings.floatResult.decimalPlaces;
|
|
101
|
+
const sep = settings.floatResult.enableSeperator;
|
|
102
|
+
const loc = settings.numberResult.decimalSeparatorLocale;
|
|
103
|
+
return autoFormatIntegerOrFloat(entry, dp, sep, loc);
|
|
104
|
+
}
|
|
105
|
+
function formatMatrix(m, locale, settings) {
|
|
106
|
+
const rowMajor = columnMajorToRowMajor(m);
|
|
107
|
+
const rows = [];
|
|
108
|
+
for (let r = 0; r < m.rows; r++) {
|
|
109
|
+
const cells = [];
|
|
110
|
+
for (let c = 0; c < m.cols; c++) {
|
|
111
|
+
cells.push(formatMatrixEntry(rowMajor[r * m.cols + c], settings));
|
|
112
|
+
}
|
|
113
|
+
rows.push(cells.join(", "));
|
|
114
|
+
}
|
|
115
|
+
return `${locale.display.resultPrefix}[${rows.join("; ")}]`;
|
|
116
|
+
}
|
|
117
|
+
function formatRange(min, max, locale) {
|
|
118
|
+
return `${locale.display.resultPrefix}${min}:${max}`;
|
|
119
|
+
}
|
|
120
|
+
function formatPercentage(value, locale, settings) {
|
|
121
|
+
const dp = settings.percentageResult.decimalPlaces;
|
|
122
|
+
const formatted = (value * 100).toFixed(dp);
|
|
123
|
+
return `= ${formatted}${locale.display.percentageSuffix}`;
|
|
124
|
+
}
|
|
125
|
+
function formatUnit(value, unit) {
|
|
126
|
+
return `= ${value} ${unit || ""}`.trim();
|
|
127
|
+
}
|
|
128
|
+
function formatValue(value, settings) {
|
|
129
|
+
const us = settings || DEFAULT_FORMATTING_SETTINGS;
|
|
130
|
+
const localeCode = us.numberResult.decimalSeparatorLocale || "en";
|
|
131
|
+
const locale = getLocale(localeCode);
|
|
132
|
+
switch (value.type) {
|
|
133
|
+
case 0 /* Number */:
|
|
134
|
+
return formatNumber(value.value, locale, us);
|
|
135
|
+
case 1 /* Hex */:
|
|
136
|
+
return formatHex(value.value, us, value.unit);
|
|
137
|
+
case 2 /* BigInt */:
|
|
138
|
+
return formatBigInt(value.value);
|
|
139
|
+
case 3 /* String */:
|
|
140
|
+
return formatString(value.value);
|
|
141
|
+
case 10 /* Boolean */:
|
|
142
|
+
return formatBoolean(value.value);
|
|
143
|
+
case 4 /* Datetime */:
|
|
144
|
+
return formatDatetime(value.value, locale);
|
|
145
|
+
case 6 /* Uom */:
|
|
146
|
+
return formatUom(value.value, value.unit, locale, us);
|
|
147
|
+
case 7 /* Matrix */:
|
|
148
|
+
return formatMatrix(value.value, locale, us);
|
|
149
|
+
case 8 /* Range */: {
|
|
150
|
+
const r = value.value;
|
|
151
|
+
return formatRange(r.min, r.max, locale);
|
|
152
|
+
}
|
|
153
|
+
case 9 /* Symbolic */:
|
|
154
|
+
return formatSymbolic(value.value);
|
|
155
|
+
case 5 /* Percentage */:
|
|
156
|
+
return formatPercentage(value.value, locale, us);
|
|
157
|
+
case 11 /* Unit */:
|
|
158
|
+
return formatUnit(value.value, value.unit);
|
|
159
|
+
case 13 /* Error */:
|
|
160
|
+
return value.unit ?? String(value.value);
|
|
161
|
+
default:
|
|
162
|
+
return `= ${String(value.value)}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { DEFAULT_FORMATTING_SETTINGS, formatValue };
|
|
167
|
+
//# sourceMappingURL=format.js.map
|
|
168
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/format/FormattingSettings.ts","../src/format/FormatEngine.ts"],"names":[],"mappings":"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","file":"format.js","sourcesContent":["/**\n * Minimal formatting settings interface for the engine\n * This allows the engine to format values without depending on app-specific settings\n */\nexport interface FormattingSettings {\n floatResult: {\n decimalPlaces: number;\n enableSeperator: boolean;\n };\n numberResult: {\n decimalSeparatorLocale: string;\n };\n hexResult: {\n enablePadding: boolean;\n paddingZeros: number;\n };\n unitOfMeasurementResult: {\n decimalPlaces: number;\n unitNames: boolean;\n };\n percentageResult: {\n decimalPlaces: number;\n };\n}\n\n/** Formatting used when a host supplies none. */\nexport const DEFAULT_FORMATTING_SETTINGS: FormattingSettings = {\n floatResult: {\n decimalPlaces: 2,\n enableSeperator: true,\n },\n numberResult: {\n decimalSeparatorLocale: \"en-US\",\n },\n hexResult: {\n enablePadding: false,\n paddingZeros: 0,\n },\n unitOfMeasurementResult: {\n decimalPlaces: 2,\n unitNames: true,\n },\n percentageResult: {\n decimalPlaces: 2,\n },\n};\n","import { Value, ValueType, type MatrixData, type MatrixEntry, type RangeData } from \"@solve-js/vm/Value\";\nimport { getLocale, type ILocale } from \"@solve-js/constants/locales\";\nimport { autoFormatIntegerOrFloat } from \"@solve-js/utilities/Number\";\nimport { FormattingSettings, DEFAULT_FORMATTING_SETTINGS } from \"./FormattingSettings\";\nimport { CURRENCY_DISPLAY } from \"@solve-js/uom/CurrencyAliases\";\nimport { columnMajorToRowMajor } from \"@solve-js/vm/MatrixOps\";\nimport { formatSymbolic, type SymbolicNode } from \"@solve-js/symbolic\";\n\nfunction formatNumber(value: number, locale: ILocale, settings: FormattingSettings): string {\n const dp = settings.floatResult.decimalPlaces;\n const sep = settings.floatResult.enableSeperator;\n const loc = settings.numberResult.decimalSeparatorLocale;\n const formatted = autoFormatIntegerOrFloat(value, dp, sep, loc);\n return `${locale.display.resultPrefix}${formatted}`;\n}\n\n/**\n * Renders a number in whichever base it is tagged with.\n *\n * The zero padding is a hexadecimal setting and stays one. Applying it to a\n * binary rendering would pad `0b101` out to the same digit count as a hex\n * value, which is a different quantity of zeros and not what the setting asks\n * for.\n */\nfunction formatHex(value: number, settings: FormattingSettings, base?: string): string {\n // Truncate and take the sign off before converting. `Number.toString(radix)`\n // does neither: it renders -255 as \"-ff\", which lands the minus inside the\n // literal as `0x-FF`, and it renders 255.7 as \"ff.b3333333333\", inventing\n // fractional hex digits for a notation that has no use for them. Both were\n // visible on `as hex` until the builtins started sharing this path.\n const truncated = Math.trunc(value);\n const sign = truncated < 0 ? \"-\" : \"\";\n const magnitude = Math.abs(truncated);\n\n if (base === \"bin\") return `= ${sign}0b${magnitude.toString(2)}`;\n if (base === \"oct\") return `= ${sign}0o${magnitude.toString(8)}`;\n const padding = settings.hexResult.enablePadding ? settings.hexResult.paddingZeros : 0;\n const hex = magnitude.toString(16).toUpperCase().padStart(padding, \"0\");\n return `= ${sign}0x${hex}`;\n}\n\nfunction formatBigInt(value: bigint): string {\n return `= ${value}`;\n}\n\nfunction formatString(value: string): string {\n return `= ${value}`;\n}\n\nfunction formatBoolean(value: boolean): string {\n return `= ${value}`;\n}\n\n/**\n * Renders a Datetime value locale-aware, the previous implementation\n * called `d.toLocaleString()` with no arguments, which always uses the JS\n * runtime's own default locale and never actually consulted `locale.code`\n * despite receiving it as a parameter (both branches of its old\n * `dateFormat === \"default\"` check were byte-for-byte identical, dead\n * groundwork for a distinction that was never implemented). Concretely,\n * this meant every configured locale (including the shipped German one)\n * always displayed weekday/month names in English. See GitHub issue #77.\n *\n * Uses `weekday`/`month`: \"long\" for a spelled-out date (\"Monday,\n * November 17, 2025\" / \"lundi 17 novembre 2025\") since that's what a\n * literal weekday name is for; a bare numeric date doesn't need\n * localizing beyond the decimal/thousands separators `formatNumber()`\n * already handles. The time-of-day portion is only appended when it's\n * not exactly local midnight, bare date literals (\"today\", \"17/11/2025\")\n * always anchor to local midnight, and showing \"00:00:00\" on every one of\n * those would be noise, not information.\n */\nfunction formatDatetime(value: number, locale: ILocale): string {\n const d = new Date(value);\n const dateStr = d.toLocaleDateString(locale.code, { weekday: \"long\", year: \"numeric\", month: \"long\", day: \"numeric\" });\n const isMidnight = d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;\n if (isMidnight) return `= ${dateStr}`;\n return `= ${dateStr}, ${d.toLocaleTimeString(locale.code)}`;\n}\n\n/**\n * Renders a millisecond duration as clock-style `H:MM` (or `H:MM:SS` when\n * there's a non-zero seconds component). `ms` is never a user-typeable\n * unit (confirmed: it appears nowhere in `lexer/units.ts`), it's only\n * ever produced by subtracting two clock times/datetimes (`9:30 - 8:30`,\n * `VM.ts`'s Datetime SUB case), so this is a safe, narrow special case,\n * not a general change to how durations display.\n */\nfunction formatMsDuration(ms: number): string {\n const sign = ms < 0 ? \"-\" : \"\";\n const totalSeconds = Math.round(Math.abs(ms) / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, \"0\");\n if (seconds === 0) return `${sign}${hours}:${mm}`;\n const ss = String(seconds).padStart(2, \"0\");\n return `${sign}${hours}:${mm}:${ss}`;\n}\n\nfunction formatUom(value: number, unit: string | undefined, locale: ILocale, settings: FormattingSettings): string {\n if (unit === \"ms\") return `= ${formatMsDuration(value)}`;\n\n const dp = settings.unitOfMeasurementResult.decimalPlaces;\n const useUnitNames = settings.unitOfMeasurementResult.unitNames;\n\n // For TimeSpan values (days, weeks, hours, etc.), format as integer if the value is a whole number\n const timeSpanUnits = [\"days\", \"weeks\", \"hours\", \"minutes\", \"seconds\", \"day\", \"week\", \"hour\", \"minute\", \"second\"];\n const isTimeSpan = unit && timeSpanUnits.includes(unit);\n\n let formatted: string;\n if (isTimeSpan && value === Math.floor(value)) {\n // For whole number TimeSpan values, format as integer\n formatted = value.toString();\n } else {\n // For other values, use the configured decimal places\n formatted = value.toFixed(dp);\n }\n\n // Currency display: symbol + culturally-conventional placement (e.g.\n // \"$100.00\" prefix vs \"100.00 kr\" suffix) instead of the generic\n // \"amount CODE\" fallback below. See uom/CurrencyAliases.ts's\n // CURRENCY_DISPLAY table for the exact set covered and the reasoning\n // behind each placement choice. Any currency code NOT in that table\n // (most of the ~150 `CurrencyExchange.isCurrency()` recognizes) falls\n // through to the unchanged \"amount CODE\" format below.\n const currencyDisplay = unit ? CURRENCY_DISPLAY[unit.toUpperCase()] : undefined;\n if (currencyDisplay) {\n const sep = currencyDisplay.spaced ? \" \" : \"\";\n const withSymbol = currencyDisplay.position === \"prefix\"\n ? `${currencyDisplay.symbol}${sep}${formatted}`\n : `${formatted}${sep}${currencyDisplay.symbol}`;\n return `= ${withSymbol}`;\n }\n\n const unitLabel = useUnitNames ? (unit || \"\") : (unit || \"\");\n return `= ${formatted} ${unitLabel}`.trim();\n}\n\nfunction formatMatrixEntry(entry: MatrixEntry, settings: FormattingSettings): string {\n if (typeof entry === \"boolean\") return entry ? \"true\" : \"false\";\n if (typeof entry === \"object\" && entry !== null) return formatSymbolic(entry);\n const dp = settings.floatResult.decimalPlaces;\n const sep = settings.floatResult.enableSeperator;\n const loc = settings.numberResult.decimalSeparatorLocale;\n return autoFormatIntegerOrFloat(entry, dp, sep, loc);\n}\n\n/**\n * Renders a Matrix matching its own literal syntax: a single row (1xN,\n * including plain vectors) as `[a, b, c]`, a single column (Nx1) as\n * `[a; b; c]`, and a general shape as `[r0c0, r0c1; r1c0, r1c1]`, row-major\n * textual output read back out of the column-major storage\n * (`columnMajorToRowMajor()`), matching how `[1,2;3,4]` is written.\n */\nfunction formatMatrix(m: MatrixData, locale: ILocale, settings: FormattingSettings): string {\n const rowMajor = columnMajorToRowMajor(m);\n const rows: string[] = [];\n for (let r = 0; r < m.rows; r++) {\n const cells: string[] = [];\n for (let c = 0; c < m.cols; c++) {\n cells.push(formatMatrixEntry(rowMajor[r * m.cols + c], settings));\n }\n rows.push(cells.join(\", \"));\n }\n return `${locale.display.resultPrefix}[${rows.join(\"; \")}]`;\n}\n\nfunction formatRange(min: number, max: number, locale: ILocale): string {\n return `${locale.display.resultPrefix}${min}:${max}`;\n}\n\nfunction formatPercentage(value: number, locale: ILocale, settings: FormattingSettings): string {\n // ValueType.Percentage stores a fraction (0.25 for 25%). See Value.ts's\n // documented contract and the sole producer, VM.ts's TO_PERCENTAGE opcode\n // (`right/left - 1`, e.g. 0.25 for \"800 to 1000\"). Multiply by 100 before\n // formatting; without this every percentage-change result displayed as\n // e.g. \"0.25%\" instead of \"25.00%\".\n const dp = settings.percentageResult.decimalPlaces;\n const formatted = (value * 100).toFixed(dp);\n return `= ${formatted}${locale.display.percentageSuffix}`;\n}\n\nfunction formatUnit(value: number, unit: string | undefined): string {\n return `= ${value} ${unit || \"\"}`.trim();\n}\n\n/**\n * Render an evaluated {@link Value} as a display string, dispatching on\n * `value.type` to the type-specific formatter (number, hex, datetime, unit\n * of measurement, matrix, range, percentage, ...).\n *\n * Most branches produce a `\"= \"`-prefixed result string (matching the\n * plugin's inline-result convention); `ValueType.Error` is the one\n * exception, it returns the human-readable error message directly\n * (stored in `value.unit`), not an `\"= \"`-prefixed string.\n *\n * @param value - The evaluated value to format.\n * @param settings - Locale/precision/separator options; defaults to\n * {@link DEFAULT_FORMATTING_SETTINGS} when omitted.\n * @example\n * ```typescript\n * const [value] = engine.evaluateExpression(\"10 USD to GBP\");\n * formatValue(value); // \"= £7.85\" (exact output depends on live exchange rates)\n * ```\n */\nexport function formatValue(value: Value, settings?: FormattingSettings): string {\n const us = settings || DEFAULT_FORMATTING_SETTINGS;\n const localeCode = us.numberResult.decimalSeparatorLocale || \"en\";\n const locale = getLocale(localeCode);\n\n switch (value.type) {\n case ValueType.Number:\n return formatNumber(value.value as number, locale, us);\n case ValueType.Hex:\n return formatHex(value.value as number, us, value.unit);\n case ValueType.BigInt:\n return formatBigInt(value.value as bigint);\n case ValueType.String:\n return formatString(value.value as string);\n case ValueType.Boolean:\n return formatBoolean(value.value as boolean);\n case ValueType.Datetime:\n return formatDatetime(value.value as number, locale);\n case ValueType.Uom:\n return formatUom(value.value as number, value.unit, locale, us);\n case ValueType.Matrix:\n return formatMatrix(value.value as MatrixData, locale, us);\n case ValueType.Range: {\n const r = value.value as RangeData;\n return formatRange(r.min, r.max, locale);\n }\n case ValueType.Symbolic:\n return formatSymbolic(value.value as SymbolicNode);\n case ValueType.Percentage:\n return formatPercentage(value.value as number, locale, us);\n case ValueType.Unit:\n return formatUnit(value.value as number, value.unit);\n case ValueType.Error:\n // errorValue(code, message) stores the human-readable message in\n // `.unit` (code goes in `.value`), falling through to the default\n // case here previously displayed the raw code (e.g.\n // \"CURRENCY_RATE_UNAVAILABLE\") instead of the actual message.\n return value.unit ?? String(value.value);\n default:\n return `= ${String(value.value)}`;\n }\n}\n"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkJBSYC7BB_cjs = require('./chunk-JBSYC7BB.cjs');
|
|
4
|
+
var chunkNMCRQP3Z_cjs = require('./chunk-NMCRQP3Z.cjs');
|
|
5
|
+
require('./chunk-NGBBNL4K.cjs');
|
|
6
|
+
require('./chunk-X6K3HUOY.cjs');
|
|
7
|
+
require('./chunk-5X2PTP6F.cjs');
|
|
8
|
+
require('./chunk-6NTVRDQV.cjs');
|
|
9
|
+
require('./chunk-47LRVGOT.cjs');
|
|
10
|
+
require('./chunk-RZCWSXTA.cjs');
|
|
11
|
+
require('./chunk-C4XZV6E7.cjs');
|
|
12
|
+
require('./chunk-EBSPLUW4.cjs');
|
|
13
|
+
require('./chunk-N5YFR4UP.cjs');
|
|
14
|
+
require('./chunk-WQTTOGXC.cjs');
|
|
15
|
+
require('./chunk-Z2XP767T.cjs');
|
|
16
|
+
require('./chunk-J73SJHR3.cjs');
|
|
17
|
+
var chunkFEAIOR7N_cjs = require('./chunk-FEAIOR7N.cjs');
|
|
18
|
+
require('./chunk-XJCMXB2E.cjs');
|
|
19
|
+
require('./chunk-MZOVP3WI.cjs');
|
|
20
|
+
require('./chunk-VEKIWQ3F.cjs');
|
|
21
|
+
require('./chunk-OT6OJY7C.cjs');
|
|
22
|
+
require('./chunk-HTXVVJRA.cjs');
|
|
23
|
+
var chunkOC6LTXYS_cjs = require('./chunk-OC6LTXYS.cjs');
|
|
24
|
+
require('./chunk-QNJ4ACRT.cjs');
|
|
25
|
+
var chunkLR7YASZF_cjs = require('./chunk-LR7YASZF.cjs');
|
|
26
|
+
var chunkCLL7RUQV_cjs = require('./chunk-CLL7RUQV.cjs');
|
|
27
|
+
require('./chunk-6BKTCEUP.cjs');
|
|
28
|
+
require('./chunk-NMD5VRN4.cjs');
|
|
29
|
+
require('./chunk-GW32KPCU.cjs');
|
|
30
|
+
require('./chunk-3YNVWKR2.cjs');
|
|
31
|
+
require('./chunk-EHAHVROS.cjs');
|
|
32
|
+
require('./chunk-53B6KDDJ.cjs');
|
|
33
|
+
require('./chunk-M4N5GA5Z.cjs');
|
|
34
|
+
require('./chunk-B7LXJ6LC.cjs');
|
|
35
|
+
|
|
36
|
+
// src/api/PackageRegistry.ts
|
|
37
|
+
var PackageRegistry = class {
|
|
38
|
+
constructor() {
|
|
39
|
+
this.Value = chunkOC6LTXYS_cjs.Value;
|
|
40
|
+
}
|
|
41
|
+
registerPrefixParselet(tokenType, parselet) {
|
|
42
|
+
chunkNMCRQP3Z_cjs.sharedParseletRegistry.registerPrefix(tokenType, parselet);
|
|
43
|
+
}
|
|
44
|
+
registerInfixParselet(tokenType, parselet) {
|
|
45
|
+
chunkNMCRQP3Z_cjs.sharedParseletRegistry.registerInfix(tokenType, parselet);
|
|
46
|
+
}
|
|
47
|
+
registerVariableSource(source) {
|
|
48
|
+
chunkFEAIOR7N_cjs.sharedVariableResolver.registerSource(source);
|
|
49
|
+
}
|
|
50
|
+
registerPackage(pkg) {
|
|
51
|
+
chunkJBSYC7BB_cjs.assertEngineVersionCompatible(pkg);
|
|
52
|
+
if (pkg.lexerVocabulary) {
|
|
53
|
+
chunkCLL7RUQV_cjs.sharedLexer.registerVocabulary(pkg.lexerVocabulary);
|
|
54
|
+
}
|
|
55
|
+
if (pkg.prefixParselets) {
|
|
56
|
+
for (const pp of pkg.prefixParselets) {
|
|
57
|
+
this.registerPrefixParselet(pp.tokenType, pp.parselet);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (pkg.infixParselets) {
|
|
61
|
+
for (const ip of pkg.infixParselets) {
|
|
62
|
+
this.registerInfixParselet(ip.tokenType, ip.parselet);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (pkg.variableSources) {
|
|
66
|
+
for (const vs of pkg.variableSources) {
|
|
67
|
+
this.registerVariableSource(vs);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var packageRegistry = new PackageRegistry();
|
|
73
|
+
|
|
74
|
+
Object.defineProperty(exports, "ExpressionEngine", {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
get: function () { return chunkJBSYC7BB_cjs.ExpressionEngine; }
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "assertEngineVersionCompatible", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () { return chunkJBSYC7BB_cjs.assertEngineVersionCompatible; }
|
|
81
|
+
});
|
|
82
|
+
Object.defineProperty(exports, "checkEngineVersionCompatibility", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get: function () { return chunkJBSYC7BB_cjs.checkEngineVersionCompatibility; }
|
|
85
|
+
});
|
|
86
|
+
Object.defineProperty(exports, "checkPackageCompatibility", {
|
|
87
|
+
enumerable: true,
|
|
88
|
+
get: function () { return chunkJBSYC7BB_cjs.checkPackageCompatibility; }
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(exports, "ENGINE_VERSION", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () { return chunkLR7YASZF_cjs.ENGINE_VERSION; }
|
|
93
|
+
});
|
|
94
|
+
exports.PackageRegistry = PackageRegistry;
|
|
95
|
+
exports.packageRegistry = packageRegistry;
|
|
96
|
+
//# sourceMappingURL=index.cjs.map
|
|
97
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/PackageRegistry.ts"],"names":["Value","sharedParseletRegistry","sharedVariableResolver","assertEngineVersionCompatible","sharedLexer"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+PO,IAAM,kBAAN,MAAkD;AAAA,EAAlD,WAAA,GAAA;AACL,IAAA,IAAA,CAAA,KAAA,GAAQA,uBAAA;AAAA,EAAA;AAAA,EAER,sBAAA,CAAuB,WAAmB,QAAA,EAAgC;AACxE,IAAAC,wCAAA,CAAuB,cAAA,CAAe,WAAW,QAAQ,CAAA;AAAA,EAC3D;AAAA,EAEA,qBAAA,CAAsB,WAAmB,QAAA,EAA+B;AACtE,IAAAA,wCAAA,CAAuB,aAAA,CAAc,WAAW,QAAQ,CAAA;AAAA,EAC1D;AAAA,EAEA,uBAAuB,MAAA,EAA+B;AACpD,IAAAC,wCAAA,CAAuB,eAAe,MAAM,CAAA;AAAA,EAC9C;AAAA,EAEA,gBAAgB,GAAA,EAA2B;AAMzC,IAAAC,+CAAA,CAA8B,GAAG,CAAA;AAEjC,IAAA,IAAI,IAAI,eAAA,EAAiB;AACvB,MAAAC,6BAAA,CAAY,kBAAA,CAAmB,IAAI,eAAe,CAAA;AAAA,IACpD;AACA,IAAA,IAAI,IAAI,eAAA,EAAiB;AACvB,MAAA,KAAA,MAAW,EAAA,IAAM,IAAI,eAAA,EAAiB;AACpC,QAAA,IAAA,CAAK,sBAAA,CAAuB,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAQ,CAAA;AAAA,MACvD;AAAA,IACF;AACA,IAAA,IAAI,IAAI,cAAA,EAAgB;AACtB,MAAA,KAAA,MAAW,EAAA,IAAM,IAAI,cAAA,EAAgB;AACnC,QAAA,IAAA,CAAK,qBAAA,CAAsB,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAQ,CAAA;AAAA,MACtD;AAAA,IACF;AACA,IAAA,IAAI,IAAI,eAAA,EAAiB;AACvB,MAAA,KAAA,MAAW,EAAA,IAAM,IAAI,eAAA,EAAiB;AACpC,QAAA,IAAA,CAAK,uBAAuB,EAAE,CAAA;AAAA,MAChC;AAAA,IACF;AAAA,EAIF;AACF;AAQO,IAAM,eAAA,GAAkB,IAAI,eAAA","file":"index.cjs","sourcesContent":["import { sharedParseletRegistry } from \"@solve-js/parser/registry/ParseletRegistry\";\nimport { PrefixParselet, InfixParselet } from \"@solve-js/parser/Parselet\";\nimport { Value } from \"@solve-js/vm/Value\";\nimport { IVariableSource } from \"@solve-js/variables/IVariableSource\";\nimport { sharedVariableResolver } from \"@solve-js/variables/VariableResolver\";\nimport { sharedLexer } from \"@solve-js/lexer/Lexer\";\nimport type { LexerVocabulary } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { IAsyncResolver } from \"@solve-js/resolvers/ResolverRegistry\";\nimport type { NormalizerRule } from \"@solve-js/normalizer/NormalizerRule\";\nimport type { TokenCategory } from \"@solve-js/language/TokenCategory\";\nimport type { CompletionItem } from \"@solve-js/language/LanguageService\";\nimport type { LineExecutionContext } from \"@solve-js/vm/VM\";\nimport { assertEngineVersionCompatible } from \"./EngineVersionCompatibility\";\n\n/**\n * Public API for registering plugins with the solve-js engine.\n *\n * All registration goes through this interface, parselets, variable\n * sources, and full packages. The default implementation is\n * {@link PackageRegistry} (singleton via {@link packageRegistry}).\n *\n * @example\n * ```typescript\n * import { packageRegistry } from \"solve-engine\";\n * packageRegistry.registerPackage(myCustomPackage);\n * ```\n */\nexport interface IPackageRegistry {\n /** Register a prefix parselet (e.g., `GE`, `NOW`, `floor`). */\n registerPrefixParselet(tokenType: string, parselet: PrefixParselet): void;\n /** Register an infix parselet (e.g., `+`, `in`, `to`). */\n registerInfixParselet(tokenType: string, parselet: InfixParselet): void;\n /** @deprecated Has no effect. See {@link IEnginePackage.variableSources}. */\n registerVariableSource(source: IVariableSource): void;\n /** Register a complete package (parselets + variable sources). */\n registerPackage(pkg: IEnginePackage): void;\n /** Convenience reference to the Value class for creating typed values. */\n Value: typeof Value;\n}\n\n/**\n * Package descriptor for registering a complete provider with the engine.\n *\n * A package bundles all the pieces needed for a domain-specific provider:\n * lexer plugins for custom token recognition, parselets for Pratt parsing,\n * plugin functions dispatched via CALL_PLUGIN bytecode, variable sources,\n * and optional async resolvers for data that loads asynchronously (e.g.,\n * exchange rates, game prices).\n *\n * @example\n * ```typescript\n * const myPackage: IEnginePackage = {\n * name: \"MyProvider\",\n * lexerVocabulary: myLexerVocabulary,\n * prefixParselets: [{ tokenType: \"MY_FUNC\", parselet: new MyParselet() }],\n * pluginFunctions: [{ index: MY_FN_IDX, handler: myHandler }],\n * asyncResolvers: [myAsyncResolver],\n * };\n * packageRegistry.registerPackage(myPackage);\n * ```\n */\nexport interface IEnginePackage {\n /** Human-readable name for debugging and error attribution. */\n name: string;\n /**\n * Semver range of `solve-engine` versions this package is compatible with\n * (e.g. `\"^0.1.0\"`, `\">=0.1.0 <0.3.0\"`), checked against the engine's own\n * running version ({@link ENGINE_VERSION}, `@solve-js/constants/version`)\n * via `checkEngineVersionCompatibility()`/`assertEngineVersionCompatible()`\n * (`@solve-js/api/EngineVersionCompatibility`) at registration time.\n *\n * Optional, omitted means \"no declared constraint,\" so every package\n * that predates this field (all built-ins, `examples/osrs`) keeps\n * registering exactly as before.\n *\n * Unlike every other compatibility signal in this codebase (e.g.\n * `checkPackageCompatibility()`'s sibling-package collision warnings,\n * which always log and proceed. See `api/PackageCompatibility.ts`), a\n * declared `engineVersion` range the running engine does NOT satisfy is\n * a deliberate, hard REJECTION: `registerPackage()` throws rather than\n * warning. See `ARCHITECTURE.md` §5.3.\n */\n engineVersion?: string;\n /** Optional lexer vocabulary (keywords/operators/units) for recognizing custom tokens (e.g., `GE`, `£`). */\n lexerVocabulary?: LexerVocabulary;\n /** Prefix parselets for this package's custom functions/operators. */\n prefixParselets?: Array<{ tokenType: string; parselet: PrefixParselet }>;\n /** Infix parselets for this package's custom binary operators. */\n infixParselets?: Array<{ tokenType: string; parselet: InfixParselet }>;\n /**\n * Functions dispatched via CALL_PLUGIN bytecode (emitted by this package's\n * parselets with `builder.emitIndex(index)`).\n *\n * Each entry's `index` MUST come from {@link allocatePluginFunctionIndex}\n * (`@solve-js/vm/VMBuiltins`), never hardcode a number. Two packages\n * independently picking the same index would silently overwrite each\n * other's handler in the shared registry.\n *\n * The handler's optional second parameter, `context`, carries the\n * current line's {@link LineExecutionContext} (line number, and, only\n * inside a real document, never `evaluateExpression()`'s single-shot\n * path, closures for reading another line's cached result). Every\n * handler that doesn't need cross-line data can ignore it entirely.\n *\n * @example\n * ```ts\n * const MY_FN_IDX = allocatePluginFunctionIndex();\n * // In a parselet's parse(): builder.emitOpcode(OpCode.CALL_PLUGIN); builder.emitIndex(MY_FN_IDX); builder.emitIndex(argCount);\n * pluginFunctions: [{ index: MY_FN_IDX, handler: myHandler }]\n * ```\n */\n pluginFunctions?: Array<{ index: number; handler: (args: Value[], context?: LineExecutionContext) => Value | Promise<Value> }>;\n /**\n * Named-variable sources.\n *\n * @deprecated Currently has no effect. Sources declared here are registered\n * into the engine's {@link EngineContext} and unregistered again on package\n * removal, but no evaluation path ever calls `VariableResolver.resolve()`, so\n * a variable a source provides is never found. Verified by searching every\n * use of `IVariableSource` outside its own declaration: they are all\n * registration bookkeeping.\n *\n * Declared here rather than deleted because removing a public field is a\n * breaking change and the intended behaviour is worth keeping. Documented as\n * dead so a package author does not spend an afternoon working out why their\n * variables resolve to nothing. To expose a value today, contribute a plugin\n * function through {@link IEnginePackage.pluginFunctions}.\n */\n variableSources?: IVariableSource[];\n /**\n * Async resolvers for this package's domain.\n * When set, the ExpressionEngine runs preflight() before VM execution\n * for each resolver. If async data is needed, a Pending result is\n * returned immediately and the line re-evaluates when the data resolves.\n *\n * Each resolver must have a unique `namespace`, the ResolverRegistry\n * is keyed by namespace. Multiple resolvers let a package handle\n * distinct async operations (e.g., `fetch`, `wait`, `poll`) in\n * separate, focused classes rather than one monolithic preflight().\n */\n asyncResolvers?: IAsyncResolver[];\n /**\n * Multi-word phrases to fuse into single compound tokens.\n * Each key is a space-separated phrase (e.g., \"to the power of\"),\n * each value is the target token type after fusion (e.g., \"CARET\").\n *\n * Registered into the engine's {@link PhraseTrie} for single-pass\n * O(depth) matching, no separate rule scanning per phrase.\n *\n * @example\n * ```ts\n * phrases: {\n * \"to the power of\": \"CARET\",\n * \"abyssal whip\": \"ITEM\",\n * }\n * ```\n */\n phrases?: Record<string, string>;\n /**\n * Normalizer rules for post-lexer token transformation.\n * Applied by the TokenNormalizer between lexing and parsing.\n * For phrase fusion, prefer the declarative {@link phrases} field\n * which uses the faster PhraseTrie. Use this for non-phrase rules\n * like implicit operator insertion.\n */\n normalizerRules?: NormalizerRule[];\n /**\n * Semantic highlight categories for this package's custom token types\n * (introduced via {@link lexerVocabulary} or {@link normalizerRules}), the\n * plugin-facing half of solve-js's editor-agnostic language service (see\n * `language/TokenCategoryMap.ts`). Without an entry here, a package's\n * custom tokens (e.g. a game-item name fused from several identifiers)\n * are still lexed and parsed correctly, but render with no highlight\n * category in any editor integration.\n *\n * @example\n * ```ts\n * tokenCategories: { MY_KEYWORD: \"keyword\", MY_ITEM: \"my-plugin-item\" }\n * ```\n */\n tokenCategories?: Record<string, TokenCategory>;\n /**\n * Completion candidates for this package, the plugin-facing half of\n * solve-js's editor-agnostic completions API\n * (`LanguageService.getCompletions()`). A package's single-word\n * keywords (via {@link lexerVocabulary}) already flow into completions\n * automatically; this field is for candidates that AREN'T lexer\n * keywords, such as a vocabulary of item/entity names. A plain,\n * pre-built list, not a callback, completion candidate lists are\n * meant to be cheap and static within one engine configuration.\n *\n * @example\n * ```ts\n * completionItems: [{ label: \"Abyssal whip\", category: \"my-plugin-item\", detail: \"Item\" }]\n * ```\n */\n completionItems?: CompletionItem[];\n /**\n * Custom `as <name>` converters, the extension point for the\n * Converters package's general `<expr> as <type>` grammar (e.g.\n * `50% as decimal`, `255 as hex`). The built-in converter names\n * (`percent`, `decimal`, `hex`, `fraction`, `multiplier`, `sci`,\n * `binary`, `octal`, ...) dispatch to dedicated fast opcodes; anything\n * else, including any name a third-party package registers here\n * resolves through `OpCode.CALL_AS_CONVERTER` against\n * `vm/VMBuiltins.ts`'s `asConverterRegistry` at runtime. No lexer\n * keyword registration is needed for a custom name: the AS parselet\n * accepts any bare-word token after \"as\" and reads its raw text.\n *\n * Each handler is a pure, synchronous `(value: Value) => Value`, for\n * async conversions (e.g. a live currency-style lookup), use\n * {@link asyncResolvers} instead.\n *\n * @example\n * ```ts\n * asConverters: { roman: (v) => stringValue(toRomanNumeral(v.toNumber())) }\n * ```\n */\n asConverters?: Record<string, (value: Value) => Value>;\n}\n\n/**\n * Default implementation of {@link IPackageRegistry}, the plugin registration API.\n *\n * All registrations delegate to shared singletons (parselet registry,\n * variable resolver, lexer). This ensures that packages registered through\n * any PackageRegistry instance are visible engine-wide.\n *\n * @example\n * ```typescript\n * import { packageRegistry } from \"solve-engine\";\n *\n * // Register a complete provider package\n * packageRegistry.registerPackage({\n * name: \"MyProvider\",\n * prefixParselets: [{ tokenType: \"MY_FUNC\", parselet: new MyParselet() }],\n * });\n * ```\n *\n * @deprecated Register on an engine instead:\n * `engine.registerPackage(pkg)`.\n *\n * This class writes into process-wide singletons, which is incompatible with an\n * engine owning its own registries. Since the introduction of\n * {@link EngineContext}, an engine reads plugin functions, opcode handlers and\n * variable sources from its own context, so a package registered here is not\n * visible to any engine. Parselets and lexer vocabulary registered here reach\n * the shared registries, which an engine also does not read: it builds its own\n * `ParseletRegistry` and its own `Lexer`.\n *\n * In other words this path registers into state nothing evaluates against. It\n * remains exported because removing it is a breaking change, and it is where\n * the singletons that survive are still written from, but it should not be used\n * in new code and will be removed before 1.0 proper.\n */\nexport class PackageRegistry implements IPackageRegistry {\n Value = Value;\n\n registerPrefixParselet(tokenType: string, parselet: PrefixParselet): void {\n sharedParseletRegistry.registerPrefix(tokenType, parselet);\n }\n\n registerInfixParselet(tokenType: string, parselet: InfixParselet): void {\n sharedParseletRegistry.registerInfix(tokenType, parselet);\n }\n\n registerVariableSource(source: IVariableSource): void {\n sharedVariableResolver.registerSource(source);\n }\n\n registerPackage(pkg: IEnginePackage): void {\n // Same hard engine-version gate ExpressionEngine.registerPackage() uses\n // (see its own comment and ARCHITECTURE.md §5.3). This weaker\n // shared-singleton path had no compatibility checking of any kind\n // before this, so without this call the version gate would be\n // trivially bypassable through this entry point.\n assertEngineVersionCompatible(pkg);\n\n if (pkg.lexerVocabulary) {\n sharedLexer.registerVocabulary(pkg.lexerVocabulary);\n }\n if (pkg.prefixParselets) {\n for (const pp of pkg.prefixParselets) {\n this.registerPrefixParselet(pp.tokenType, pp.parselet);\n }\n }\n if (pkg.infixParselets) {\n for (const ip of pkg.infixParselets) {\n this.registerInfixParselet(ip.tokenType, ip.parselet);\n }\n }\n if (pkg.variableSources) {\n for (const vs of pkg.variableSources) {\n this.registerVariableSource(vs);\n }\n }\n // Note: asyncResolvers are NOT registered here, the shared PackageRegistry singleton\n // doesn't have a ResolverRegistry (that lives inside ExpressionEngine).\n // Use ExpressionEngine.registerPackage() directly if you need async resolvers.\n }\n}\n\n/**\n * Singleton PackageRegistry instance, the default plugin registration API.\n *\n * All packages should register through this instance. The underlying registries\n * are shared singletons, so multiple PackageRegistry instances would be redundant.\n */\nexport const packageRegistry = new PackageRegistry();\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { I as IEnginePackage } from './PackageRegistry-D-Tv_7ca.cjs';
|
|
2
|
+
export { E as EvalResults, a as ExpressionEngine, b as IPackageRegistry, L as LineEvaluation, P as PackageRegistry, p as packageRegistry } from './PackageRegistry-D-Tv_7ca.cjs';
|
|
3
|
+
export { ENGINE_VERSION } from './constants.cjs';
|
|
4
|
+
import './Parselet-CK8cQu2a.cjs';
|
|
5
|
+
import './BytecodeBuilder-3egMyuDi.cjs';
|
|
6
|
+
import './Token-0jpvUdPY.cjs';
|
|
7
|
+
import './pipeline-DPUQt7yL.cjs';
|
|
8
|
+
import './Value-KtAQNHur.cjs';
|
|
9
|
+
import './variables.cjs';
|
|
10
|
+
import './Lexer-BJdhlnej.cjs';
|
|
11
|
+
import './resolvers.cjs';
|
|
12
|
+
import '@tanstack/query-core';
|
|
13
|
+
import './NormalizerRule-BrVoVjmP.cjs';
|
|
14
|
+
import './ScopeManager-CKfQtl7l.cjs';
|
|
15
|
+
import './EngineError-DvPSnhZi.cjs';
|
|
16
|
+
import './Configuration-fVpd-HC-.cjs';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Package load-time compatibility checking, the "detect overlapping
|
|
20
|
+
* logic between packages" SDK surface.
|
|
21
|
+
*
|
|
22
|
+
* This engine's package system (`IEnginePackage`) has always had SOME
|
|
23
|
+
* collision visibility, but it's inconsistent and scattered: `ParseletRegistry`
|
|
24
|
+
* warns on a token-type overwrite, `asConverterRegistry` warns on a converter
|
|
25
|
+
* name overwrite, and `PhraseTrie` warns on... nothing at all, a second
|
|
26
|
+
* package fusing the exact same multi-word phrase to a different token type
|
|
27
|
+
* silently wins with zero signal, the same class of gap
|
|
28
|
+
* `ParseletRegistry.registerPrefix()`'s collision-visibility fix closed for
|
|
29
|
+
* parselets specifically (see `ARCHITECTURE.md`'s punch list). And none of
|
|
30
|
+
* these existing checks can be run BEFORE registration, they only fire at
|
|
31
|
+
* the moment a collision actually happens, deep inside a live engine.
|
|
32
|
+
*
|
|
33
|
+
* `checkPackageCompatibility()` is a single, pure, side-effect-free function
|
|
34
|
+
* that statically compares one candidate package's declared descriptor
|
|
35
|
+
* against a list of already-registered packages' descriptors, across every
|
|
36
|
+
* collision-capable field `IEnginePackage` has, callable standalone (a host
|
|
37
|
+
* building a plugin marketplace could run it before ever constructing an
|
|
38
|
+
* engine) or wired into registration itself (see
|
|
39
|
+
* `ExpressionEngine.registerPackage()`, which calls this automatically and
|
|
40
|
+
* logs every conflict found, the "load-up resiliency" half of this
|
|
41
|
+
* mechanism).
|
|
42
|
+
*
|
|
43
|
+
* A real, concrete motivating bug (found the same session this module was
|
|
44
|
+
* built): the currency package's real `IEnginePackage` descriptor
|
|
45
|
+
* (`CurrencyPackage.ts`) and its parallel test-harness registration helper
|
|
46
|
+
* (`parselets/index.ts`'s `registerCurrencyParselets()`) drifted out of sync
|
|
47
|
+
*, new currency-symbol token types were wired into one but not the other
|
|
48
|
+
* caught only by a test happening to exercise the stale path. This module
|
|
49
|
+
* doesn't catch THAT specific class of bug (two hand-written registration
|
|
50
|
+
* functions for the same logical package diverging is a source-consistency
|
|
51
|
+
* problem, not a runtime collision), but it DOES catch the more common and
|
|
52
|
+
* more dangerous sibling: two DIFFERENT, independently-authored packages
|
|
53
|
+
* unknowingly claiming the same token type, phrase, converter name, plugin
|
|
54
|
+
* function index, or lexer keyword.
|
|
55
|
+
*/
|
|
56
|
+
/** How serious a detected conflict is. */
|
|
57
|
+
type CompatibilitySeverity = "error" | "warning" | "info";
|
|
58
|
+
/** The category of overlap detected between two packages. */
|
|
59
|
+
type CompatibilityConflictKind = "prefixParseletTokenType" | "infixParseletTokenType" | "phrase" | "converterName" | "pluginFunctionIndex" | "lexerKeyword" | "lexerOperator" | "asyncResolverNamespace" | "tokenCategory";
|
|
60
|
+
/** One way two packages collide, for example claiming the same keyword. */
|
|
61
|
+
interface CompatibilityConflict {
|
|
62
|
+
kind: CompatibilityConflictKind;
|
|
63
|
+
severity: CompatibilitySeverity;
|
|
64
|
+
/** Human-readable description, safe to log directly. */
|
|
65
|
+
detail: string;
|
|
66
|
+
/** The two package names involved, [existing, candidate]. */
|
|
67
|
+
packages: [string, string];
|
|
68
|
+
}
|
|
69
|
+
/** Every conflict found between a candidate package and those already registered. */
|
|
70
|
+
interface CompatibilityReport {
|
|
71
|
+
/** `false` iff at least one "error"-severity conflict was found. */
|
|
72
|
+
compatible: boolean;
|
|
73
|
+
conflicts: CompatibilityConflict[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Statically check `candidate` against every package in `existing` for
|
|
77
|
+
* overlapping/conflicting declarations, across every collision-capable
|
|
78
|
+
* field `IEnginePackage` has. Pure and side-effect-free, does not touch
|
|
79
|
+
* any shared registry, does not require a live `ExpressionEngine`.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const report = checkPackageCompatibility(myNewPackage, BUILTIN_PACKAGES);
|
|
84
|
+
* if (!report.compatible) {
|
|
85
|
+
* for (const c of report.conflicts) console.error(c.detail);
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
declare function checkPackageCompatibility(candidate: IEnginePackage, existing: IEnginePackage[]): CompatibilityReport;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Engine-version package compatibility gating, the "reject a package built
|
|
93
|
+
* for a different engine version" SDK surface.
|
|
94
|
+
*
|
|
95
|
+
* This is a DIFFERENT kind of check from `api/PackageCompatibility.ts`'s
|
|
96
|
+
* `checkPackageCompatibility()`, and deliberately kept in its own module
|
|
97
|
+
* rather than folded into that one. `checkPackageCompatibility()` answers
|
|
98
|
+
* "do these two SIMULTANEOUSLY-registered packages' declared fields
|
|
99
|
+
* collide" and its contract, pure, package-vs-package, every conflict
|
|
100
|
+
* including "error" severity is advisory, the caller always just logs and
|
|
101
|
+
* proceeds, is locked in by its own regression suite and stated explicitly
|
|
102
|
+
* in `ExpressionEngine.registerPackage()`'s comments. This module answers a
|
|
103
|
+
* different question, "can THIS package's declared engine-version range
|
|
104
|
+
* run against the engine that's actually running RIGHT NOW", and, unlike
|
|
105
|
+
* every other compatibility signal in this codebase, a mismatch here is a
|
|
106
|
+
* hard REJECTION, not a warning. Mixing that blocking behavior into
|
|
107
|
+
* `checkPackageCompatibility()`'s report type would be a footgun for any
|
|
108
|
+
* future reader who's learned (correctly, until now) that every conflict
|
|
109
|
+
* that module can produce stays advisory.
|
|
110
|
+
*
|
|
111
|
+
* `checkEngineVersionCompatibility()` is the pure predicate (mirrors
|
|
112
|
+
* `checkPackageCompatibility()`'s "return a result, caller decides" shape,
|
|
113
|
+
* and this codebase's own testing convention of asserting against plain
|
|
114
|
+
* result objects rather than `toThrow()` for a pure function).
|
|
115
|
+
* `assertEngineVersionCompatible()` is the thin throwing wrapper both
|
|
116
|
+
* `ExpressionEngine.registerPackage()` and the `PackageRegistry` singleton
|
|
117
|
+
* call as the very first thing they do. See `ARCHITECTURE.md` §5.3.
|
|
118
|
+
*/
|
|
119
|
+
type EngineVersionCheckResult = {
|
|
120
|
+
compatible: true;
|
|
121
|
+
} | {
|
|
122
|
+
compatible: false;
|
|
123
|
+
reason: "range-not-satisfied";
|
|
124
|
+
declaredRange: string;
|
|
125
|
+
engineVersion: string;
|
|
126
|
+
} | {
|
|
127
|
+
compatible: false;
|
|
128
|
+
reason: "invalid-range";
|
|
129
|
+
declaredRange: string;
|
|
130
|
+
engineVersion: string;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Pure, side-effect-free. Returns `{ compatible: true }` when `pkg` declares
|
|
134
|
+
* no `engineVersion` at all (no constraint = always allowed, preserves
|
|
135
|
+
* every package that predates this field), when the declared range is
|
|
136
|
+
* satisfied by `engineVersion`, or a `{ compatible: false, reason, ... }`
|
|
137
|
+
* result otherwise. A malformed/unparseable range string (a typo in the
|
|
138
|
+
* package's own descriptor) is its own distinct `"invalid-range"` reason
|
|
139
|
+
* never conflated with a genuine `"range-not-satisfied"` mismatch, so a
|
|
140
|
+
* package author gets feedback about the actual problem they have.
|
|
141
|
+
*/
|
|
142
|
+
declare function checkEngineVersionCompatibility(pkg: IEnginePackage, engineVersion?: string): EngineVersionCheckResult;
|
|
143
|
+
/**
|
|
144
|
+
* Throws an `EngineError` (`ErrorCategory.CONFIG`, matching the existing
|
|
145
|
+
* precedent for `PLUGIN_KEYWORD_COLLISION`/`PLUGIN_OPERATOR_COLLISION`/
|
|
146
|
+
* `PLUGIN_UNIT_COLLISION` in `lexer/ExpressionLexer.ts`, the only other
|
|
147
|
+
* place in this codebase that hard-rejects a package at registration time)
|
|
148
|
+
* when `pkg` is not engine-version compatible. Does nothing when compatible.
|
|
149
|
+
*/
|
|
150
|
+
declare function assertEngineVersionCompatible(pkg: IEnginePackage, engineVersion?: string): void;
|
|
151
|
+
|
|
152
|
+
export { type CompatibilityConflict, type CompatibilityConflictKind, type CompatibilityReport, type CompatibilitySeverity, type EngineVersionCheckResult, IEnginePackage, assertEngineVersionCompatible, checkEngineVersionCompatibility, checkPackageCompatibility };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { I as IEnginePackage } from './PackageRegistry-DaH4aIKP.js';
|
|
2
|
+
export { E as EvalResults, a as ExpressionEngine, b as IPackageRegistry, L as LineEvaluation, P as PackageRegistry, p as packageRegistry } from './PackageRegistry-DaH4aIKP.js';
|
|
3
|
+
export { ENGINE_VERSION } from './constants.js';
|
|
4
|
+
import './Parselet-ConOIdRO.js';
|
|
5
|
+
import './BytecodeBuilder-3egMyuDi.js';
|
|
6
|
+
import './Token-0jpvUdPY.js';
|
|
7
|
+
import './pipeline-CrsRPmsv.js';
|
|
8
|
+
import './Value-KtAQNHur.js';
|
|
9
|
+
import './variables.js';
|
|
10
|
+
import './Lexer-D9l4Yrk2.js';
|
|
11
|
+
import './resolvers.js';
|
|
12
|
+
import '@tanstack/query-core';
|
|
13
|
+
import './NormalizerRule-CEjf1FyD.js';
|
|
14
|
+
import './ScopeManager-B5k0nk05.js';
|
|
15
|
+
import './EngineError-DvPSnhZi.js';
|
|
16
|
+
import './Configuration-fVpd-HC-.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Package load-time compatibility checking, the "detect overlapping
|
|
20
|
+
* logic between packages" SDK surface.
|
|
21
|
+
*
|
|
22
|
+
* This engine's package system (`IEnginePackage`) has always had SOME
|
|
23
|
+
* collision visibility, but it's inconsistent and scattered: `ParseletRegistry`
|
|
24
|
+
* warns on a token-type overwrite, `asConverterRegistry` warns on a converter
|
|
25
|
+
* name overwrite, and `PhraseTrie` warns on... nothing at all, a second
|
|
26
|
+
* package fusing the exact same multi-word phrase to a different token type
|
|
27
|
+
* silently wins with zero signal, the same class of gap
|
|
28
|
+
* `ParseletRegistry.registerPrefix()`'s collision-visibility fix closed for
|
|
29
|
+
* parselets specifically (see `ARCHITECTURE.md`'s punch list). And none of
|
|
30
|
+
* these existing checks can be run BEFORE registration, they only fire at
|
|
31
|
+
* the moment a collision actually happens, deep inside a live engine.
|
|
32
|
+
*
|
|
33
|
+
* `checkPackageCompatibility()` is a single, pure, side-effect-free function
|
|
34
|
+
* that statically compares one candidate package's declared descriptor
|
|
35
|
+
* against a list of already-registered packages' descriptors, across every
|
|
36
|
+
* collision-capable field `IEnginePackage` has, callable standalone (a host
|
|
37
|
+
* building a plugin marketplace could run it before ever constructing an
|
|
38
|
+
* engine) or wired into registration itself (see
|
|
39
|
+
* `ExpressionEngine.registerPackage()`, which calls this automatically and
|
|
40
|
+
* logs every conflict found, the "load-up resiliency" half of this
|
|
41
|
+
* mechanism).
|
|
42
|
+
*
|
|
43
|
+
* A real, concrete motivating bug (found the same session this module was
|
|
44
|
+
* built): the currency package's real `IEnginePackage` descriptor
|
|
45
|
+
* (`CurrencyPackage.ts`) and its parallel test-harness registration helper
|
|
46
|
+
* (`parselets/index.ts`'s `registerCurrencyParselets()`) drifted out of sync
|
|
47
|
+
*, new currency-symbol token types were wired into one but not the other
|
|
48
|
+
* caught only by a test happening to exercise the stale path. This module
|
|
49
|
+
* doesn't catch THAT specific class of bug (two hand-written registration
|
|
50
|
+
* functions for the same logical package diverging is a source-consistency
|
|
51
|
+
* problem, not a runtime collision), but it DOES catch the more common and
|
|
52
|
+
* more dangerous sibling: two DIFFERENT, independently-authored packages
|
|
53
|
+
* unknowingly claiming the same token type, phrase, converter name, plugin
|
|
54
|
+
* function index, or lexer keyword.
|
|
55
|
+
*/
|
|
56
|
+
/** How serious a detected conflict is. */
|
|
57
|
+
type CompatibilitySeverity = "error" | "warning" | "info";
|
|
58
|
+
/** The category of overlap detected between two packages. */
|
|
59
|
+
type CompatibilityConflictKind = "prefixParseletTokenType" | "infixParseletTokenType" | "phrase" | "converterName" | "pluginFunctionIndex" | "lexerKeyword" | "lexerOperator" | "asyncResolverNamespace" | "tokenCategory";
|
|
60
|
+
/** One way two packages collide, for example claiming the same keyword. */
|
|
61
|
+
interface CompatibilityConflict {
|
|
62
|
+
kind: CompatibilityConflictKind;
|
|
63
|
+
severity: CompatibilitySeverity;
|
|
64
|
+
/** Human-readable description, safe to log directly. */
|
|
65
|
+
detail: string;
|
|
66
|
+
/** The two package names involved, [existing, candidate]. */
|
|
67
|
+
packages: [string, string];
|
|
68
|
+
}
|
|
69
|
+
/** Every conflict found between a candidate package and those already registered. */
|
|
70
|
+
interface CompatibilityReport {
|
|
71
|
+
/** `false` iff at least one "error"-severity conflict was found. */
|
|
72
|
+
compatible: boolean;
|
|
73
|
+
conflicts: CompatibilityConflict[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Statically check `candidate` against every package in `existing` for
|
|
77
|
+
* overlapping/conflicting declarations, across every collision-capable
|
|
78
|
+
* field `IEnginePackage` has. Pure and side-effect-free, does not touch
|
|
79
|
+
* any shared registry, does not require a live `ExpressionEngine`.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const report = checkPackageCompatibility(myNewPackage, BUILTIN_PACKAGES);
|
|
84
|
+
* if (!report.compatible) {
|
|
85
|
+
* for (const c of report.conflicts) console.error(c.detail);
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
declare function checkPackageCompatibility(candidate: IEnginePackage, existing: IEnginePackage[]): CompatibilityReport;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Engine-version package compatibility gating, the "reject a package built
|
|
93
|
+
* for a different engine version" SDK surface.
|
|
94
|
+
*
|
|
95
|
+
* This is a DIFFERENT kind of check from `api/PackageCompatibility.ts`'s
|
|
96
|
+
* `checkPackageCompatibility()`, and deliberately kept in its own module
|
|
97
|
+
* rather than folded into that one. `checkPackageCompatibility()` answers
|
|
98
|
+
* "do these two SIMULTANEOUSLY-registered packages' declared fields
|
|
99
|
+
* collide" and its contract, pure, package-vs-package, every conflict
|
|
100
|
+
* including "error" severity is advisory, the caller always just logs and
|
|
101
|
+
* proceeds, is locked in by its own regression suite and stated explicitly
|
|
102
|
+
* in `ExpressionEngine.registerPackage()`'s comments. This module answers a
|
|
103
|
+
* different question, "can THIS package's declared engine-version range
|
|
104
|
+
* run against the engine that's actually running RIGHT NOW", and, unlike
|
|
105
|
+
* every other compatibility signal in this codebase, a mismatch here is a
|
|
106
|
+
* hard REJECTION, not a warning. Mixing that blocking behavior into
|
|
107
|
+
* `checkPackageCompatibility()`'s report type would be a footgun for any
|
|
108
|
+
* future reader who's learned (correctly, until now) that every conflict
|
|
109
|
+
* that module can produce stays advisory.
|
|
110
|
+
*
|
|
111
|
+
* `checkEngineVersionCompatibility()` is the pure predicate (mirrors
|
|
112
|
+
* `checkPackageCompatibility()`'s "return a result, caller decides" shape,
|
|
113
|
+
* and this codebase's own testing convention of asserting against plain
|
|
114
|
+
* result objects rather than `toThrow()` for a pure function).
|
|
115
|
+
* `assertEngineVersionCompatible()` is the thin throwing wrapper both
|
|
116
|
+
* `ExpressionEngine.registerPackage()` and the `PackageRegistry` singleton
|
|
117
|
+
* call as the very first thing they do. See `ARCHITECTURE.md` §5.3.
|
|
118
|
+
*/
|
|
119
|
+
type EngineVersionCheckResult = {
|
|
120
|
+
compatible: true;
|
|
121
|
+
} | {
|
|
122
|
+
compatible: false;
|
|
123
|
+
reason: "range-not-satisfied";
|
|
124
|
+
declaredRange: string;
|
|
125
|
+
engineVersion: string;
|
|
126
|
+
} | {
|
|
127
|
+
compatible: false;
|
|
128
|
+
reason: "invalid-range";
|
|
129
|
+
declaredRange: string;
|
|
130
|
+
engineVersion: string;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Pure, side-effect-free. Returns `{ compatible: true }` when `pkg` declares
|
|
134
|
+
* no `engineVersion` at all (no constraint = always allowed, preserves
|
|
135
|
+
* every package that predates this field), when the declared range is
|
|
136
|
+
* satisfied by `engineVersion`, or a `{ compatible: false, reason, ... }`
|
|
137
|
+
* result otherwise. A malformed/unparseable range string (a typo in the
|
|
138
|
+
* package's own descriptor) is its own distinct `"invalid-range"` reason
|
|
139
|
+
* never conflated with a genuine `"range-not-satisfied"` mismatch, so a
|
|
140
|
+
* package author gets feedback about the actual problem they have.
|
|
141
|
+
*/
|
|
142
|
+
declare function checkEngineVersionCompatibility(pkg: IEnginePackage, engineVersion?: string): EngineVersionCheckResult;
|
|
143
|
+
/**
|
|
144
|
+
* Throws an `EngineError` (`ErrorCategory.CONFIG`, matching the existing
|
|
145
|
+
* precedent for `PLUGIN_KEYWORD_COLLISION`/`PLUGIN_OPERATOR_COLLISION`/
|
|
146
|
+
* `PLUGIN_UNIT_COLLISION` in `lexer/ExpressionLexer.ts`, the only other
|
|
147
|
+
* place in this codebase that hard-rejects a package at registration time)
|
|
148
|
+
* when `pkg` is not engine-version compatible. Does nothing when compatible.
|
|
149
|
+
*/
|
|
150
|
+
declare function assertEngineVersionCompatible(pkg: IEnginePackage, engineVersion?: string): void;
|
|
151
|
+
|
|
152
|
+
export { type CompatibilityConflict, type CompatibilityConflictKind, type CompatibilityReport, type CompatibilitySeverity, type EngineVersionCheckResult, IEnginePackage, assertEngineVersionCompatible, checkEngineVersionCompatibility, checkPackageCompatibility };
|