@pydantic/genai-prices 0.0.22 → 0.0.24
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/cli.js +39 -4
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +147 -95
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export declare interface ArrayMatch {
|
|
2
|
+
field: string;
|
|
3
|
+
match: MatchLogic;
|
|
4
|
+
type: 'array-match';
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
export declare function calcPrice(usage: Usage, modelId: string, options?: PriceOptions): PriceCalculationResult;
|
|
2
8
|
|
|
3
9
|
export declare interface ConditionalPrice {
|
|
@@ -5,6 +11,8 @@ export declare interface ConditionalPrice {
|
|
|
5
11
|
prices: ModelPrice;
|
|
6
12
|
}
|
|
7
13
|
|
|
14
|
+
export declare type ExtractPath = (ArrayMatch | string)[] | string;
|
|
15
|
+
|
|
8
16
|
export declare function extractUsage(provider: Provider, responseData: unknown, apiFlavor?: string): [string, Usage];
|
|
9
17
|
|
|
10
18
|
export declare function findProvider(options: ProviderFindOptions): Provider | undefined;
|
|
@@ -140,13 +148,13 @@ export declare interface Usage {
|
|
|
140
148
|
export declare interface UsageExtractor {
|
|
141
149
|
api_flavor: string;
|
|
142
150
|
mappings: UsageExtractorMapping[];
|
|
143
|
-
model_path:
|
|
144
|
-
root:
|
|
151
|
+
model_path: ExtractPath;
|
|
152
|
+
root: ExtractPath;
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
export declare interface UsageExtractorMapping {
|
|
148
156
|
dest: 'cache_audio_read_tokens' | 'cache_read_tokens' | 'cache_write_tokens' | 'input_audio_tokens' | 'input_tokens' | 'output_audio_tokens' | 'output_tokens';
|
|
149
|
-
path:
|
|
157
|
+
path: ExtractPath;
|
|
150
158
|
required: boolean;
|
|
151
159
|
}
|
|
152
160
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export declare interface ArrayMatch {
|
|
2
|
+
field: string;
|
|
3
|
+
match: MatchLogic;
|
|
4
|
+
type: 'array-match';
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
export declare function calcPrice(usage: Usage, modelId: string, options?: PriceOptions): PriceCalculationResult;
|
|
2
8
|
|
|
3
9
|
export declare interface ConditionalPrice {
|
|
@@ -5,6 +11,8 @@ export declare interface ConditionalPrice {
|
|
|
5
11
|
prices: ModelPrice;
|
|
6
12
|
}
|
|
7
13
|
|
|
14
|
+
export declare type ExtractPath = (ArrayMatch | string)[] | string;
|
|
15
|
+
|
|
8
16
|
export declare function extractUsage(provider: Provider, responseData: unknown, apiFlavor?: string): [string, Usage];
|
|
9
17
|
|
|
10
18
|
export declare function findProvider(options: ProviderFindOptions): Provider | undefined;
|
|
@@ -140,13 +148,13 @@ export declare interface Usage {
|
|
|
140
148
|
export declare interface UsageExtractor {
|
|
141
149
|
api_flavor: string;
|
|
142
150
|
mappings: UsageExtractorMapping[];
|
|
143
|
-
model_path:
|
|
144
|
-
root:
|
|
151
|
+
model_path: ExtractPath;
|
|
152
|
+
root: ExtractPath;
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
export declare interface UsageExtractorMapping {
|
|
148
156
|
dest: 'cache_audio_read_tokens' | 'cache_read_tokens' | 'cache_write_tokens' | 'input_audio_tokens' | 'input_tokens' | 'output_audio_tokens' | 'output_tokens';
|
|
149
|
-
path:
|
|
157
|
+
path: ExtractPath;
|
|
150
158
|
required: boolean;
|
|
151
159
|
}
|
|
152
160
|
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const w = [
|
|
2
2
|
{
|
|
3
3
|
id: "anthropic",
|
|
4
4
|
name: "Anthropic",
|
|
@@ -21,6 +21,16 @@ const f = [
|
|
|
21
21
|
dest: "input_tokens",
|
|
22
22
|
required: !0
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
path: "cache_creation_input_tokens",
|
|
26
|
+
dest: "input_tokens",
|
|
27
|
+
required: !1
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
path: "cache_read_input_tokens",
|
|
31
|
+
dest: "input_tokens",
|
|
32
|
+
required: !1
|
|
33
|
+
},
|
|
24
34
|
{
|
|
25
35
|
path: "cache_creation_input_tokens",
|
|
26
36
|
dest: "cache_write_tokens",
|
|
@@ -1509,8 +1519,8 @@ Compared to other leading proprietary and open-weights models Command A delivers
|
|
|
1509
1519
|
extractors: [
|
|
1510
1520
|
{
|
|
1511
1521
|
api_flavor: "default",
|
|
1512
|
-
root: "
|
|
1513
|
-
model_path: "
|
|
1522
|
+
root: "usageMetadata",
|
|
1523
|
+
model_path: "modelVersion",
|
|
1514
1524
|
mappings: [
|
|
1515
1525
|
{
|
|
1516
1526
|
path: "promptTokenCount",
|
|
@@ -1518,10 +1528,35 @@ Compared to other leading proprietary and open-weights models Command A delivers
|
|
|
1518
1528
|
required: !0
|
|
1519
1529
|
},
|
|
1520
1530
|
{
|
|
1521
|
-
path:
|
|
1531
|
+
path: [
|
|
1532
|
+
"cacheTokensDetails",
|
|
1533
|
+
{
|
|
1534
|
+
type: "array-match",
|
|
1535
|
+
field: "modality",
|
|
1536
|
+
match: {
|
|
1537
|
+
equals: "TEXT"
|
|
1538
|
+
}
|
|
1539
|
+
},
|
|
1540
|
+
"tokenCount"
|
|
1541
|
+
],
|
|
1522
1542
|
dest: "cache_read_tokens",
|
|
1523
1543
|
required: !1
|
|
1524
1544
|
},
|
|
1545
|
+
{
|
|
1546
|
+
path: [
|
|
1547
|
+
"cacheTokensDetails",
|
|
1548
|
+
{
|
|
1549
|
+
type: "array-match",
|
|
1550
|
+
field: "modality",
|
|
1551
|
+
match: {
|
|
1552
|
+
equals: "AUDIO"
|
|
1553
|
+
}
|
|
1554
|
+
},
|
|
1555
|
+
"tokenCount"
|
|
1556
|
+
],
|
|
1557
|
+
dest: "cache_audio_read_tokens",
|
|
1558
|
+
required: !1
|
|
1559
|
+
},
|
|
1525
1560
|
{
|
|
1526
1561
|
path: "candidatesTokenCount",
|
|
1527
1562
|
dest: "output_tokens",
|
|
@@ -3613,7 +3648,7 @@ Compared to other leading proprietary and open-weights models Command A delivers
|
|
|
3613
3648
|
equals: "gpt-5-nano"
|
|
3614
3649
|
},
|
|
3615
3650
|
{
|
|
3616
|
-
|
|
3651
|
+
starts_with: "gpt-5-nano-"
|
|
3617
3652
|
}
|
|
3618
3653
|
]
|
|
3619
3654
|
},
|
|
@@ -10846,23 +10881,23 @@ Compared to other leading proprietary and open-weights models Command A delivers
|
|
|
10846
10881
|
]
|
|
10847
10882
|
}
|
|
10848
10883
|
];
|
|
10849
|
-
function
|
|
10884
|
+
function y(t, e) {
|
|
10850
10885
|
if (e <= 0) return 0;
|
|
10851
10886
|
let a = 0;
|
|
10852
|
-
const i = [...t.tiers].sort((r,
|
|
10853
|
-
a +=
|
|
10887
|
+
const i = [...t.tiers].sort((r, s) => r.start - s.start), o = i[0]?.start ?? e, n = Math.min(e, o);
|
|
10888
|
+
a += n * t.base / 1e6;
|
|
10854
10889
|
for (let r = 0; r < i.length; r++) {
|
|
10855
|
-
const
|
|
10856
|
-
u > 0 && (a += u *
|
|
10890
|
+
const s = i[r], m = i[r + 1]?.start ?? 1 / 0, u = Math.max(0, Math.min(e, m) - s.start);
|
|
10891
|
+
u > 0 && (a += u * s.price / 1e6);
|
|
10857
10892
|
}
|
|
10858
10893
|
return a;
|
|
10859
10894
|
}
|
|
10860
|
-
function
|
|
10861
|
-
return t === void 0 || e === void 0 ? 0 : typeof t == "number" ? t * e / 1e6 :
|
|
10895
|
+
function p(t, e, a) {
|
|
10896
|
+
return t === void 0 || e === void 0 ? 0 : typeof t == "number" ? t * e / 1e6 : y(t, e);
|
|
10862
10897
|
}
|
|
10863
|
-
function
|
|
10898
|
+
function M(t, e) {
|
|
10864
10899
|
let a = 0, i = 0;
|
|
10865
|
-
a +=
|
|
10900
|
+
a += p(e.input_mtok, t.input_tokens), a += p(e.cache_write_mtok, t.cache_write_tokens), a += p(e.cache_read_mtok, t.cache_read_tokens), a += p(e.input_audio_mtok, t.input_audio_tokens), a += p(e.cache_audio_read_mtok, t.cache_audio_read_tokens), i += p(e.output_mtok, t.output_tokens), i += p(e.output_audio_mtok, t.output_audio_tokens), e.requests_kcount !== void 0 && (a += e.requests_kcount / 1e3);
|
|
10866
10901
|
const o = a + i;
|
|
10867
10902
|
return {
|
|
10868
10903
|
input_price: a,
|
|
@@ -10870,7 +10905,7 @@ function B(t, e) {
|
|
|
10870
10905
|
total_price: o
|
|
10871
10906
|
};
|
|
10872
10907
|
}
|
|
10873
|
-
function
|
|
10908
|
+
function I(t, e) {
|
|
10874
10909
|
if (!Array.isArray(t.prices))
|
|
10875
10910
|
return t.prices;
|
|
10876
10911
|
for (let a = t.prices.length - 1; a >= 0; a--) {
|
|
@@ -10881,150 +10916,167 @@ function y(t, e) {
|
|
|
10881
10916
|
if (e >= new Date(o.start_date))
|
|
10882
10917
|
return i.prices;
|
|
10883
10918
|
} else {
|
|
10884
|
-
const
|
|
10885
|
-
if (
|
|
10886
|
-
if (
|
|
10919
|
+
const n = e.toISOString().slice(11, 19), r = o.start_time, s = o.end_time;
|
|
10920
|
+
if (s < r) {
|
|
10921
|
+
if (n >= r || n < s)
|
|
10887
10922
|
return i.prices;
|
|
10888
|
-
} else if (
|
|
10923
|
+
} else if (n >= r && n < s)
|
|
10889
10924
|
return i.prices;
|
|
10890
10925
|
}
|
|
10891
10926
|
}
|
|
10892
10927
|
return t.prices[0].prices;
|
|
10893
10928
|
}
|
|
10894
|
-
function
|
|
10895
|
-
return "or" in t ? t.or.some((a) =>
|
|
10929
|
+
function h(t, e) {
|
|
10930
|
+
return "or" in t ? t.or.some((a) => h(a, e)) : "and" in t ? t.and.every((a) => h(a, e)) : "equals" in t ? e === t.equals : "starts_with" in t ? e.startsWith(t.starts_with) : "ends_with" in t ? e.endsWith(t.ends_with) : "contains" in t ? e.includes(t.contains) : "regex" in t ? new RegExp(t.regex).test(e) : !1;
|
|
10896
10931
|
}
|
|
10897
|
-
function
|
|
10932
|
+
function P(t, e) {
|
|
10898
10933
|
const a = e.toLowerCase().trim(), i = t.find((o) => o.id === a);
|
|
10899
|
-
return i || t.find((o) => o.provider_match &&
|
|
10934
|
+
return i || t.find((o) => o.provider_match && h(o.provider_match, a));
|
|
10900
10935
|
}
|
|
10901
|
-
function
|
|
10936
|
+
function v(t, { modelId: e, providerApiUrl: a, providerId: i }) {
|
|
10902
10937
|
if (i)
|
|
10903
|
-
return
|
|
10938
|
+
return P(t, i);
|
|
10904
10939
|
if (a)
|
|
10905
10940
|
return t.find((o) => new RegExp(o.api_pattern).test(a));
|
|
10906
10941
|
if (e)
|
|
10907
|
-
return t.find((o) => o.model_match &&
|
|
10942
|
+
return t.find((o) => o.model_match && h(o.model_match, e));
|
|
10908
10943
|
}
|
|
10909
|
-
function
|
|
10910
|
-
return t.find((a) =>
|
|
10944
|
+
function L(t, e) {
|
|
10945
|
+
return t.find((a) => h(a.match, e));
|
|
10911
10946
|
}
|
|
10912
|
-
const
|
|
10913
|
-
let
|
|
10914
|
-
function
|
|
10915
|
-
"then" in t ? (
|
|
10916
|
-
|
|
10917
|
-
})) : (
|
|
10947
|
+
const T = "https://raw.githubusercontent.com/pydantic/genai-prices/main/prices/data.json";
|
|
10948
|
+
let _ = w, q = Promise.resolve(w), b = null;
|
|
10949
|
+
function G(t) {
|
|
10950
|
+
"then" in t ? (q = t, t.then((e) => {
|
|
10951
|
+
_ = e;
|
|
10952
|
+
})) : (q = Promise.resolve(t), _ = t);
|
|
10918
10953
|
}
|
|
10919
|
-
function
|
|
10920
|
-
|
|
10954
|
+
function S(t) {
|
|
10955
|
+
b = t;
|
|
10921
10956
|
}
|
|
10922
|
-
function
|
|
10957
|
+
function z(t) {
|
|
10923
10958
|
t({
|
|
10924
|
-
onCalc:
|
|
10925
|
-
remoteDataUrl:
|
|
10926
|
-
setProviderData:
|
|
10959
|
+
onCalc: S,
|
|
10960
|
+
remoteDataUrl: T,
|
|
10961
|
+
setProviderData: G
|
|
10927
10962
|
});
|
|
10928
10963
|
}
|
|
10929
|
-
function
|
|
10930
|
-
return
|
|
10964
|
+
function N() {
|
|
10965
|
+
return q;
|
|
10931
10966
|
}
|
|
10932
|
-
function
|
|
10933
|
-
|
|
10934
|
-
const i = e.toLowerCase().trim(), o = a?.provider ??
|
|
10967
|
+
function Q(t, e, a) {
|
|
10968
|
+
b?.();
|
|
10969
|
+
const i = e.toLowerCase().trim(), o = a?.provider ?? v(_, { modelId: i, providerApiUrl: a?.providerApiUrl, providerId: a?.providerId });
|
|
10935
10970
|
if (!o) return null;
|
|
10936
|
-
const
|
|
10937
|
-
if (!
|
|
10938
|
-
const r = a?.timestamp ?? /* @__PURE__ */ new Date(),
|
|
10971
|
+
const n = L(o.models, i);
|
|
10972
|
+
if (!n) return null;
|
|
10973
|
+
const r = a?.timestamp ?? /* @__PURE__ */ new Date(), s = I(n, r), m = M(t, s);
|
|
10939
10974
|
return {
|
|
10940
10975
|
auto_update_timestamp: void 0,
|
|
10941
|
-
model:
|
|
10942
|
-
model_price:
|
|
10976
|
+
model: n,
|
|
10977
|
+
model_price: s,
|
|
10943
10978
|
provider: o,
|
|
10944
|
-
...
|
|
10979
|
+
...m
|
|
10945
10980
|
};
|
|
10946
10981
|
}
|
|
10947
|
-
function
|
|
10948
|
-
return
|
|
10982
|
+
function E(t) {
|
|
10983
|
+
return b?.(), v(_, t);
|
|
10949
10984
|
}
|
|
10950
|
-
function
|
|
10985
|
+
function O(t, e, a) {
|
|
10951
10986
|
if (!t.extractors)
|
|
10952
10987
|
throw new Error("No extraction logic defined for this provider");
|
|
10953
10988
|
let i;
|
|
10954
10989
|
if (a) {
|
|
10955
|
-
const
|
|
10956
|
-
if (
|
|
10957
|
-
i =
|
|
10990
|
+
const m = t.extractors.find((u) => u.api_flavor === a);
|
|
10991
|
+
if (m)
|
|
10992
|
+
i = m;
|
|
10958
10993
|
else {
|
|
10959
|
-
const u = t.extractors.map((
|
|
10994
|
+
const u = t.extractors.map((l) => l.api_flavor).join(", ");
|
|
10960
10995
|
throw new Error(`Unknown apiFlavor '${a}', allowed values: ${u}`);
|
|
10961
10996
|
}
|
|
10962
10997
|
} else if (t.extractors.length === 1)
|
|
10963
10998
|
i = t.extractors[0];
|
|
10964
10999
|
else
|
|
10965
11000
|
throw new Error("No apiFlavor specified and multiple extractors available");
|
|
10966
|
-
if (!
|
|
11001
|
+
if (!k.guard(e))
|
|
10967
11002
|
throw new Error(`Expected response data to be a mapping object, got ${c(e)}`);
|
|
10968
|
-
const o =
|
|
10969
|
-
for (const
|
|
10970
|
-
const u =
|
|
11003
|
+
const o = g(i.model_path, e, A, !0, []), n = x(i.root), r = g(n, e, k, !0, []), s = {};
|
|
11004
|
+
for (const m of i.mappings) {
|
|
11005
|
+
const u = g(m.path, r, C, m.required, n);
|
|
10971
11006
|
if (u !== null) {
|
|
10972
|
-
const
|
|
10973
|
-
m
|
|
11007
|
+
const l = s[m.dest] ?? 0;
|
|
11008
|
+
s[m.dest] = l + u;
|
|
10974
11009
|
}
|
|
10975
11010
|
}
|
|
10976
|
-
if (!Object.keys(
|
|
11011
|
+
if (!Object.keys(s).length)
|
|
10977
11012
|
throw new Error(`No usage information found at ${JSON.stringify(i.root)}`);
|
|
10978
|
-
return [o,
|
|
11013
|
+
return [o, s];
|
|
10979
11014
|
}
|
|
10980
|
-
function
|
|
10981
|
-
const [
|
|
10982
|
-
if (typeof
|
|
10983
|
-
throw new Error(`Expected last step of path to be a string, got ${c(
|
|
10984
|
-
let m = e;
|
|
11015
|
+
function g(t, e, a, i, o) {
|
|
11016
|
+
const [n, ...r] = x(t).reverse();
|
|
11017
|
+
if (typeof n != "string")
|
|
11018
|
+
throw new Error(`Expected last step of path to be a string, got ${c(n)}`);
|
|
10985
11019
|
r.reverse();
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
11020
|
+
let s = e;
|
|
11021
|
+
const m = [];
|
|
11022
|
+
for (const l of r) {
|
|
11023
|
+
if (m.push(l), typeof l == "object")
|
|
11024
|
+
if (Array.isArray(s))
|
|
11025
|
+
s = R(l, s);
|
|
11026
|
+
else
|
|
11027
|
+
throw new Error(`Expected \`${d(o, m)}\` value to be a mapping, got ${c(s)}`);
|
|
11028
|
+
else if (k.guard(s))
|
|
11029
|
+
s = s[l];
|
|
11030
|
+
else
|
|
11031
|
+
throw new Error(`Expected \`${d(o, m)}\` value to be a mapping, got ${c(s)}`);
|
|
11032
|
+
if (typeof s > "u")
|
|
11033
|
+
if (i) {
|
|
11034
|
+
const B = typeof l == "object" ? "Unable to find item" : "Missing value";
|
|
11035
|
+
throw new Error(`${B} at \`${d(o, m)}\``);
|
|
11036
|
+
} else
|
|
11037
|
+
return null;
|
|
10996
11038
|
}
|
|
10997
|
-
|
|
11039
|
+
if (!k.guard(s))
|
|
11040
|
+
throw new Error(`Expected \`${d(o, m)}\` value to be a mapping, got ${c(s)}`);
|
|
11041
|
+
const u = s[n];
|
|
10998
11042
|
if (typeof u > "u") {
|
|
10999
11043
|
if (i)
|
|
11000
|
-
throw
|
|
11044
|
+
throw m.push(n), new Error(`Missing value at \`${d(o, m)}\``);
|
|
11001
11045
|
return null;
|
|
11002
11046
|
}
|
|
11003
11047
|
if (a.guard(u))
|
|
11004
11048
|
return u;
|
|
11005
|
-
throw
|
|
11049
|
+
throw m.push(n), new Error(`Expected \`${d(o, m)}\` value to be a ${a.name}, got ${c(u)}`);
|
|
11006
11050
|
}
|
|
11007
|
-
function
|
|
11051
|
+
function R(t, e) {
|
|
11052
|
+
for (const a of e)
|
|
11053
|
+
if (k.guard(a)) {
|
|
11054
|
+
const i = a[t.field];
|
|
11055
|
+
if (typeof i == "string" && h(t.match, i))
|
|
11056
|
+
return a;
|
|
11057
|
+
}
|
|
11058
|
+
}
|
|
11059
|
+
function x(t) {
|
|
11008
11060
|
return Array.isArray(t) ? [...t] : [t];
|
|
11009
11061
|
}
|
|
11010
11062
|
function c(t) {
|
|
11011
11063
|
return t === null ? "null" : Array.isArray(t) ? "array" : typeof t == "object" ? "mapping" : typeof t;
|
|
11012
11064
|
}
|
|
11013
|
-
const
|
|
11065
|
+
const k = {
|
|
11014
11066
|
guard: (t) => c(t) === "mapping",
|
|
11015
11067
|
name: "mapping"
|
|
11016
|
-
},
|
|
11068
|
+
}, A = {
|
|
11017
11069
|
guard: (t) => typeof t == "string",
|
|
11018
11070
|
name: "string"
|
|
11019
|
-
},
|
|
11071
|
+
}, C = {
|
|
11020
11072
|
guard: (t) => typeof t == "number",
|
|
11021
11073
|
name: "number"
|
|
11022
|
-
};
|
|
11074
|
+
}, d = (t, e) => [...t.map(f), ...e.map(f)].join("."), f = (t) => typeof t == "string" ? t : JSON.stringify(t);
|
|
11023
11075
|
export {
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11076
|
+
T as REMOTE_DATA_JSON_URL,
|
|
11077
|
+
Q as calcPrice,
|
|
11078
|
+
O as extractUsage,
|
|
11079
|
+
E as findProvider,
|
|
11080
|
+
z as updatePrices,
|
|
11081
|
+
N as waitForUpdate
|
|
11030
11082
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pydantic/genai-prices",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"description": "Calculate prices for calling LLM inference APIs",
|
|
5
5
|
"author": "Pydantic Team",
|
|
6
6
|
"type": "module",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dev": "vite build --watch",
|
|
48
48
|
"typecheck": "tsc --noEmit",
|
|
49
49
|
"lint": "eslint",
|
|
50
|
-
"
|
|
50
|
+
"lint-fix": "eslint --fix --quiet",
|
|
51
51
|
"test": "vitest run",
|
|
52
52
|
"test:watch": "vitest",
|
|
53
53
|
"test:ui": "vitest --ui",
|