av6-core 1.6.1 → 1.6.3

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/dist/index.js +217 -11
  2. package/dist/index.mjs +217 -11
  3. package/package.json +36 -35
package/dist/index.js CHANGED
@@ -1320,15 +1320,11 @@ function customOmit(obj, keys) {
1320
1320
  return { rest, omitted };
1321
1321
  }
1322
1322
  function getDynamicValue(obj, accessorKey) {
1323
- if (!accessorKey || obj == null || typeof obj !== "object") {
1324
- return null;
1325
- }
1323
+ if (!accessorKey || obj == null || typeof obj !== "object") return null;
1326
1324
  const keys = accessorKey.split(".");
1327
1325
  let result = obj;
1328
1326
  for (const key of keys) {
1329
- if (result == null || typeof result !== "object" || !(key in result)) {
1330
- return null;
1331
- }
1327
+ if (result == null || typeof result !== "object" || !(key in result)) return null;
1332
1328
  result = result[key];
1333
1329
  }
1334
1330
  return result === void 0 ? null : result;
@@ -1592,6 +1588,214 @@ var buildJoiSchemaForOp = (cfg, op, ctx) => {
1592
1588
  });
1593
1589
  };
1594
1590
 
1591
+ // src/utils/dynamicOperation.utils.ts
1592
+ var import_av6_utils = require("av6-utils");
1593
+ var OP_PRECEDENCE = {
1594
+ "u-": 3,
1595
+ // unary minus
1596
+ "*": 2,
1597
+ "/": 2,
1598
+ "%": 2,
1599
+ "+": 1,
1600
+ "-": 1
1601
+ };
1602
+ var OP_ASSOC = {
1603
+ "u-": "R",
1604
+ "*": "L",
1605
+ "/": "L",
1606
+ "%": "L",
1607
+ "+": "L",
1608
+ "-": "L"
1609
+ };
1610
+ function isDigit(ch) {
1611
+ return ch >= "0" && ch <= "9";
1612
+ }
1613
+ function isIdentStart(ch) {
1614
+ return /[A-Za-z_$]/.test(ch);
1615
+ }
1616
+ function isIdentPart(ch) {
1617
+ return /[A-Za-z0-9_$]/.test(ch);
1618
+ }
1619
+ function tokenize(expr) {
1620
+ const tokens = [];
1621
+ let i = 0;
1622
+ while (i < expr.length) {
1623
+ const ch = expr[i];
1624
+ if (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
1625
+ i++;
1626
+ continue;
1627
+ }
1628
+ if (ch === "(" || ch === ")") {
1629
+ tokens.push({ type: "paren", value: ch });
1630
+ i++;
1631
+ continue;
1632
+ }
1633
+ if (ch === "+" || ch === "-" || ch === "*" || ch === "/" || ch === "%") {
1634
+ tokens.push({ type: "op", value: ch });
1635
+ i++;
1636
+ continue;
1637
+ }
1638
+ if (isDigit(ch) || ch === "." && isDigit(expr[i + 1] ?? "")) {
1639
+ let j = i;
1640
+ let seenDot = false;
1641
+ while (j < expr.length) {
1642
+ const c = expr[j];
1643
+ if (c === ".") {
1644
+ if (seenDot) break;
1645
+ seenDot = true;
1646
+ j++;
1647
+ continue;
1648
+ }
1649
+ if (!isDigit(c)) break;
1650
+ j++;
1651
+ }
1652
+ const raw = expr.slice(i, j);
1653
+ const num = Number(raw);
1654
+ tokens.push({ type: "number", value: num });
1655
+ i = j;
1656
+ continue;
1657
+ }
1658
+ if (isIdentStart(ch)) {
1659
+ let j = i;
1660
+ while (j < expr.length) {
1661
+ const c = expr[j];
1662
+ if (c === ".") {
1663
+ j++;
1664
+ continue;
1665
+ }
1666
+ if (!isIdentPart(c)) break;
1667
+ j++;
1668
+ }
1669
+ const ident = expr.slice(i, j);
1670
+ tokens.push({ type: "ident", value: ident });
1671
+ i = j;
1672
+ continue;
1673
+ }
1674
+ throw new Error(`Invalid character in expression: "${ch}" at position ${i}`);
1675
+ }
1676
+ const out = [];
1677
+ for (let k = 0; k < tokens.length; k++) {
1678
+ const t = tokens[k];
1679
+ if (t.type === "op" && t.value === "-") {
1680
+ const prev = out[out.length - 1];
1681
+ const isUnary = !prev || prev.type === "op" || prev.type === "paren" && prev.value === "(";
1682
+ out.push({ type: "op", value: isUnary ? "u-" : "-" });
1683
+ } else {
1684
+ out.push(t);
1685
+ }
1686
+ }
1687
+ return out;
1688
+ }
1689
+ function toRpn(tokens) {
1690
+ const output = [];
1691
+ const stack = [];
1692
+ for (const t of tokens) {
1693
+ if (t.type === "number" || t.type === "ident") {
1694
+ output.push(t);
1695
+ continue;
1696
+ }
1697
+ if (t.type === "op") {
1698
+ while (stack.length) {
1699
+ const top = stack[stack.length - 1];
1700
+ if (top.type !== "op") break;
1701
+ const pTop = OP_PRECEDENCE[top.value];
1702
+ const pCur = OP_PRECEDENCE[t.value];
1703
+ const shouldPop = OP_ASSOC[t.value] === "L" && pCur <= pTop || OP_ASSOC[t.value] === "R" && pCur < pTop;
1704
+ if (!shouldPop) break;
1705
+ output.push(stack.pop());
1706
+ }
1707
+ stack.push(t);
1708
+ continue;
1709
+ }
1710
+ if (t.type === "paren" && t.value === "(") {
1711
+ stack.push(t);
1712
+ continue;
1713
+ }
1714
+ if (t.type === "paren" && t.value === ")") {
1715
+ let foundLeft = false;
1716
+ while (stack.length) {
1717
+ const top = stack.pop();
1718
+ if (top.type === "paren" && top.value === "(") {
1719
+ foundLeft = true;
1720
+ break;
1721
+ }
1722
+ output.push(top);
1723
+ }
1724
+ if (!foundLeft) throw new Error("Mismatched parentheses");
1725
+ continue;
1726
+ }
1727
+ }
1728
+ while (stack.length) {
1729
+ const top = stack.pop();
1730
+ if (top.type === "paren") throw new Error("Mismatched parentheses");
1731
+ output.push(top);
1732
+ }
1733
+ return output;
1734
+ }
1735
+ function evalRpn(rpn, rowObj) {
1736
+ const stack = [];
1737
+ const toNumberOrNull2 = (v) => {
1738
+ if (v === null || v === void 0 || v === "") return null;
1739
+ const n = typeof v === "number" ? v : Number(v);
1740
+ return Number.isFinite(n) ? n : null;
1741
+ };
1742
+ for (const t of rpn) {
1743
+ if (t.type === "number") {
1744
+ stack.push(t.value);
1745
+ continue;
1746
+ }
1747
+ if (t.type === "ident") {
1748
+ const v = getDynamicValue(rowObj, t.value);
1749
+ const n = toNumberOrNull2(v);
1750
+ if (n === null) return null;
1751
+ stack.push(n);
1752
+ continue;
1753
+ }
1754
+ if (t.type === "op") {
1755
+ if (t.value === "u-") {
1756
+ if (stack.length < 1) throw new Error("Bad expression (unary -)");
1757
+ const a2 = stack.pop();
1758
+ stack.push(-a2);
1759
+ continue;
1760
+ }
1761
+ if (stack.length < 2) throw new Error("Bad expression (binary op)");
1762
+ const b = stack.pop();
1763
+ const a = stack.pop();
1764
+ switch (t.value) {
1765
+ case "+":
1766
+ stack.push(a + b);
1767
+ break;
1768
+ case "-":
1769
+ stack.push(a - b);
1770
+ break;
1771
+ case "*":
1772
+ stack.push(a * b);
1773
+ break;
1774
+ case "/":
1775
+ stack.push(b === 0 ? NaN : a / b);
1776
+ break;
1777
+ case "%":
1778
+ stack.push(b === 0 ? NaN : a % b);
1779
+ break;
1780
+ }
1781
+ continue;
1782
+ }
1783
+ }
1784
+ if (stack.length !== 1) throw new Error("Bad expression (final stack)");
1785
+ const res = stack[0];
1786
+ return Number.isFinite(res) ? (0, import_av6_utils.applyRound)(res, "TO_FIXED", 5) : null;
1787
+ }
1788
+ function getDynamicValueOrExpression(obj, accessorOrExpr) {
1789
+ const s = (accessorOrExpr ?? "").trim();
1790
+ if (!s) return null;
1791
+ if (/[+\-*/%()]/.test(s)) {
1792
+ const tokens = tokenize(s);
1793
+ const rpn = toRpn(tokens);
1794
+ return evalRpn(rpn, obj);
1795
+ }
1796
+ return getDynamicValue(obj, s);
1797
+ }
1798
+
1595
1799
  // src/services/common.service.ts
