@valbuild/server 0.106.1 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -5,4 +5,4 @@ import { ValidationError } from "@valbuild/core";
|
|
|
5
5
|
* There is no schema in hand here — a `ValidationError` carries only the value
|
|
6
6
|
* it flagged — so the shape is all there is to go on.
|
|
7
7
|
*/
|
|
8
|
-
export declare function getValidationErrorFileRef(validationError: ValidationError):
|
|
8
|
+
export declare function getValidationErrorFileRef(validationError: ValidationError): any;
|
|
@@ -3648,7 +3648,7 @@ class JsonEntryFilesFingerprint {
|
|
|
3648
3648
|
if (cached && cached.moduleMtimeMs === moduleMtimeMs) {
|
|
3649
3649
|
return cached.entryFilePaths;
|
|
3650
3650
|
}
|
|
3651
|
-
let entryFilePaths
|
|
3651
|
+
let entryFilePaths;
|
|
3652
3652
|
try {
|
|
3653
3653
|
const contents = fs__default["default"].readFileSync(absModulePath, "utf-8");
|
|
3654
3654
|
entryFilePaths = findJsonEntryFilePathsInSource(moduleFilePath, ts__default["default"].createSourceFile(absModulePath, contents, ts__default["default"].ScriptTarget.ES2015));
|
|
@@ -3972,14 +3972,14 @@ const FSPatch = z.z.object({
|
|
|
3972
3972
|
path: z.z.string().refine(p => p.startsWith("/") && p.includes(".val."), "Path is not valid. Must start with '/' and include '.val.'"),
|
|
3973
3973
|
patch: internal.Patch,
|
|
3974
3974
|
patchId: z.z.string(),
|
|
3975
|
-
baseSha: z.z.string().refine(
|
|
3976
|
-
authorId: z.z.string().refine(
|
|
3975
|
+
baseSha: z.z.string().refine(_p => true),
|
|
3976
|
+
authorId: z.z.string().refine(_p => true).nullable(),
|
|
3977
3977
|
createdAt: z.z.string().datetime(),
|
|
3978
3978
|
coreVersion: z.z.string().nullable(),
|
|
3979
3979
|
sessionId: z.z.string().nullable()
|
|
3980
3980
|
});
|
|
3981
3981
|
const FSPatchBase = z.z.object({
|
|
3982
|
-
baseSha: z.z.string().refine(
|
|
3982
|
+
baseSha: z.z.string().refine(_p => true),
|
|
3983
3983
|
timestamp: z.z.string().datetime()
|
|
3984
3984
|
});
|
|
3985
3985
|
|
|
@@ -4753,7 +4753,6 @@ async function acquirePatchLock(lockFilePath, options) {
|
|
|
4753
4753
|
message: `Could not create the directory for ${lockFilePath}: ${err instanceof Error ? err.message : "unknown error"}`
|
|
4754
4754
|
};
|
|
4755
4755
|
}
|
|
4756
|
-
let lastSeenHolder = null;
|
|
4757
4756
|
for (;;) {
|
|
4758
4757
|
const acquiredAt = now();
|
|
4759
4758
|
const info = {
|
|
@@ -4785,7 +4784,7 @@ async function acquirePatchLock(lockFilePath, options) {
|
|
|
4785
4784
|
// Released between the failed create and the read. Go straight round again.
|
|
4786
4785
|
continue;
|
|
4787
4786
|
}
|
|
4788
|
-
lastSeenHolder = parsePatchLockInfo(rawBefore);
|
|
4787
|
+
const lastSeenHolder = parsePatchLockInfo(rawBefore);
|
|
4789
4788
|
if (isExpired(lastSeenHolder, now())) {
|
|
4790
4789
|
// Read twice across a poll interval before removing it: an unchanged stale
|
|
4791
4790
|
// file is one nobody is renewing, and requiring the second read is what
|
|
@@ -9782,15 +9781,12 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
9782
9781
|
// 3) the benefit an attacker would get is an image that is not yet published (i.e. most cases: not very interesting)
|
|
9783
9782
|
// Thus: attack surface + ease of attack + benefit = low probability of attack
|
|
9784
9783
|
// If we couldn't argue that patch ids are secret enough, then this would be a problem.
|
|
9785
|
-
let cacheControl;
|
|
9786
9784
|
let fileBuffer;
|
|
9787
9785
|
let mimeType;
|
|
9788
9786
|
const remote = query.remote === "true";
|
|
9789
9787
|
if (query.patch_id) {
|
|
9790
9788
|
fileBuffer = await serverOps.getBase64EncodedBinaryFileFromPatch(filePath, query.patch_id, remote);
|
|
9791
9789
|
mimeType = core.Internal.filenameToMimeType(filePath);
|
|
9792
|
-
// TODO: reenable this:
|
|
9793
|
-
// cacheControl = "public, max-age=20000, immutable";
|
|
9794
9790
|
} else {
|
|
9795
9791
|
if (serverOps instanceof ValOpsHttp && remote) {
|
|
9796
9792
|
console.error(`Remote file: ${filePath} requested without patch id. This is most likely a bug in Val.`);
|
|
@@ -9803,7 +9799,12 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
9803
9799
|
headers: {
|
|
9804
9800
|
// TODO: we could use ETag and return 304 instead
|
|
9805
9801
|
"Content-Type": mimeType || "application/octet-stream",
|
|
9806
|
-
|
|
9802
|
+
// TODO: a file requested with a patch_id is immutable for that
|
|
9803
|
+
// patch, so it could be served "public, max-age=20000, immutable"
|
|
9804
|
+
// instead. There used to be a `cacheControl` variable here for
|
|
9805
|
+
// that, but its only assignment was commented out, so every
|
|
9806
|
+
// response has always taken the revalidate branch.
|
|
9807
|
+
"Cache-Control": "public, max-age=0, must-revalidate"
|
|
9807
9808
|
},
|
|
9808
9809
|
body: bufferToReadableStream(fileBuffer)
|
|
9809
9810
|
};
|
|
@@ -10705,9 +10706,7 @@ async function extractImageMetadata(filename, input) {
|
|
|
10705
10706
|
mimeType
|
|
10706
10707
|
};
|
|
10707
10708
|
}
|
|
10708
|
-
async function extractFileMetadata(filename,
|
|
10709
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10710
|
-
_input // TODO: use buffer to determine mimetype
|
|
10709
|
+
async function extractFileMetadata(filename, _input // TODO: use buffer to determine mimetype
|
|
10711
10710
|
) {
|
|
10712
10711
|
let mimeType = core.Internal.filenameToMimeType(filename);
|
|
10713
10712
|
if (!mimeType) {
|
|
@@ -11747,7 +11746,6 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
11747
11746
|
// schema above already established that this IS media.
|
|
11748
11747
|
const actualRemoteFileSource = resolvedRemoteFileAtSourcePath.source;
|
|
11749
11748
|
const fileSourceMetadata = actualRemoteFileSource && typeof actualRemoteFileSource === "object" && "path" in actualRemoteFileSource ? (() => {
|
|
11750
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11751
11749
|
const {
|
|
11752
11750
|
path: _path,
|
|
11753
11751
|
...metadata
|
|
@@ -12163,7 +12161,9 @@ async function evalValConfigFile(projectRoot, configFileName) {
|
|
|
12163
12161
|
if (isFileNotFound(err)) {
|
|
12164
12162
|
return null;
|
|
12165
12163
|
}
|
|
12166
|
-
throw Error(`Could not read Val config file at path: '${valConfigPath}': ${err instanceof Error ? err.message : String(err)}
|
|
12164
|
+
throw Error(`Could not read Val config file at path: '${valConfigPath}': ${err instanceof Error ? err.message : String(err)}`, {
|
|
12165
|
+
cause: err
|
|
12166
|
+
});
|
|
12167
12167
|
}
|
|
12168
12168
|
if (!code.trim()) {
|
|
12169
12169
|
return null;
|
|
@@ -3648,7 +3648,7 @@ class JsonEntryFilesFingerprint {
|
|
|
3648
3648
|
if (cached && cached.moduleMtimeMs === moduleMtimeMs) {
|
|
3649
3649
|
return cached.entryFilePaths;
|
|
3650
3650
|
}
|
|
3651
|
-
let entryFilePaths
|
|
3651
|
+
let entryFilePaths;
|
|
3652
3652
|
try {
|
|
3653
3653
|
const contents = fs__default["default"].readFileSync(absModulePath, "utf-8");
|
|
3654
3654
|
entryFilePaths = findJsonEntryFilePathsInSource(moduleFilePath, ts__default["default"].createSourceFile(absModulePath, contents, ts__default["default"].ScriptTarget.ES2015));
|
|
@@ -3972,14 +3972,14 @@ const FSPatch = z.z.object({
|
|
|
3972
3972
|
path: z.z.string().refine(p => p.startsWith("/") && p.includes(".val."), "Path is not valid. Must start with '/' and include '.val.'"),
|
|
3973
3973
|
patch: internal.Patch,
|
|
3974
3974
|
patchId: z.z.string(),
|
|
3975
|
-
baseSha: z.z.string().refine(
|
|
3976
|
-
authorId: z.z.string().refine(
|
|
3975
|
+
baseSha: z.z.string().refine(_p => true),
|
|
3976
|
+
authorId: z.z.string().refine(_p => true).nullable(),
|
|
3977
3977
|
createdAt: z.z.string().datetime(),
|
|
3978
3978
|
coreVersion: z.z.string().nullable(),
|
|
3979
3979
|
sessionId: z.z.string().nullable()
|
|
3980
3980
|
});
|
|
3981
3981
|
const FSPatchBase = z.z.object({
|
|
3982
|
-
baseSha: z.z.string().refine(
|
|
3982
|
+
baseSha: z.z.string().refine(_p => true),
|
|
3983
3983
|
timestamp: z.z.string().datetime()
|
|
3984
3984
|
});
|
|
3985
3985
|
|
|
@@ -4753,7 +4753,6 @@ async function acquirePatchLock(lockFilePath, options) {
|
|
|
4753
4753
|
message: `Could not create the directory for ${lockFilePath}: ${err instanceof Error ? err.message : "unknown error"}`
|
|
4754
4754
|
};
|
|
4755
4755
|
}
|
|
4756
|
-
let lastSeenHolder = null;
|
|
4757
4756
|
for (;;) {
|
|
4758
4757
|
const acquiredAt = now();
|
|
4759
4758
|
const info = {
|
|
@@ -4785,7 +4784,7 @@ async function acquirePatchLock(lockFilePath, options) {
|
|
|
4785
4784
|
// Released between the failed create and the read. Go straight round again.
|
|
4786
4785
|
continue;
|
|
4787
4786
|
}
|
|
4788
|
-
lastSeenHolder = parsePatchLockInfo(rawBefore);
|
|
4787
|
+
const lastSeenHolder = parsePatchLockInfo(rawBefore);
|
|
4789
4788
|
if (isExpired(lastSeenHolder, now())) {
|
|
4790
4789
|
// Read twice across a poll interval before removing it: an unchanged stale
|
|
4791
4790
|
// file is one nobody is renewing, and requiring the second read is what
|
|
@@ -9782,15 +9781,12 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
9782
9781
|
// 3) the benefit an attacker would get is an image that is not yet published (i.e. most cases: not very interesting)
|
|
9783
9782
|
// Thus: attack surface + ease of attack + benefit = low probability of attack
|
|
9784
9783
|
// If we couldn't argue that patch ids are secret enough, then this would be a problem.
|
|
9785
|
-
let cacheControl;
|
|
9786
9784
|
let fileBuffer;
|
|
9787
9785
|
let mimeType;
|
|
9788
9786
|
const remote = query.remote === "true";
|
|
9789
9787
|
if (query.patch_id) {
|
|
9790
9788
|
fileBuffer = await serverOps.getBase64EncodedBinaryFileFromPatch(filePath, query.patch_id, remote);
|
|
9791
9789
|
mimeType = core.Internal.filenameToMimeType(filePath);
|
|
9792
|
-
// TODO: reenable this:
|
|
9793
|
-
// cacheControl = "public, max-age=20000, immutable";
|
|
9794
9790
|
} else {
|
|
9795
9791
|
if (serverOps instanceof ValOpsHttp && remote) {
|
|
9796
9792
|
console.error(`Remote file: ${filePath} requested without patch id. This is most likely a bug in Val.`);
|
|
@@ -9803,7 +9799,12 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
9803
9799
|
headers: {
|
|
9804
9800
|
// TODO: we could use ETag and return 304 instead
|
|
9805
9801
|
"Content-Type": mimeType || "application/octet-stream",
|
|
9806
|
-
|
|
9802
|
+
// TODO: a file requested with a patch_id is immutable for that
|
|
9803
|
+
// patch, so it could be served "public, max-age=20000, immutable"
|
|
9804
|
+
// instead. There used to be a `cacheControl` variable here for
|
|
9805
|
+
// that, but its only assignment was commented out, so every
|
|
9806
|
+
// response has always taken the revalidate branch.
|
|
9807
|
+
"Cache-Control": "public, max-age=0, must-revalidate"
|
|
9807
9808
|
},
|
|
9808
9809
|
body: bufferToReadableStream(fileBuffer)
|
|
9809
9810
|
};
|
|
@@ -10705,9 +10706,7 @@ async function extractImageMetadata(filename, input) {
|
|
|
10705
10706
|
mimeType
|
|
10706
10707
|
};
|
|
10707
10708
|
}
|
|
10708
|
-
async function extractFileMetadata(filename,
|
|
10709
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10710
|
-
_input // TODO: use buffer to determine mimetype
|
|
10709
|
+
async function extractFileMetadata(filename, _input // TODO: use buffer to determine mimetype
|
|
10711
10710
|
) {
|
|
10712
10711
|
let mimeType = core.Internal.filenameToMimeType(filename);
|
|
10713
10712
|
if (!mimeType) {
|
|
@@ -11747,7 +11746,6 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
11747
11746
|
// schema above already established that this IS media.
|
|
11748
11747
|
const actualRemoteFileSource = resolvedRemoteFileAtSourcePath.source;
|
|
11749
11748
|
const fileSourceMetadata = actualRemoteFileSource && typeof actualRemoteFileSource === "object" && "path" in actualRemoteFileSource ? (() => {
|
|
11750
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11751
11749
|
const {
|
|
11752
11750
|
path: _path,
|
|
11753
11751
|
...metadata
|
|
@@ -12163,7 +12161,9 @@ async function evalValConfigFile(projectRoot, configFileName) {
|
|
|
12163
12161
|
if (isFileNotFound(err)) {
|
|
12164
12162
|
return null;
|
|
12165
12163
|
}
|
|
12166
|
-
throw Error(`Could not read Val config file at path: '${valConfigPath}': ${err instanceof Error ? err.message : String(err)}
|
|
12164
|
+
throw Error(`Could not read Val config file at path: '${valConfigPath}': ${err instanceof Error ? err.message : String(err)}`, {
|
|
12165
|
+
cause: err
|
|
12166
|
+
});
|
|
12167
12167
|
}
|
|
12168
12168
|
if (!code.trim()) {
|
|
12169
12169
|
return null;
|
|
@@ -3614,7 +3614,7 @@ class JsonEntryFilesFingerprint {
|
|
|
3614
3614
|
if (cached && cached.moduleMtimeMs === moduleMtimeMs) {
|
|
3615
3615
|
return cached.entryFilePaths;
|
|
3616
3616
|
}
|
|
3617
|
-
let entryFilePaths
|
|
3617
|
+
let entryFilePaths;
|
|
3618
3618
|
try {
|
|
3619
3619
|
const contents = fs.readFileSync(absModulePath, "utf-8");
|
|
3620
3620
|
entryFilePaths = findJsonEntryFilePathsInSource(moduleFilePath, ts.createSourceFile(absModulePath, contents, ts.ScriptTarget.ES2015));
|
|
@@ -3938,14 +3938,14 @@ const FSPatch = z.object({
|
|
|
3938
3938
|
path: z.string().refine(p => p.startsWith("/") && p.includes(".val."), "Path is not valid. Must start with '/' and include '.val.'"),
|
|
3939
3939
|
patch: Patch,
|
|
3940
3940
|
patchId: z.string(),
|
|
3941
|
-
baseSha: z.string().refine(
|
|
3942
|
-
authorId: z.string().refine(
|
|
3941
|
+
baseSha: z.string().refine(_p => true),
|
|
3942
|
+
authorId: z.string().refine(_p => true).nullable(),
|
|
3943
3943
|
createdAt: z.string().datetime(),
|
|
3944
3944
|
coreVersion: z.string().nullable(),
|
|
3945
3945
|
sessionId: z.string().nullable()
|
|
3946
3946
|
});
|
|
3947
3947
|
const FSPatchBase = z.object({
|
|
3948
|
-
baseSha: z.string().refine(
|
|
3948
|
+
baseSha: z.string().refine(_p => true),
|
|
3949
3949
|
timestamp: z.string().datetime()
|
|
3950
3950
|
});
|
|
3951
3951
|
|
|
@@ -4719,7 +4719,6 @@ async function acquirePatchLock(lockFilePath, options) {
|
|
|
4719
4719
|
message: `Could not create the directory for ${lockFilePath}: ${err instanceof Error ? err.message : "unknown error"}`
|
|
4720
4720
|
};
|
|
4721
4721
|
}
|
|
4722
|
-
let lastSeenHolder = null;
|
|
4723
4722
|
for (;;) {
|
|
4724
4723
|
const acquiredAt = now();
|
|
4725
4724
|
const info = {
|
|
@@ -4751,7 +4750,7 @@ async function acquirePatchLock(lockFilePath, options) {
|
|
|
4751
4750
|
// Released between the failed create and the read. Go straight round again.
|
|
4752
4751
|
continue;
|
|
4753
4752
|
}
|
|
4754
|
-
lastSeenHolder = parsePatchLockInfo(rawBefore);
|
|
4753
|
+
const lastSeenHolder = parsePatchLockInfo(rawBefore);
|
|
4755
4754
|
if (isExpired(lastSeenHolder, now())) {
|
|
4756
4755
|
// Read twice across a poll interval before removing it: an unchanged stale
|
|
4757
4756
|
// file is one nobody is renewing, and requiring the second read is what
|
|
@@ -9748,15 +9747,12 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
9748
9747
|
// 3) the benefit an attacker would get is an image that is not yet published (i.e. most cases: not very interesting)
|
|
9749
9748
|
// Thus: attack surface + ease of attack + benefit = low probability of attack
|
|
9750
9749
|
// If we couldn't argue that patch ids are secret enough, then this would be a problem.
|
|
9751
|
-
let cacheControl;
|
|
9752
9750
|
let fileBuffer;
|
|
9753
9751
|
let mimeType;
|
|
9754
9752
|
const remote = query.remote === "true";
|
|
9755
9753
|
if (query.patch_id) {
|
|
9756
9754
|
fileBuffer = await serverOps.getBase64EncodedBinaryFileFromPatch(filePath, query.patch_id, remote);
|
|
9757
9755
|
mimeType = Internal.filenameToMimeType(filePath);
|
|
9758
|
-
// TODO: reenable this:
|
|
9759
|
-
// cacheControl = "public, max-age=20000, immutable";
|
|
9760
9756
|
} else {
|
|
9761
9757
|
if (serverOps instanceof ValOpsHttp && remote) {
|
|
9762
9758
|
console.error(`Remote file: ${filePath} requested without patch id. This is most likely a bug in Val.`);
|
|
@@ -9769,7 +9765,12 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
9769
9765
|
headers: {
|
|
9770
9766
|
// TODO: we could use ETag and return 304 instead
|
|
9771
9767
|
"Content-Type": mimeType || "application/octet-stream",
|
|
9772
|
-
|
|
9768
|
+
// TODO: a file requested with a patch_id is immutable for that
|
|
9769
|
+
// patch, so it could be served "public, max-age=20000, immutable"
|
|
9770
|
+
// instead. There used to be a `cacheControl` variable here for
|
|
9771
|
+
// that, but its only assignment was commented out, so every
|
|
9772
|
+
// response has always taken the revalidate branch.
|
|
9773
|
+
"Cache-Control": "public, max-age=0, must-revalidate"
|
|
9773
9774
|
},
|
|
9774
9775
|
body: bufferToReadableStream(fileBuffer)
|
|
9775
9776
|
};
|
|
@@ -10671,9 +10672,7 @@ async function extractImageMetadata(filename, input) {
|
|
|
10671
10672
|
mimeType
|
|
10672
10673
|
};
|
|
10673
10674
|
}
|
|
10674
|
-
async function extractFileMetadata(filename,
|
|
10675
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10676
|
-
_input // TODO: use buffer to determine mimetype
|
|
10675
|
+
async function extractFileMetadata(filename, _input // TODO: use buffer to determine mimetype
|
|
10677
10676
|
) {
|
|
10678
10677
|
let mimeType = Internal.filenameToMimeType(filename);
|
|
10679
10678
|
if (!mimeType) {
|
|
@@ -11713,7 +11712,6 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
11713
11712
|
// schema above already established that this IS media.
|
|
11714
11713
|
const actualRemoteFileSource = resolvedRemoteFileAtSourcePath.source;
|
|
11715
11714
|
const fileSourceMetadata = actualRemoteFileSource && typeof actualRemoteFileSource === "object" && "path" in actualRemoteFileSource ? (() => {
|
|
11716
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11717
11715
|
const {
|
|
11718
11716
|
path: _path,
|
|
11719
11717
|
...metadata
|
|
@@ -12129,7 +12127,9 @@ async function evalValConfigFile(projectRoot, configFileName) {
|
|
|
12129
12127
|
if (isFileNotFound(err)) {
|
|
12130
12128
|
return null;
|
|
12131
12129
|
}
|
|
12132
|
-
throw Error(`Could not read Val config file at path: '${valConfigPath}': ${err instanceof Error ? err.message : String(err)}
|
|
12130
|
+
throw Error(`Could not read Val config file at path: '${valConfigPath}': ${err instanceof Error ? err.message : String(err)}`, {
|
|
12131
|
+
cause: err
|
|
12132
|
+
});
|
|
12133
12133
|
}
|
|
12134
12134
|
if (!code.trim()) {
|
|
12135
12135
|
return null;
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"./package.json": "./package.json"
|
|
17
17
|
},
|
|
18
18
|
"types": "dist/valbuild-server.cjs.d.ts",
|
|
19
|
-
"version": "0.
|
|
19
|
+
"version": "0.108.0",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@prettier/sync": "^0.6.1",
|
|
22
22
|
"@types/jest": "^30.0.0"
|
|
@@ -24,17 +24,17 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"chokidar": "^5.0.0",
|
|
26
26
|
"image-size": "^2.0.2",
|
|
27
|
-
"minimatch": "^10.2.
|
|
27
|
+
"minimatch": "^10.2.6",
|
|
28
28
|
"sucrase": "^3.35.1",
|
|
29
|
-
"typescript": "^
|
|
30
|
-
"zod": "^4.3
|
|
29
|
+
"typescript": "^6.0.3",
|
|
30
|
+
"zod": "^4.4.3",
|
|
31
31
|
"zod-validation-error": "^5.0.0",
|
|
32
32
|
"@valbuild/core": "0.106.0",
|
|
33
|
-
"@valbuild/shared": "0.
|
|
34
|
-
"@valbuild/ui": "0.
|
|
33
|
+
"@valbuild/shared": "0.108.0",
|
|
34
|
+
"@valbuild/ui": "0.108.0"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
|
-
"node": "
|
|
37
|
+
"node": "^20.19.0 || >=22"
|
|
38
38
|
},
|
|
39
39
|
"files": [
|
|
40
40
|
"dist"
|