@fileverse-dev/formulajs 4.4.15 → 4.4.17-fix-sort-fn-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/formula.js +106 -61
- package/lib/browser/formula.min.js +2 -2
- package/lib/browser/formula.min.js.map +1 -1
- package/lib/cjs/index.cjs +78 -41
- package/lib/esm/index.mjs +78 -41
- package/package.json +1 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -1271,47 +1271,73 @@ function ROWS(array) {
|
|
|
1271
1271
|
* @returns
|
|
1272
1272
|
*/
|
|
1273
1273
|
function SORT(array, sort_index = 1, sort_order = 1, by_col = false) {
|
|
1274
|
-
if (!array || !Array.isArray(array))
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1274
|
+
if (!array || !Array.isArray(array)) return na;
|
|
1275
|
+
if (array.length === 0) return 0;
|
|
1277
1276
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1277
|
+
let idx = parseNumber(sort_index);
|
|
1278
|
+
if (!idx || idx < 1) return value;
|
|
1279
|
+
idx = idx - 1;
|
|
1281
1280
|
|
|
1282
|
-
|
|
1283
|
-
if (
|
|
1284
|
-
return value
|
|
1285
|
-
}
|
|
1281
|
+
let order = parseNumber(sort_order);
|
|
1282
|
+
if (order !== 1 && order !== -1) return value;
|
|
1286
1283
|
|
|
1287
|
-
|
|
1288
|
-
if (
|
|
1289
|
-
|
|
1290
|
-
|
|
1284
|
+
const byCol = parseBool(by_col);
|
|
1285
|
+
if (typeof byCol !== "boolean") return name;
|
|
1286
|
+
|
|
1287
|
+
// Rectangularize then orient
|
|
1288
|
+
const matrix = fillMatrix(array);
|
|
1289
|
+
const working = byCol ? transpose(matrix) : matrix;
|
|
1291
1290
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
return name
|
|
1291
|
+
if (!working.length || !working[0] || idx >= working[0].length) {
|
|
1292
|
+
return value; // out of bounds
|
|
1295
1293
|
}
|
|
1296
1294
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
a = parseString(a[sort_index - 1]);
|
|
1300
|
-
b = parseString(b[sort_index - 1]);
|
|
1295
|
+
// Helpers (aiming for spreadsheet-ish behavior)
|
|
1296
|
+
const isBlank = (v) => v === "" || v === null || v === undefined;
|
|
1301
1297
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1298
|
+
const cmp = (a, b) => {
|
|
1299
|
+
// Blanks last (ascending); we'll multiply by order later for descending.
|
|
1300
|
+
const aBlank = isBlank(a);
|
|
1301
|
+
const bBlank = isBlank(b);
|
|
1302
|
+
if (aBlank && bBlank) return 0;
|
|
1303
|
+
if (aBlank) return 1;
|
|
1304
|
+
if (bBlank) return -1;
|
|
1304
1305
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1306
|
+
// If both parse as finite numbers, compare numerically
|
|
1307
|
+
const na = parseNumber(a);
|
|
1308
|
+
const nb = parseNumber(b);
|
|
1309
|
+
const aNum = Number.isFinite(na);
|
|
1310
|
+
const bNum = Number.isFinite(nb);
|
|
1311
|
+
|
|
1312
|
+
if (aNum && bNum) {
|
|
1313
|
+
if (na < nb) return -1;
|
|
1314
|
+
if (na > nb) return 1;
|
|
1315
|
+
return 0;
|
|
1316
|
+
}
|
|
1307
1317
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1318
|
+
// Fallback: case-insensitive string compare
|
|
1319
|
+
const sa = (parseString(a) ?? "").toString().toLowerCase();
|
|
1320
|
+
const sb = (parseString(b) ?? "").toString().toLowerCase();
|
|
1321
|
+
if (sa < sb) return -1;
|
|
1322
|
+
if (sa > sb) return 1;
|
|
1323
|
+
return 0;
|
|
1324
|
+
};
|
|
1325
|
+
|
|
1326
|
+
// Stable sort: decorate with original index
|
|
1327
|
+
const decorated = working.map((row, i) => ({ row, i }));
|
|
1328
|
+
|
|
1329
|
+
decorated.sort((A, B) => {
|
|
1330
|
+
const base = cmp(A.row[idx], B.row[idx]);
|
|
1331
|
+
if (base !== 0) return base * order;
|
|
1332
|
+
// stable tiebreaker: original order
|
|
1333
|
+
return A.i - B.i;
|
|
1334
|
+
});
|
|
1335
|
+
|
|
1336
|
+
const sorted = decorated.map((d) => d.row);
|
|
1337
|
+
return byCol ? transpose(sorted) : sorted;
|
|
1313
1338
|
}
|
|
1314
1339
|
|
|
1340
|
+
|
|
1315
1341
|
/**
|
|
1316
1342
|
* Returns the transpose of an array.
|
|
1317
1343
|
*
|
|
@@ -17870,7 +17896,7 @@ async function COINGECKO() {
|
|
|
17870
17896
|
const out = {};
|
|
17871
17897
|
for (const [token, prices] of Object.entries(json))
|
|
17872
17898
|
for (const [cur, val] of Object.entries(prices))
|
|
17873
|
-
out[`${token.
|
|
17899
|
+
out[`${token.toUpperCase()}_${cur.toUpperCase()}`] = val;
|
|
17874
17900
|
return [out]
|
|
17875
17901
|
}
|
|
17876
17902
|
|
|
@@ -18586,17 +18612,22 @@ const SUPPORTED_TOKEN_NAMES = {
|
|
|
18586
18612
|
|
|
18587
18613
|
|
|
18588
18614
|
function formatNumber(raw, decimals) {
|
|
18589
|
-
|
|
18615
|
+
try {
|
|
18616
|
+
if(!decimals){
|
|
18617
|
+
return raw
|
|
18618
|
+
}
|
|
18619
|
+
const quorum = BigInt(raw);
|
|
18620
|
+
const divisor = 10 ** decimals;
|
|
18621
|
+
const normalized = Number(quorum) / divisor;
|
|
18622
|
+
|
|
18623
|
+
return new Intl.NumberFormat("en-US", {
|
|
18624
|
+
notation: "compact",
|
|
18625
|
+
maximumFractionDigits: 2,
|
|
18626
|
+
}).format(normalized);
|
|
18627
|
+
} catch (error) {
|
|
18628
|
+
console.log({error});
|
|
18590
18629
|
return raw
|
|
18591
18630
|
}
|
|
18592
|
-
const quorum = BigInt(raw);
|
|
18593
|
-
const divisor = 10 ** decimals;
|
|
18594
|
-
const normalized = Number(quorum) / divisor;
|
|
18595
|
-
|
|
18596
|
-
return new Intl.NumberFormat("en-US", {
|
|
18597
|
-
notation: "compact",
|
|
18598
|
-
maximumFractionDigits: 2,
|
|
18599
|
-
}).format(normalized);
|
|
18600
18631
|
}
|
|
18601
18632
|
|
|
18602
18633
|
let cachedChains = null;
|
|
@@ -18667,7 +18698,13 @@ async function DUNE() {
|
|
|
18667
18698
|
});
|
|
18668
18699
|
|
|
18669
18700
|
const res = await fetch(finalUrl, { method: "GET", headers: HEADERS });
|
|
18670
|
-
if (!res.ok)
|
|
18701
|
+
if (!res.ok) {
|
|
18702
|
+
if(res.status === 400){
|
|
18703
|
+
const data = await res.json();
|
|
18704
|
+
throw new ValidationError(data.message)
|
|
18705
|
+
}
|
|
18706
|
+
throw new NetworkError(SERVICES_API_KEY.DuneSim, res.status);
|
|
18707
|
+
}
|
|
18671
18708
|
|
|
18672
18709
|
const json = await res.json();
|
|
18673
18710
|
const data =
|
package/lib/esm/index.mjs
CHANGED
|
@@ -1269,47 +1269,73 @@ function ROWS(array) {
|
|
|
1269
1269
|
* @returns
|
|
1270
1270
|
*/
|
|
1271
1271
|
function SORT(array, sort_index = 1, sort_order = 1, by_col = false) {
|
|
1272
|
-
if (!array || !Array.isArray(array))
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1272
|
+
if (!array || !Array.isArray(array)) return na;
|
|
1273
|
+
if (array.length === 0) return 0;
|
|
1275
1274
|
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1275
|
+
let idx = parseNumber(sort_index);
|
|
1276
|
+
if (!idx || idx < 1) return value;
|
|
1277
|
+
idx = idx - 1;
|
|
1279
1278
|
|
|
1280
|
-
|
|
1281
|
-
if (
|
|
1282
|
-
return value
|
|
1283
|
-
}
|
|
1279
|
+
let order = parseNumber(sort_order);
|
|
1280
|
+
if (order !== 1 && order !== -1) return value;
|
|
1284
1281
|
|
|
1285
|
-
|
|
1286
|
-
if (
|
|
1287
|
-
|
|
1288
|
-
|
|
1282
|
+
const byCol = parseBool(by_col);
|
|
1283
|
+
if (typeof byCol !== "boolean") return name;
|
|
1284
|
+
|
|
1285
|
+
// Rectangularize then orient
|
|
1286
|
+
const matrix = fillMatrix(array);
|
|
1287
|
+
const working = byCol ? transpose(matrix) : matrix;
|
|
1289
1288
|
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
return name
|
|
1289
|
+
if (!working.length || !working[0] || idx >= working[0].length) {
|
|
1290
|
+
return value; // out of bounds
|
|
1293
1291
|
}
|
|
1294
1292
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
a = parseString(a[sort_index - 1]);
|
|
1298
|
-
b = parseString(b[sort_index - 1]);
|
|
1293
|
+
// Helpers (aiming for spreadsheet-ish behavior)
|
|
1294
|
+
const isBlank = (v) => v === "" || v === null || v === undefined;
|
|
1299
1295
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1296
|
+
const cmp = (a, b) => {
|
|
1297
|
+
// Blanks last (ascending); we'll multiply by order later for descending.
|
|
1298
|
+
const aBlank = isBlank(a);
|
|
1299
|
+
const bBlank = isBlank(b);
|
|
1300
|
+
if (aBlank && bBlank) return 0;
|
|
1301
|
+
if (aBlank) return 1;
|
|
1302
|
+
if (bBlank) return -1;
|
|
1302
1303
|
|
|
1303
|
-
|
|
1304
|
-
|
|
1304
|
+
// If both parse as finite numbers, compare numerically
|
|
1305
|
+
const na = parseNumber(a);
|
|
1306
|
+
const nb = parseNumber(b);
|
|
1307
|
+
const aNum = Number.isFinite(na);
|
|
1308
|
+
const bNum = Number.isFinite(nb);
|
|
1309
|
+
|
|
1310
|
+
if (aNum && bNum) {
|
|
1311
|
+
if (na < nb) return -1;
|
|
1312
|
+
if (na > nb) return 1;
|
|
1313
|
+
return 0;
|
|
1314
|
+
}
|
|
1305
1315
|
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1316
|
+
// Fallback: case-insensitive string compare
|
|
1317
|
+
const sa = (parseString(a) ?? "").toString().toLowerCase();
|
|
1318
|
+
const sb = (parseString(b) ?? "").toString().toLowerCase();
|
|
1319
|
+
if (sa < sb) return -1;
|
|
1320
|
+
if (sa > sb) return 1;
|
|
1321
|
+
return 0;
|
|
1322
|
+
};
|
|
1323
|
+
|
|
1324
|
+
// Stable sort: decorate with original index
|
|
1325
|
+
const decorated = working.map((row, i) => ({ row, i }));
|
|
1326
|
+
|
|
1327
|
+
decorated.sort((A, B) => {
|
|
1328
|
+
const base = cmp(A.row[idx], B.row[idx]);
|
|
1329
|
+
if (base !== 0) return base * order;
|
|
1330
|
+
// stable tiebreaker: original order
|
|
1331
|
+
return A.i - B.i;
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
const sorted = decorated.map((d) => d.row);
|
|
1335
|
+
return byCol ? transpose(sorted) : sorted;
|
|
1311
1336
|
}
|
|
1312
1337
|
|
|
1338
|
+
|
|
1313
1339
|
/**
|
|
1314
1340
|
* Returns the transpose of an array.
|
|
1315
1341
|
*
|
|
@@ -17868,7 +17894,7 @@ async function COINGECKO() {
|
|
|
17868
17894
|
const out = {};
|
|
17869
17895
|
for (const [token, prices] of Object.entries(json))
|
|
17870
17896
|
for (const [cur, val] of Object.entries(prices))
|
|
17871
|
-
out[`${token.
|
|
17897
|
+
out[`${token.toUpperCase()}_${cur.toUpperCase()}`] = val;
|
|
17872
17898
|
return [out]
|
|
17873
17899
|
}
|
|
17874
17900
|
|
|
@@ -18584,17 +18610,22 @@ const SUPPORTED_TOKEN_NAMES = {
|
|
|
18584
18610
|
|
|
18585
18611
|
|
|
18586
18612
|
function formatNumber(raw, decimals) {
|
|
18587
|
-
|
|
18613
|
+
try {
|
|
18614
|
+
if(!decimals){
|
|
18615
|
+
return raw
|
|
18616
|
+
}
|
|
18617
|
+
const quorum = BigInt(raw);
|
|
18618
|
+
const divisor = 10 ** decimals;
|
|
18619
|
+
const normalized = Number(quorum) / divisor;
|
|
18620
|
+
|
|
18621
|
+
return new Intl.NumberFormat("en-US", {
|
|
18622
|
+
notation: "compact",
|
|
18623
|
+
maximumFractionDigits: 2,
|
|
18624
|
+
}).format(normalized);
|
|
18625
|
+
} catch (error) {
|
|
18626
|
+
console.log({error});
|
|
18588
18627
|
return raw
|
|
18589
18628
|
}
|
|
18590
|
-
const quorum = BigInt(raw);
|
|
18591
|
-
const divisor = 10 ** decimals;
|
|
18592
|
-
const normalized = Number(quorum) / divisor;
|
|
18593
|
-
|
|
18594
|
-
return new Intl.NumberFormat("en-US", {
|
|
18595
|
-
notation: "compact",
|
|
18596
|
-
maximumFractionDigits: 2,
|
|
18597
|
-
}).format(normalized);
|
|
18598
18629
|
}
|
|
18599
18630
|
|
|
18600
18631
|
let cachedChains = null;
|
|
@@ -18665,7 +18696,13 @@ async function DUNE() {
|
|
|
18665
18696
|
});
|
|
18666
18697
|
|
|
18667
18698
|
const res = await fetch(finalUrl, { method: "GET", headers: HEADERS });
|
|
18668
|
-
if (!res.ok)
|
|
18699
|
+
if (!res.ok) {
|
|
18700
|
+
if(res.status === 400){
|
|
18701
|
+
const data = await res.json();
|
|
18702
|
+
throw new ValidationError(data.message)
|
|
18703
|
+
}
|
|
18704
|
+
throw new NetworkError(SERVICES_API_KEY.DuneSim, res.status);
|
|
18705
|
+
}
|
|
18669
18706
|
|
|
18670
18707
|
const json = await res.json();
|
|
18671
18708
|
const data =
|