1596
1800
  var import_axios = __toESM(require("axios"));
1597
1801
  var import_exceljs = __toESM(require("exceljs"));
@@ -1643,7 +1847,7 @@ var commonService = (serviceDeps) => {
1643
1847
  ws.addRow(headers).font = { bold: true };
1644
1848
  for (const element of commonData.data) {
1645
1849
  const row = searchParams.config.map((config) => {
1646
- const value = getDynamicValue(element, config.accessorKey);
1850
+ const value = getDynamicValueOrExpression(element, config.accessorKey);
1647
1851
  return value === null || value === void 0 ? "" : value;
1648
1852
  });
1649
1853
  ws.addRow(row);
@@ -1661,7 +1865,7 @@ var commonService = (serviceDeps) => {
1661
1865
  const detail = searchParams.config?.reduce(
1662
1866
  (acc, curr) => ({
1663
1867
  ...acc,
1664
- [curr.label]: getDynamicValue(element, curr.accessorKey)
1868
+ [curr.label]: getDynamicValueOrExpression(element, curr.accessorKey)
1665
1869
  }),
1666
1870
  {}
1667
1871
  );
@@ -1689,7 +1893,7 @@ var commonService = (serviceDeps) => {
1689
1893
  ws.addRow(headers).font = { bold: true };
1690
1894
  for (const element2 of detailsList) {
1691
1895
  const row = searchParams.detailedConfig.map((config) => {
1692
- const value = getDynamicValue(element2, config.accessorKey);
1896
+ const value = getDynamicValueOrExpression(element2, config.accessorKey);
1693
1897
  return value === null || value === void 0 ? "" : value;
1694
1898
  });
1695
1899
  ws.addRow(row);
@@ -3734,9 +3938,11 @@ var NotificationService = class {
3734
3938
  async (recipient) => {
3735
3939
  const res = await args.provider.send({
3736
3940
  recipient,
3737
- bodyValues: args.bodyValues,
3738
- provider: args.provider
3941
+ bodyValues: args.bodyValues
3942
+ // provider: args.provider,
3739
3943
  // these extra fields exist in your old types; provider.send will ignore extras if not used
3944
+ // eventConfigId: 0,
3945
+ // evt
3740
3946
  });
3741
3947
  return {
3742
3948
  recipient,
package/dist/index.mjs CHANGED
@@ -1270,15 +1270,11 @@ function customOmit(obj, keys) {
1270
1270
  return { rest, omitted };
1271
1271
  }
1272
1272
  function getDynamicValue(obj, accessorKey) {
1273
- if (!accessorKey || obj == null || typeof obj !== "object") {
1274
- return null;
1275
- }
1273
+ if (!accessorKey || obj == null || typeof obj !== "object") return null;
1276
1274
  const keys = accessorKey.split(".");
1277
1275
  let result = obj;
1278
1276
  for (const key of keys) {
1279
- if (result == null || typeof result !== "object" || !(key in result)) {
1280
- return null;
1281
- }
1277
+ if (result == null || typeof result !== "object" || !(key in result)) return null;
1282
1278
  result = result[key];
1283
1279
  }
1284
1280
  return result === void 0 ? null : result;
@@ -1542,6 +1538,214 @@ var buildJoiSchemaForOp = (cfg, op, ctx) => {
1542
1538
  });
1543
1539
  };
1544
1540
 
1541
+ // src/utils/dynamicOperation.utils.ts
1542
+ import { applyRound } from "av6-utils";
1543
+ var OP_PRECEDENCE = {
1544
+ "u-": 3,
1545
+ // unary minus
1546
+ "*": 2,
1547
+ "/": 2,
1548
+ "%": 2,
1549
+ "+": 1,
1550
+ "-": 1
1551
+ };
1552
+ var OP_ASSOC = {
1553
+ "u-": "R",
1554
+ "*": "L",
1555
+ "/": "L",
1556
+ "%": "L",
1557
+ "+": "L",
1558
+ "-": "L"
1559
+ };
1560
+ function isDigit(ch) {
1561
+ return ch >= "0" && ch <= "9";
1562
+ }
1563
+ function isIdentStart(ch) {
1564
+ return /[A-Za-z_$]/.test(ch);
1565
+ }
1566
+ function isIdentPart(ch) {
1567
+ return /[A-Za-z0-9_$]/.test(ch);
1568
+ }
1569
+ function tokenize(expr) {
1570
+ const tokens = [];
1571
+ let i = 0;
1572
+ while (i < expr.length) {
1573
+ const ch = expr[i];
1574
+ if (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
1575
+ i++;
1576
+ continue;
1577
+ }
1578
+ if (ch === "(" || ch === ")") {
1579
+ tokens.push({ type: "paren", value: ch });
1580
+ i++;
1581
+ continue;
1582
+ }
1583
+ if (ch === "+" || ch === "-" || ch === "*" || ch === "/" || ch === "%") {
1584
+ tokens.push({ type: "op", value: ch });
1585
+ i++;
1586
+ continue;
1587
+ }
1588
+ if (isDigit(ch) || ch === "." && isDigit(expr[i + 1] ?? "")) {
1589
+ let j = i;
1590
+ let seenDot = false;
1591
+ while (j < expr.length) {
1592
+ const c = expr[j];
1593
+ if (c === ".") {
1594
+ if (seenDot) break;
1595
+ seenDot = true;
1596
+ j++;
1597
+ continue;
1598
+ }
1599
+ if (!isDigit(c)) break;
1600
+ j++;
1601
+ }
1602
+ const raw = expr.slice(i, j);
1603
+ const num = Number(raw);
1604
+ tokens.push({ type: "number", value: num });
1605
+ i = j;
1606
+ continue;
1607
+ }
1608
+ if (isIdentStart(ch)) {
1609
+ let j = i;
1610
+ while (j < expr.length) {
1611
+ const c = expr[j];
1612
+ if (c === ".") {
1613
+ j++;
1614
+ continue;
1615
+ }
1616
+ if (!isIdentPart(c)) break;
1617
+ j++;
1618
+ }
1619
+ const ident = expr.slice(i, j);
1620
+ tokens.push({ type: "ident", value: ident });
1621
+ i = j;
1622
+ continue;
1623
+ }
1624
+ throw new Error(`Invalid character in expression: "${ch}" at position ${i}`);
1625
+ }
1626
+ const out = [];
1627
+ for (let k = 0; k < tokens.length; k++) {
1628
+ const t = tokens[k];
1629
+ if (t.type === "op" && t.value === "-") {
1630
+ const prev = out[out.length - 1];
1631
+ const isUnary = !prev || prev.type === "op" || prev.type === "paren" && prev.value === "(";
1632
+ out.push({ type: "op", value: isUnary ? "u-" : "-" });
1633
+ } else {
1634
+ out.push(t);
1635
+ }
1636
+ }
1637
+ return out;
1638
+ }
1639
+ function toRpn(tokens) {
1640
+ const output = [];
1641
+ const stack = [];
1642
+ for (const t of tokens) {
1643
+ if (t.type === "number" || t.type === "ident") {
1644
+ output.push(t);
1645
+ continue;
1646
+ }
1647
+ if (t.type === "op") {
1648
+ while (stack.length) {
1649
+ const top = stack[stack.length - 1];
1650
+ if (top.type !== "op") break;
1651
+ const pTop = OP_PRECEDENCE[top.value];
1652
+ const pCur = OP_PRECEDENCE[t.value];
1653
+ const shouldPop = OP_ASSOC[t.value] === "L" && pCur <= pTop || OP_ASSOC[t.value] === "R" && pCur < pTop;
1654
+ if (!shouldPop) break;
1655
+ output.push(stack.pop());
1656
+ }
1657
+ stack.push(t);
1658
+ continue;
1659
+ }
1660
+ if (t.type === "paren" && t.value === "(") {
1661
+ stack.push(t);
1662
+ continue;
1663
+ }
1664
+ if (t.type === "paren" && t.value === ")") {
1665
+ let foundLeft = false;
1666
+ while (stack.length) {
1667
+ const top = stack.pop();
1668
+ if (top.type === "paren" && top.value === "(") {
1669
+ foundLeft = true;
1670
+ break;
1671
+ }
1672
+ output.push(top);
1673
+ }
1674
+ if (!foundLeft) throw new Error("Mismatched parentheses");
1675
+ continue;
1676
+ }
1677
+ }
1678
+ while (stack.length) {
1679
+ const top = stack.pop();
1680
+ if (top.type === "paren") throw new Error("Mismatched parentheses");
1681
+ output.push(top);
1682
+ }
1683
+ return output;
1684
+ }
1685
+ function evalRpn(rpn, rowObj) {
1686
+ const stack = [];
1687
+ const toNumberOrNull2 = (v) => {
1688
+ if (v === null || v === void 0 || v === "") return null;
1689
+ const n = typeof v === "number" ? v : Number(v);
1690
+ return Number.isFinite(n) ? n : null;
1691
+ };
1692
+ for (const t of rpn) {
1693
+ if (t.type === "number") {
1694
+ stack.push(t.value);
1695
+ continue;
1696
+ }
1697
+ if (t.type === "ident") {
1698
+ const v = getDynamicValue(rowObj, t.value);
1699
+ const n = toNumberOrNull2(v);
1700
+ if (n === null) return null;
1701
+ stack.push(n);
1702
+ continue;
1703
+ }
1704
+ if (t.type === "op") {
1705
+ if (t.value === "u-") {
1706
+ if (stack.length < 1) throw new Error("Bad expression (unary -)");
1707
+ const a2 = stack.pop();
1708
+ stack.push(-a2);
1709
+ continue;
1710
+ }
1711
+ if (stack.length < 2) throw new Error("Bad expression (binary op)");
1712
+ const b = stack.pop();
1713
+ const a = stack.pop();
1714
+ switch (t.value) {
1715
+ case "+":
1716
+ stack.push(a + b);
1717
+ break;
1718
+ case "-":
1719
+ stack.push(a - b);
1720
+ break;
1721
+ case "*":
1722
+ stack.push(a * b);
1723
+ break;
1724
+ case "/":
1725
+ stack.push(b === 0 ? NaN : a / b);
1726
+ break;
1727
+ case "%":
1728
+ stack.push(b === 0 ? NaN : a % b);
1729
+ break;
1730
+ }
1731
+ continue;
1732
+ }
1733
+ }
1734
+ if (stack.length !== 1) throw new Error("Bad expression (final stack)");
1735
+ const res = stack[0];
1736
+ return Number.isFinite(res) ? applyRound(res, "TO_FIXED", 5) : null;
1737
+ }
1738
+ function getDynamicValueOrExpression(obj, accessorOrExpr) {
1739
+ const s = (accessorOrExpr ?? "").trim();
1740
+ if (!s) return null;
1741
+ if (/[+\-*/%()]/.test(s)) {
1742
+ const tokens = tokenize(s);
1743
+ const rpn = toRpn(tokens);
1744
+ return evalRpn(rpn, obj);
1745
+ }
1746
+ return getDynamicValue(obj, s);
1747
+ }
1748
+
1545
1749
  // src/services/common.service.ts
1546
1750
  import axios from "axios";
1547
1751
  import ExcelJs from "exceljs";
@@ -1593,7 +1797,7 @@ var commonService = (serviceDeps) => {
1593
1797
  ws.addRow(headers).font = { bold: true };
1594
1798
  for (const element of commonData.data) {
1595
1799
  const row = searchParams.config.map((config) => {
1596
- const value = getDynamicValue(element, config.accessorKey);
1800
+ const value = getDynamicValueOrExpression(element, config.accessorKey);
1597
1801
  return value === null || value === void 0 ? "" : value;
1598
1802
  });
1599
1803
  ws.addRow(row);
@@ -1611,7 +1815,7 @@ var commonService = (serviceDeps) => {
1611
1815
  const detail = searchParams.config?.reduce(
1612
1816
  (acc, curr) => ({
1613
1817
  ...acc,
1614
- [curr.label]: getDynamicValue(element, curr.accessorKey)
1818
+ [curr.label]: getDynamicValueOrExpression(element, curr.accessorKey)
1615
1819
  }),
1616
1820
  {}
1617
1821
  );
@@ -1639,7 +1843,7 @@ var commonService = (serviceDeps) => {
1639
1843
  ws.addRow(headers).font = { bold: true };
1640
1844
  for (const element2 of detailsList) {
1641
1845
  const row = searchParams.detailedConfig.map((config) => {
1642
- const value = getDynamicValue(element2, config.accessorKey);
1846
+ const value = getDynamicValueOrExpression(element2, config.accessorKey);
1643
1847
  return value === null || value === void 0 ? "" : value;
1644
1848
  });
1645
1849
  ws.addRow(row);
@@ -3684,9 +3888,11 @@ var NotificationService = class {
3684
3888
  async (recipient) => {
3685
3889
  const res = await args.provider.send({
3686
3890
  recipient,
3687
- bodyValues: args.bodyValues,
3688
- provider: args.provider
3891
+ bodyValues: args.bodyValues
3892
+ // provider: args.provider,
3689
3893
  // these extra fields exist in your old types; provider.send will ignore extras if not used
3894
+ // eventConfigId: 0,
3895
+ // evt
3690
3896
  });
3691
3897
  return {
3692
3898
  recipient,
package/package.json CHANGED
@@ -1,35 +1,36 @@
1
- {
2
- "name": "av6-core",
3
- "version": "1.6.1",
4
- "main": "dist/index.js",
5
- "module": "dist/index.mjs",
6
- "types": "dist/index.d.ts",
7
- "description": "All utility function for av6 node js projects.",
8
- "author": "Aniket Sarkar",
9
- "license": "ISC",
10
- "scripts": {
11
- "build": "npm run format && tsup",
12
- "p:gen": "prisma generate",
13
- "format": "prettier --write **/*.ts"
14
- },
15
- "devDependencies": {
16
- "@prisma/client": "^6.19.0",
17
- "@types/nodemailer": "^7.0.3",
18
- "tsup": "^8.5.0",
19
- "typescript": "^5.9.2"
20
- },
21
- "peerDependencies": {
22
- "@prisma/client": "^6.19.0",
23
- "winston": "^3.17.0"
24
- },
25
- "dependencies": {
26
- "axios": "^1.11.0",
27
- "exceljs": "^4.4.0",
28
- "handlebars": "^4.7.8",
29
- "joi": "^17.13.3",
30
- "node-cron": "^4.2.1",
31
- "nodemailer": "^7.0.10",
32
- "prettier": "^3.6.2",
33
- "prisma": "^6.19.0"
34
- }
35
- }
1
+ {
2
+ "name": "av6-core",
3
+ "version": "1.6.3",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.mjs",
6
+ "types": "dist/index.d.ts",
7
+ "description": "All utility function for av6 node js projects.",
8
+ "author": "Aniket Sarkar",
9
+ "license": "ISC",
10
+ "scripts": {
11
+ "build": "npm run format && tsup",
12
+ "p:gen": "prisma generate",
13
+ "format": "prettier --write **/*.ts"
14
+ },
15
+ "devDependencies": {
16
+ "@prisma/client": "^6.19.0",
17
+ "@types/nodemailer": "^7.0.3",
18
+ "tsup": "^8.5.0",
19
+ "typescript": "^5.9.2"
20
+ },
21
+ "peerDependencies": {
22
+ "@prisma/client": "^6.19.0",
23
+ "winston": "^3.17.0"
24
+ },
25
+ "dependencies": {
26
+ "av6-utils": "^1.0.4",
27
+ "axios": "^1.11.0",
28
+ "exceljs": "^4.4.0",
29
+ "handlebars": "^4.7.8",
30
+ "joi": "^17.13.3",
31
+ "node-cron": "^4.2.1",
32
+ "nodemailer": "^7.0.10",
33
+ "prettier": "^3.6.2",
34
+ "prisma": "^6.19.0"
35
+ }
36
+ }