@valbuild/server 0.97.0 → 0.97.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/valbuild-server.cjs.dev.js +70 -289
- package/dist/valbuild-server.cjs.prod.js +70 -289
- package/dist/valbuild-server.esm.js +72 -291
- package/package.json +4 -4
|
@@ -1289,6 +1289,11 @@ export default new Proxy({}, {
|
|
|
1289
1289
|
value: "export const ValApp = new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'ValApp' in this file`) } } } )"
|
|
1290
1290
|
};
|
|
1291
1291
|
}
|
|
1292
|
+
if (modulePath.includes("/ValModulesClient")) {
|
|
1293
|
+
return {
|
|
1294
|
+
value: "export const ValModulesClient = new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'ValModulesClient' in this file`) } } } ); export const useRegisterValModules = () => { throw new Error(`Cannot use 'useRegisterValModules' in this type of file`) };"
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1292
1297
|
return {
|
|
1293
1298
|
value: moduleLoader.getModule(modulePath)
|
|
1294
1299
|
};
|
|
@@ -1359,6 +1364,11 @@ export default new Proxy({}, {
|
|
|
1359
1364
|
value: requestedName
|
|
1360
1365
|
};
|
|
1361
1366
|
}
|
|
1367
|
+
if (requestedName.includes("/ValModulesClient")) {
|
|
1368
|
+
return {
|
|
1369
|
+
value: requestedName
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1362
1372
|
const modulePath = moduleLoader.resolveModulePath(baseModuleName, requestedName);
|
|
1363
1373
|
return {
|
|
1364
1374
|
value: modulePath
|
|
@@ -1493,7 +1503,6 @@ function encodeJwt(payload, sessionKey) {
|
|
|
1493
1503
|
}
|
|
1494
1504
|
|
|
1495
1505
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1496
|
-
const textEncoder$2 = new TextEncoder();
|
|
1497
1506
|
const jsonOps = new patch.JSONOps();
|
|
1498
1507
|
const tsOps = new TSOps(document => {
|
|
1499
1508
|
return fp.pipe(analyzeValModule(document), fp.result.map(({
|
|
@@ -1525,47 +1534,6 @@ class ValOps {
|
|
|
1525
1534
|
this.configSha = null;
|
|
1526
1535
|
this.modulesErrors = null;
|
|
1527
1536
|
}
|
|
1528
|
-
hash(input) {
|
|
1529
|
-
if (typeof input === "object") {
|
|
1530
|
-
return this.hashObject(input);
|
|
1531
|
-
}
|
|
1532
|
-
return core.Internal.getSHA256Hash(textEncoder$2.encode(input));
|
|
1533
|
-
}
|
|
1534
|
-
hashObject(obj) {
|
|
1535
|
-
const collector = [];
|
|
1536
|
-
this.collectObjectRecursive(obj, collector);
|
|
1537
|
-
return core.Internal.getSHA256Hash(textEncoder$2.encode(collector.join("")));
|
|
1538
|
-
}
|
|
1539
|
-
collectObjectRecursive(item, collector) {
|
|
1540
|
-
if (typeof item === "string") {
|
|
1541
|
-
collector.push(`"`, item, `"`);
|
|
1542
|
-
return;
|
|
1543
|
-
} else if (typeof item === "number") {
|
|
1544
|
-
collector.push(item.toString());
|
|
1545
|
-
return;
|
|
1546
|
-
} else if (typeof item === "object") {
|
|
1547
|
-
if (Array.isArray(item)) {
|
|
1548
|
-
collector.push("[");
|
|
1549
|
-
for (let i = 0; i < item.length; i++) {
|
|
1550
|
-
this.collectObjectRecursive(item[i], collector);
|
|
1551
|
-
if (i !== item.length - 1) collector.push(",");
|
|
1552
|
-
}
|
|
1553
|
-
collector.push("]");
|
|
1554
|
-
} else {
|
|
1555
|
-
collector.push("{");
|
|
1556
|
-
const keys = Object.keys(item).sort();
|
|
1557
|
-
keys.forEach((key, i) => {
|
|
1558
|
-
collector.push(`"${key}":`);
|
|
1559
|
-
this.collectObjectRecursive(item[key], collector);
|
|
1560
|
-
if (i !== keys.length - 1) collector.push(",");
|
|
1561
|
-
});
|
|
1562
|
-
collector.push("}");
|
|
1563
|
-
}
|
|
1564
|
-
return;
|
|
1565
|
-
} else {
|
|
1566
|
-
console.warn("Unknown type encountered when hashing object", typeof item, item);
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
1537
|
|
|
1570
1538
|
// #region stat
|
|
1571
1539
|
/**
|
|
@@ -1581,93 +1549,23 @@ class ValOps {
|
|
|
1581
1549
|
// #region initTree
|
|
1582
1550
|
async initSources() {
|
|
1583
1551
|
if (this.baseSha === null || this.sourcesSha === null || this.configSha === null || this.schemaSha === null || this.sources === null || this.schemas === null || this.modulesErrors === null) {
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1552
|
+
const extracted = await core.extractValModules(this.valModules);
|
|
1553
|
+
this.sources = extracted.sources;
|
|
1554
|
+
this.schemas = extracted.schemas;
|
|
1555
|
+
this.baseSha = extracted.baseSha;
|
|
1556
|
+
this.schemaSha = extracted.schemaSha;
|
|
1557
|
+
this.sourcesSha = extracted.sourcesSha;
|
|
1558
|
+
this.configSha = extracted.configSha;
|
|
1559
|
+
this.modulesErrors = extracted.moduleErrors;
|
|
1560
|
+
return {
|
|
1561
|
+
baseSha: this.baseSha,
|
|
1562
|
+
schemaSha: this.schemaSha,
|
|
1563
|
+
sourcesSha: this.sourcesSha,
|
|
1564
|
+
configSha: this.configSha,
|
|
1565
|
+
sources: extracted.sources,
|
|
1566
|
+
schemas: extracted.schemas,
|
|
1567
|
+
moduleErrors: extracted.moduleErrors
|
|
1590
1568
|
};
|
|
1591
|
-
const currentSources = {};
|
|
1592
|
-
const currentSchemas = {};
|
|
1593
|
-
const configSha = this.hash(JSON.stringify(this.valModules.config));
|
|
1594
|
-
let sourcesSha = "";
|
|
1595
|
-
let baseSha = configSha;
|
|
1596
|
-
let schemaSha = configSha;
|
|
1597
|
-
for (let moduleIdx = 0; moduleIdx < this.valModules.modules.length; moduleIdx++) {
|
|
1598
|
-
const module = this.valModules.modules[moduleIdx];
|
|
1599
|
-
if (!module.def) {
|
|
1600
|
-
addModuleError("val.modules is missing 'def' property", moduleIdx);
|
|
1601
|
-
continue;
|
|
1602
|
-
}
|
|
1603
|
-
if (typeof module.def !== "function") {
|
|
1604
|
-
addModuleError("val.modules 'def' property is not a function", moduleIdx);
|
|
1605
|
-
continue;
|
|
1606
|
-
}
|
|
1607
|
-
await module.def().then(value => {
|
|
1608
|
-
if (!value) {
|
|
1609
|
-
addModuleError(`val.modules 'def' did not return a value`, moduleIdx);
|
|
1610
|
-
return;
|
|
1611
|
-
}
|
|
1612
|
-
if (!value.default) {
|
|
1613
|
-
addModuleError(`val.modules 'def' did not return a default export`, moduleIdx);
|
|
1614
|
-
return;
|
|
1615
|
-
}
|
|
1616
|
-
const path = core.Internal.getValPath(value.default);
|
|
1617
|
-
if (path === undefined) {
|
|
1618
|
-
addModuleError(`path is undefined`, moduleIdx);
|
|
1619
|
-
return;
|
|
1620
|
-
}
|
|
1621
|
-
const schema = core.Internal.getSchema(value.default);
|
|
1622
|
-
if (schema === undefined) {
|
|
1623
|
-
addModuleError(`schema in path '${path}' is undefined`, moduleIdx, path);
|
|
1624
|
-
return;
|
|
1625
|
-
}
|
|
1626
|
-
if (!(schema instanceof core.Schema)) {
|
|
1627
|
-
addModuleError(`schema in path '${path}' is not an instance of Schema`, moduleIdx, path);
|
|
1628
|
-
return;
|
|
1629
|
-
}
|
|
1630
|
-
if (typeof schema["executeSerialize"] !== "function") {
|
|
1631
|
-
addModuleError(`schema.serialize in path '${path}' is not a function`, moduleIdx, path);
|
|
1632
|
-
return;
|
|
1633
|
-
}
|
|
1634
|
-
const source = core.Internal.getSource(value.default);
|
|
1635
|
-
if (source === undefined) {
|
|
1636
|
-
addModuleError(`source in ${path} is undefined`, moduleIdx, path);
|
|
1637
|
-
return;
|
|
1638
|
-
}
|
|
1639
|
-
let serializedSchema;
|
|
1640
|
-
try {
|
|
1641
|
-
serializedSchema = schema["executeSerialize"]();
|
|
1642
|
-
} catch (e) {
|
|
1643
|
-
const message = e instanceof Error ? e.message : JSON.stringify(e);
|
|
1644
|
-
addModuleError(`Could not serialize module: '${path}'. Error: ${message}`, moduleIdx, path);
|
|
1645
|
-
return;
|
|
1646
|
-
}
|
|
1647
|
-
const pathM = path;
|
|
1648
|
-
currentSources[pathM] = source;
|
|
1649
|
-
currentSchemas[pathM] = schema;
|
|
1650
|
-
// make sure the checks above is enough that this does not fail - even if val modules are not set up correctly
|
|
1651
|
-
sourcesSha = this.hash(sourcesSha + JSON.stringify({
|
|
1652
|
-
path,
|
|
1653
|
-
source
|
|
1654
|
-
}));
|
|
1655
|
-
baseSha = this.hash(baseSha + JSON.stringify({
|
|
1656
|
-
path,
|
|
1657
|
-
schema: serializedSchema,
|
|
1658
|
-
source,
|
|
1659
|
-
modulesErrors: currentModulesErrors
|
|
1660
|
-
}));
|
|
1661
|
-
schemaSha = this.hash(schemaSha + JSON.stringify(serializedSchema));
|
|
1662
|
-
});
|
|
1663
|
-
}
|
|
1664
|
-
this.sources = currentSources;
|
|
1665
|
-
this.schemas = currentSchemas;
|
|
1666
|
-
this.baseSha = baseSha;
|
|
1667
|
-
this.schemaSha = schemaSha;
|
|
1668
|
-
this.sourcesSha = sourcesSha;
|
|
1669
|
-
this.configSha = configSha;
|
|
1670
|
-
this.modulesErrors = currentModulesErrors;
|
|
1671
1569
|
}
|
|
1672
1570
|
return {
|
|
1673
1571
|
baseSha: this.baseSha,
|
|
@@ -1847,79 +1745,6 @@ class ValOps {
|
|
|
1847
1745
|
|
|
1848
1746
|
// #region validateSources
|
|
1849
1747
|
async validateSources(schemas, sources, patchesByModule) {
|
|
1850
|
-
const checkKeyIsValid = async (key, sourcePath) => {
|
|
1851
|
-
var _schemas$moduleFilePa;
|
|
1852
|
-
const [moduleFilePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
1853
|
-
const keyOfModuleSource = sources[moduleFilePath];
|
|
1854
|
-
const keyOfModuleSchema = (_schemas$moduleFilePa = schemas[moduleFilePath]) === null || _schemas$moduleFilePa === void 0 ? void 0 : _schemas$moduleFilePa["executeSerialize"]();
|
|
1855
|
-
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
1856
|
-
return {
|
|
1857
|
-
error: true,
|
|
1858
|
-
message: `Expected key at ${sourcePath} to be of type 'record'`
|
|
1859
|
-
};
|
|
1860
|
-
}
|
|
1861
|
-
if (keyOfModuleSource && typeof keyOfModuleSource === "object" && key in keyOfModuleSource) {
|
|
1862
|
-
return {
|
|
1863
|
-
error: false
|
|
1864
|
-
};
|
|
1865
|
-
}
|
|
1866
|
-
if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
|
|
1867
|
-
return {
|
|
1868
|
-
error: true,
|
|
1869
|
-
message: `Expected ${sourcePath} to be a truthy object`
|
|
1870
|
-
};
|
|
1871
|
-
}
|
|
1872
|
-
return {
|
|
1873
|
-
error: true,
|
|
1874
|
-
message: `Key '${key}' does not exist in ${sourcePath}.`
|
|
1875
|
-
};
|
|
1876
|
-
};
|
|
1877
|
-
const checkRouteIsValid = async (route, includePattern, excludePattern) => {
|
|
1878
|
-
// Find all router modules (record schemas with router property)
|
|
1879
|
-
const routerModules = [];
|
|
1880
|
-
for (const [moduleFilePath, schema] of Object.entries(schemas)) {
|
|
1881
|
-
const serializedSchema = schema["executeSerialize"]();
|
|
1882
|
-
if (serializedSchema.type === "record" && serializedSchema.router) {
|
|
1883
|
-
const source = sources[moduleFilePath];
|
|
1884
|
-
if (source && typeof source === "object") {
|
|
1885
|
-
routerModules.push({
|
|
1886
|
-
path: moduleFilePath,
|
|
1887
|
-
routes: Object.keys(source)
|
|
1888
|
-
});
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
if (routerModules.length === 0) {
|
|
1893
|
-
return {
|
|
1894
|
-
error: true,
|
|
1895
|
-
message: `No router modules found. Route validation requires at least one s.record().router() module.`
|
|
1896
|
-
};
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
// Check if route exists in any router module
|
|
1900
|
-
const allRoutes = routerModules.flatMap(m => m.routes);
|
|
1901
|
-
const routeExists = allRoutes.includes(route);
|
|
1902
|
-
if (!routeExists) {
|
|
1903
|
-
// Filter routes by include/exclude patterns for suggestions
|
|
1904
|
-
const validRoutes = internal.filterRoutesByPatterns(allRoutes, includePattern, excludePattern);
|
|
1905
|
-
return {
|
|
1906
|
-
error: true,
|
|
1907
|
-
message: `Route '${route}' does not exist in any router module. Available routes: ${validRoutes.slice(0, 10).join(", ")}${validRoutes.length > 10 ? "..." : ""}`
|
|
1908
|
-
};
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
// Validate against include/exclude patterns
|
|
1912
|
-
const patternValidation = internal.validateRoutePatterns(route, includePattern, excludePattern);
|
|
1913
|
-
if (!patternValidation.valid) {
|
|
1914
|
-
return {
|
|
1915
|
-
error: true,
|
|
1916
|
-
message: patternValidation.message
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
return {
|
|
1920
|
-
error: false
|
|
1921
|
-
};
|
|
1922
|
-
};
|
|
1923
1748
|
const errors = {};
|
|
1924
1749
|
const files = {};
|
|
1925
1750
|
const remoteFiles = {};
|
|
@@ -1927,15 +1752,27 @@ class ValOps {
|
|
|
1927
1752
|
// Build a map of gallery directory → [ModuleFilePath, ...] across ALL modules
|
|
1928
1753
|
// (must include all modules, not just those being validated, since conflicts can come from any module)
|
|
1929
1754
|
const galleryDirectoryToModules = new Map();
|
|
1755
|
+
// Build a schema/source snapshot so the shared resolver can cross-reference
|
|
1756
|
+
// keyof:check-keys and router:check-route against every module's data.
|
|
1757
|
+
const snapshot = {
|
|
1758
|
+
schemas: {},
|
|
1759
|
+
sources: {}
|
|
1760
|
+
};
|
|
1930
1761
|
for (const [moduleFilePathS, schema] of entries) {
|
|
1762
|
+
const moduleFilePath = moduleFilePathS;
|
|
1931
1763
|
const serialized = schema["executeSerialize"]();
|
|
1764
|
+
snapshot.schemas[moduleFilePath] = serialized;
|
|
1765
|
+
const sourceForModule = sources[moduleFilePath];
|
|
1766
|
+
if (sourceForModule !== undefined) {
|
|
1767
|
+
snapshot.sources[moduleFilePath] = sourceForModule;
|
|
1768
|
+
}
|
|
1932
1769
|
if (serialized.type === "record" && serialized.mediaType && serialized.directory) {
|
|
1933
1770
|
const dir = serialized.directory;
|
|
1934
1771
|
const existing = galleryDirectoryToModules.get(dir);
|
|
1935
1772
|
if (existing) {
|
|
1936
|
-
existing.push(
|
|
1773
|
+
existing.push(moduleFilePath);
|
|
1937
1774
|
} else {
|
|
1938
|
-
galleryDirectoryToModules.set(dir, [
|
|
1775
|
+
galleryDirectoryToModules.set(dir, [moduleFilePath]);
|
|
1939
1776
|
}
|
|
1940
1777
|
}
|
|
1941
1778
|
}
|
|
@@ -1993,78 +1830,12 @@ class ValOps {
|
|
|
1993
1830
|
}
|
|
1994
1831
|
} else if ((_validationError$fixe = validationError.fixes) !== null && _validationError$fixe !== void 0 && _validationError$fixe.includes("image:check-remote") || (_validationError$fixe2 = validationError.fixes) !== null && _validationError$fixe2 !== void 0 && _validationError$fixe2.includes("file:check-remote")) {
|
|
1995
1832
|
remoteFiles[sourcePath] = validationError.value;
|
|
1996
|
-
} else if ((_validationError$fixe3 = validationError.fixes) !== null && _validationError$fixe3 !== void 0 && _validationError$fixe3.includes("keyof:check-keys")) {
|
|
1997
|
-
const
|
|
1998
|
-
if (
|
|
1999
|
-
addError(
|
|
2000
|
-
message: `Could not find a value for keyOf at ${sourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2001
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2002
|
-
typeError: true
|
|
2003
|
-
});
|
|
2004
|
-
} else {
|
|
2005
|
-
if (typeof validationError.value !== "object") {
|
|
2006
|
-
addError({
|
|
2007
|
-
message: `Expected keyOf validation error to have a 'value' property of type 'object'. Found: ${typeof validationError.value}. ${TYPE_ERROR_MESSAGE}`,
|
|
2008
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2009
|
-
typeError: true
|
|
2010
|
-
});
|
|
2011
|
-
} else {
|
|
2012
|
-
const key = "key" in validationError.value && validationError.value.key;
|
|
2013
|
-
const validationErrorSourcePath = "sourcePath" in validationError.value && validationError.value.sourcePath;
|
|
2014
|
-
if (typeof key !== "string") {
|
|
2015
|
-
addError({
|
|
2016
|
-
message: `Expected keyOf validation error 'value' to have property 'key' of type 'string'. Found: ${typeof key}. ${TYPE_ERROR_MESSAGE}`,
|
|
2017
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2018
|
-
typeError: true
|
|
2019
|
-
});
|
|
2020
|
-
} else if (typeof validationErrorSourcePath !== "string") {
|
|
2021
|
-
addError({
|
|
2022
|
-
message: `Expected keyOf validation error 'value' to have property 'sourcePath' of type 'string'. Found: ${typeof validationErrorSourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2023
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2024
|
-
typeError: true
|
|
2025
|
-
});
|
|
2026
|
-
} else {
|
|
2027
|
-
const res = await checkKeyIsValid(key, validationErrorSourcePath);
|
|
2028
|
-
if (res.error) {
|
|
2029
|
-
addError({
|
|
2030
|
-
message: res.message
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
} else if ((_validationError$fixe4 = validationError.fixes) !== null && _validationError$fixe4 !== void 0 && _validationError$fixe4.includes("router:check-route")) {
|
|
2037
|
-
const TYPE_ERROR_MESSAGE = `This is most likely a Val version mismatch or Val bug.`;
|
|
2038
|
-
if (!validationError.value) {
|
|
2039
|
-
addError({
|
|
2040
|
-
message: `Could not find a value for route at ${sourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2041
|
-
typeError: true
|
|
2042
|
-
});
|
|
2043
|
-
} else {
|
|
2044
|
-
if (typeof validationError.value !== "object") {
|
|
2045
|
-
addError({
|
|
2046
|
-
message: `Expected route validation error to have a 'value' property of type 'object'. Found: ${typeof validationError.value}. ${TYPE_ERROR_MESSAGE}`,
|
|
2047
|
-
typeError: true
|
|
2048
|
-
});
|
|
2049
|
-
} else {
|
|
2050
|
-
const route = "route" in validationError.value && validationError.value.route;
|
|
2051
|
-
const includePattern = "include" in validationError.value && validationError.value.include;
|
|
2052
|
-
const excludePattern = "exclude" in validationError.value && validationError.value.exclude;
|
|
2053
|
-
if (typeof route !== "string") {
|
|
2054
|
-
addError({
|
|
2055
|
-
message: `Expected route validation error 'value' to have property 'route' of type 'string'. Found: ${typeof route}. ${TYPE_ERROR_MESSAGE}`,
|
|
2056
|
-
typeError: true
|
|
2057
|
-
});
|
|
2058
|
-
} else {
|
|
2059
|
-
const res = await checkRouteIsValid(route, includePattern && typeof includePattern === "object" && "source" in includePattern && "flags" in includePattern ? includePattern : undefined, excludePattern && typeof excludePattern === "object" && "source" in excludePattern && "flags" in excludePattern ? excludePattern : undefined);
|
|
2060
|
-
if (res.error) {
|
|
2061
|
-
addError({
|
|
2062
|
-
message: res.message
|
|
2063
|
-
});
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
1833
|
+
} else if ((_validationError$fixe3 = validationError.fixes) !== null && _validationError$fixe3 !== void 0 && _validationError$fixe3.includes("keyof:check-keys") || (_validationError$fixe4 = validationError.fixes) !== null && _validationError$fixe4 !== void 0 && _validationError$fixe4.includes("router:check-route")) {
|
|
1834
|
+
const resolved = internal.resolveSchemaSourceFixForError(validationError, snapshot);
|
|
1835
|
+
if (resolved && resolved.status === "remaining") {
|
|
1836
|
+
addError(resolved.error);
|
|
2067
1837
|
}
|
|
1838
|
+
// resolved.status === "resolved" → drop silently
|
|
2068
1839
|
} else if ((_validationError$fixe5 = validationError.fixes) !== null && _validationError$fixe5 !== void 0 && _validationError$fixe5.includes("images:check-unique-folder") || (_validationError$fixe6 = validationError.fixes) !== null && _validationError$fixe6 !== void 0 && _validationError$fixe6.includes("files:check-unique-folder")) {
|
|
2069
1840
|
const TYPE_ERROR_MESSAGE = `This is most likely a Val version mismatch or Val bug.`;
|
|
2070
1841
|
if (!validationError.value || typeof validationError.value !== "object") {
|
|
@@ -5915,21 +5686,29 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
5915
5686
|
const schemasRes = await serverOps.getSchemas();
|
|
5916
5687
|
let sourcesRes = await serverOps.getSources();
|
|
5917
5688
|
const unpatchedSources = sourcesRes.sources;
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
...
|
|
5925
|
-
...
|
|
5926
|
-
}
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5689
|
+
// Default to true to keep the legacy contract for older clients.
|
|
5690
|
+
// The studio client always passes false: it owns patch application
|
|
5691
|
+
// and rendering, and treats /sources/~ as a pure un-patched read.
|
|
5692
|
+
const applyPatches = query.apply_patches !== false;
|
|
5693
|
+
if (applyPatches) {
|
|
5694
|
+
const onlyPatchedTreeModules = await serverOps.getSources({
|
|
5695
|
+
...patchAnalysis,
|
|
5696
|
+
...patchOps
|
|
5697
|
+
});
|
|
5698
|
+
sourcesRes = {
|
|
5699
|
+
sources: {
|
|
5700
|
+
...sourcesRes.sources,
|
|
5701
|
+
...(onlyPatchedTreeModules.sources || {})
|
|
5702
|
+
},
|
|
5703
|
+
errors: {
|
|
5704
|
+
...sourcesRes.errors,
|
|
5705
|
+
...(onlyPatchedTreeModules.errors || {})
|
|
5706
|
+
}
|
|
5707
|
+
};
|
|
5708
|
+
}
|
|
5709
|
+
const renderRes = applyPatches ? await serverOps.getRenders(schemasRes, sourcesRes.sources) : {
|
|
5710
|
+
renders: {}
|
|
5931
5711
|
};
|
|
5932
|
-
const renderRes = await serverOps.getRenders(schemasRes, sourcesRes.sources);
|
|
5933
5712
|
let sourcesValidation = {
|
|
5934
5713
|
errors: {},
|
|
5935
5714
|
files: {},
|
|
@@ -5977,7 +5756,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
5977
5756
|
const hasPatches = (((_patchAnalysis$patche2 = patchAnalysis.patchesByModule[moduleFilePath]) === null || _patchAnalysis$patche2 === void 0 ? void 0 : _patchAnalysis$patche2.length) ?? 0) > 0;
|
|
5978
5757
|
modules[moduleFilePath] = {
|
|
5979
5758
|
source: module,
|
|
5980
|
-
baseSource
|
|
5759
|
+
// baseSource is only meaningful when the server applied patches:
|
|
5760
|
+
// with apply_patches=false, `source` is already un-patched.
|
|
5761
|
+
baseSource: applyPatches && hasPatches ? unpatchedSources[moduleFilePath] : undefined,
|
|
5981
5762
|
render: renderRes.renders[moduleFilePath] || null,
|
|
5982
5763
|
patches: appliedPatches.length > 0 || skippedPatches.length > 0 || Object.keys(patchErrors).length > 0 ? {
|
|
5983
5764
|
applied: appliedPatches,
|
|
@@ -1289,6 +1289,11 @@ export default new Proxy({}, {
|
|
|
1289
1289
|
value: "export const ValApp = new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'ValApp' in this file`) } } } )"
|
|
1290
1290
|
};
|
|
1291
1291
|
}
|
|
1292
|
+
if (modulePath.includes("/ValModulesClient")) {
|
|
1293
|
+
return {
|
|
1294
|
+
value: "export const ValModulesClient = new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'ValModulesClient' in this file`) } } } ); export const useRegisterValModules = () => { throw new Error(`Cannot use 'useRegisterValModules' in this type of file`) };"
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1292
1297
|
return {
|
|
1293
1298
|
value: moduleLoader.getModule(modulePath)
|
|
1294
1299
|
};
|
|
@@ -1359,6 +1364,11 @@ export default new Proxy({}, {
|
|
|
1359
1364
|
value: requestedName
|
|
1360
1365
|
};
|
|
1361
1366
|
}
|
|
1367
|
+
if (requestedName.includes("/ValModulesClient")) {
|
|
1368
|
+
return {
|
|
1369
|
+
value: requestedName
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1362
1372
|
const modulePath = moduleLoader.resolveModulePath(baseModuleName, requestedName);
|
|
1363
1373
|
return {
|
|
1364
1374
|
value: modulePath
|
|
@@ -1493,7 +1503,6 @@ function encodeJwt(payload, sessionKey) {
|
|
|
1493
1503
|
}
|
|
1494
1504
|
|
|
1495
1505
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1496
|
-
const textEncoder$2 = new TextEncoder();
|
|
1497
1506
|
const jsonOps = new patch.JSONOps();
|
|
1498
1507
|
const tsOps = new TSOps(document => {
|
|
1499
1508
|
return fp.pipe(analyzeValModule(document), fp.result.map(({
|
|
@@ -1525,47 +1534,6 @@ class ValOps {
|
|
|
1525
1534
|
this.configSha = null;
|
|
1526
1535
|
this.modulesErrors = null;
|
|
1527
1536
|
}
|
|
1528
|
-
hash(input) {
|
|
1529
|
-
if (typeof input === "object") {
|
|
1530
|
-
return this.hashObject(input);
|
|
1531
|
-
}
|
|
1532
|
-
return core.Internal.getSHA256Hash(textEncoder$2.encode(input));
|
|
1533
|
-
}
|
|
1534
|
-
hashObject(obj) {
|
|
1535
|
-
const collector = [];
|
|
1536
|
-
this.collectObjectRecursive(obj, collector);
|
|
1537
|
-
return core.Internal.getSHA256Hash(textEncoder$2.encode(collector.join("")));
|
|
1538
|
-
}
|
|
1539
|
-
collectObjectRecursive(item, collector) {
|
|
1540
|
-
if (typeof item === "string") {
|
|
1541
|
-
collector.push(`"`, item, `"`);
|
|
1542
|
-
return;
|
|
1543
|
-
} else if (typeof item === "number") {
|
|
1544
|
-
collector.push(item.toString());
|
|
1545
|
-
return;
|
|
1546
|
-
} else if (typeof item === "object") {
|
|
1547
|
-
if (Array.isArray(item)) {
|
|
1548
|
-
collector.push("[");
|
|
1549
|
-
for (let i = 0; i < item.length; i++) {
|
|
1550
|
-
this.collectObjectRecursive(item[i], collector);
|
|
1551
|
-
if (i !== item.length - 1) collector.push(",");
|
|
1552
|
-
}
|
|
1553
|
-
collector.push("]");
|
|
1554
|
-
} else {
|
|
1555
|
-
collector.push("{");
|
|
1556
|
-
const keys = Object.keys(item).sort();
|
|
1557
|
-
keys.forEach((key, i) => {
|
|
1558
|
-
collector.push(`"${key}":`);
|
|
1559
|
-
this.collectObjectRecursive(item[key], collector);
|
|
1560
|
-
if (i !== keys.length - 1) collector.push(",");
|
|
1561
|
-
});
|
|
1562
|
-
collector.push("}");
|
|
1563
|
-
}
|
|
1564
|
-
return;
|
|
1565
|
-
} else {
|
|
1566
|
-
console.warn("Unknown type encountered when hashing object", typeof item, item);
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
1537
|
|
|
1570
1538
|
// #region stat
|
|
1571
1539
|
/**
|
|
@@ -1581,93 +1549,23 @@ class ValOps {
|
|
|
1581
1549
|
// #region initTree
|
|
1582
1550
|
async initSources() {
|
|
1583
1551
|
if (this.baseSha === null || this.sourcesSha === null || this.configSha === null || this.schemaSha === null || this.sources === null || this.schemas === null || this.modulesErrors === null) {
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1552
|
+
const extracted = await core.extractValModules(this.valModules);
|
|
1553
|
+
this.sources = extracted.sources;
|
|
1554
|
+
this.schemas = extracted.schemas;
|
|
1555
|
+
this.baseSha = extracted.baseSha;
|
|
1556
|
+
this.schemaSha = extracted.schemaSha;
|
|
1557
|
+
this.sourcesSha = extracted.sourcesSha;
|
|
1558
|
+
this.configSha = extracted.configSha;
|
|
1559
|
+
this.modulesErrors = extracted.moduleErrors;
|
|
1560
|
+
return {
|
|
1561
|
+
baseSha: this.baseSha,
|
|
1562
|
+
schemaSha: this.schemaSha,
|
|
1563
|
+
sourcesSha: this.sourcesSha,
|
|
1564
|
+
configSha: this.configSha,
|
|
1565
|
+
sources: extracted.sources,
|
|
1566
|
+
schemas: extracted.schemas,
|
|
1567
|
+
moduleErrors: extracted.moduleErrors
|
|
1590
1568
|
};
|
|
1591
|
-
const currentSources = {};
|
|
1592
|
-
const currentSchemas = {};
|
|
1593
|
-
const configSha = this.hash(JSON.stringify(this.valModules.config));
|
|
1594
|
-
let sourcesSha = "";
|
|
1595
|
-
let baseSha = configSha;
|
|
1596
|
-
let schemaSha = configSha;
|
|
1597
|
-
for (let moduleIdx = 0; moduleIdx < this.valModules.modules.length; moduleIdx++) {
|
|
1598
|
-
const module = this.valModules.modules[moduleIdx];
|
|
1599
|
-
if (!module.def) {
|
|
1600
|
-
addModuleError("val.modules is missing 'def' property", moduleIdx);
|
|
1601
|
-
continue;
|
|
1602
|
-
}
|
|
1603
|
-
if (typeof module.def !== "function") {
|
|
1604
|
-
addModuleError("val.modules 'def' property is not a function", moduleIdx);
|
|
1605
|
-
continue;
|
|
1606
|
-
}
|
|
1607
|
-
await module.def().then(value => {
|
|
1608
|
-
if (!value) {
|
|
1609
|
-
addModuleError(`val.modules 'def' did not return a value`, moduleIdx);
|
|
1610
|
-
return;
|
|
1611
|
-
}
|
|
1612
|
-
if (!value.default) {
|
|
1613
|
-
addModuleError(`val.modules 'def' did not return a default export`, moduleIdx);
|
|
1614
|
-
return;
|
|
1615
|
-
}
|
|
1616
|
-
const path = core.Internal.getValPath(value.default);
|
|
1617
|
-
if (path === undefined) {
|
|
1618
|
-
addModuleError(`path is undefined`, moduleIdx);
|
|
1619
|
-
return;
|
|
1620
|
-
}
|
|
1621
|
-
const schema = core.Internal.getSchema(value.default);
|
|
1622
|
-
if (schema === undefined) {
|
|
1623
|
-
addModuleError(`schema in path '${path}' is undefined`, moduleIdx, path);
|
|
1624
|
-
return;
|
|
1625
|
-
}
|
|
1626
|
-
if (!(schema instanceof core.Schema)) {
|
|
1627
|
-
addModuleError(`schema in path '${path}' is not an instance of Schema`, moduleIdx, path);
|
|
1628
|
-
return;
|
|
1629
|
-
}
|
|
1630
|
-
if (typeof schema["executeSerialize"] !== "function") {
|
|
1631
|
-
addModuleError(`schema.serialize in path '${path}' is not a function`, moduleIdx, path);
|
|
1632
|
-
return;
|
|
1633
|
-
}
|
|
1634
|
-
const source = core.Internal.getSource(value.default);
|
|
1635
|
-
if (source === undefined) {
|
|
1636
|
-
addModuleError(`source in ${path} is undefined`, moduleIdx, path);
|
|
1637
|
-
return;
|
|
1638
|
-
}
|
|
1639
|
-
let serializedSchema;
|
|
1640
|
-
try {
|
|
1641
|
-
serializedSchema = schema["executeSerialize"]();
|
|
1642
|
-
} catch (e) {
|
|
1643
|
-
const message = e instanceof Error ? e.message : JSON.stringify(e);
|
|
1644
|
-
addModuleError(`Could not serialize module: '${path}'. Error: ${message}`, moduleIdx, path);
|
|
1645
|
-
return;
|
|
1646
|
-
}
|
|
1647
|
-
const pathM = path;
|
|
1648
|
-
currentSources[pathM] = source;
|
|
1649
|
-
currentSchemas[pathM] = schema;
|
|
1650
|
-
// make sure the checks above is enough that this does not fail - even if val modules are not set up correctly
|
|
1651
|
-
sourcesSha = this.hash(sourcesSha + JSON.stringify({
|
|
1652
|
-
path,
|
|
1653
|
-
source
|
|
1654
|
-
}));
|
|
1655
|
-
baseSha = this.hash(baseSha + JSON.stringify({
|
|
1656
|
-
path,
|
|
1657
|
-
schema: serializedSchema,
|
|
1658
|
-
source,
|
|
1659
|
-
modulesErrors: currentModulesErrors
|
|
1660
|
-
}));
|
|
1661
|
-
schemaSha = this.hash(schemaSha + JSON.stringify(serializedSchema));
|
|
1662
|
-
});
|
|
1663
|
-
}
|
|
1664
|
-
this.sources = currentSources;
|
|
1665
|
-
this.schemas = currentSchemas;
|
|
1666
|
-
this.baseSha = baseSha;
|
|
1667
|
-
this.schemaSha = schemaSha;
|
|
1668
|
-
this.sourcesSha = sourcesSha;
|
|
1669
|
-
this.configSha = configSha;
|
|
1670
|
-
this.modulesErrors = currentModulesErrors;
|
|
1671
1569
|
}
|
|
1672
1570
|
return {
|
|
1673
1571
|
baseSha: this.baseSha,
|
|
@@ -1847,79 +1745,6 @@ class ValOps {
|
|
|
1847
1745
|
|
|
1848
1746
|
// #region validateSources
|
|
1849
1747
|
async validateSources(schemas, sources, patchesByModule) {
|
|
1850
|
-
const checkKeyIsValid = async (key, sourcePath) => {
|
|
1851
|
-
var _schemas$moduleFilePa;
|
|
1852
|
-
const [moduleFilePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
1853
|
-
const keyOfModuleSource = sources[moduleFilePath];
|
|
1854
|
-
const keyOfModuleSchema = (_schemas$moduleFilePa = schemas[moduleFilePath]) === null || _schemas$moduleFilePa === void 0 ? void 0 : _schemas$moduleFilePa["executeSerialize"]();
|
|
1855
|
-
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
1856
|
-
return {
|
|
1857
|
-
error: true,
|
|
1858
|
-
message: `Expected key at ${sourcePath} to be of type 'record'`
|
|
1859
|
-
};
|
|
1860
|
-
}
|
|
1861
|
-
if (keyOfModuleSource && typeof keyOfModuleSource === "object" && key in keyOfModuleSource) {
|
|
1862
|
-
return {
|
|
1863
|
-
error: false
|
|
1864
|
-
};
|
|
1865
|
-
}
|
|
1866
|
-
if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
|
|
1867
|
-
return {
|
|
1868
|
-
error: true,
|
|
1869
|
-
message: `Expected ${sourcePath} to be a truthy object`
|
|
1870
|
-
};
|
|
1871
|
-
}
|
|
1872
|
-
return {
|
|
1873
|
-
error: true,
|
|
1874
|
-
message: `Key '${key}' does not exist in ${sourcePath}.`
|
|
1875
|
-
};
|
|
1876
|
-
};
|
|
1877
|
-
const checkRouteIsValid = async (route, includePattern, excludePattern) => {
|
|
1878
|
-
// Find all router modules (record schemas with router property)
|
|
1879
|
-
const routerModules = [];
|
|
1880
|
-
for (const [moduleFilePath, schema] of Object.entries(schemas)) {
|
|
1881
|
-
const serializedSchema = schema["executeSerialize"]();
|
|
1882
|
-
if (serializedSchema.type === "record" && serializedSchema.router) {
|
|
1883
|
-
const source = sources[moduleFilePath];
|
|
1884
|
-
if (source && typeof source === "object") {
|
|
1885
|
-
routerModules.push({
|
|
1886
|
-
path: moduleFilePath,
|
|
1887
|
-
routes: Object.keys(source)
|
|
1888
|
-
});
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
if (routerModules.length === 0) {
|
|
1893
|
-
return {
|
|
1894
|
-
error: true,
|
|
1895
|
-
message: `No router modules found. Route validation requires at least one s.record().router() module.`
|
|
1896
|
-
};
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
// Check if route exists in any router module
|
|
1900
|
-
const allRoutes = routerModules.flatMap(m => m.routes);
|
|
1901
|
-
const routeExists = allRoutes.includes(route);
|
|
1902
|
-
if (!routeExists) {
|
|
1903
|
-
// Filter routes by include/exclude patterns for suggestions
|
|
1904
|
-
const validRoutes = internal.filterRoutesByPatterns(allRoutes, includePattern, excludePattern);
|
|
1905
|
-
return {
|
|
1906
|
-
error: true,
|
|
1907
|
-
message: `Route '${route}' does not exist in any router module. Available routes: ${validRoutes.slice(0, 10).join(", ")}${validRoutes.length > 10 ? "..." : ""}`
|
|
1908
|
-
};
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
// Validate against include/exclude patterns
|
|
1912
|
-
const patternValidation = internal.validateRoutePatterns(route, includePattern, excludePattern);
|
|
1913
|
-
if (!patternValidation.valid) {
|
|
1914
|
-
return {
|
|
1915
|
-
error: true,
|
|
1916
|
-
message: patternValidation.message
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
return {
|
|
1920
|
-
error: false
|
|
1921
|
-
};
|
|
1922
|
-
};
|
|
1923
1748
|
const errors = {};
|
|
1924
1749
|
const files = {};
|
|
1925
1750
|
const remoteFiles = {};
|
|
@@ -1927,15 +1752,27 @@ class ValOps {
|
|
|
1927
1752
|
// Build a map of gallery directory → [ModuleFilePath, ...] across ALL modules
|
|
1928
1753
|
// (must include all modules, not just those being validated, since conflicts can come from any module)
|
|
1929
1754
|
const galleryDirectoryToModules = new Map();
|
|
1755
|
+
// Build a schema/source snapshot so the shared resolver can cross-reference
|
|
1756
|
+
// keyof:check-keys and router:check-route against every module's data.
|
|
1757
|
+
const snapshot = {
|
|
1758
|
+
schemas: {},
|
|
1759
|
+
sources: {}
|
|
1760
|
+
};
|
|
1930
1761
|
for (const [moduleFilePathS, schema] of entries) {
|
|
1762
|
+
const moduleFilePath = moduleFilePathS;
|
|
1931
1763
|
const serialized = schema["executeSerialize"]();
|
|
1764
|
+
snapshot.schemas[moduleFilePath] = serialized;
|
|
1765
|
+
const sourceForModule = sources[moduleFilePath];
|
|
1766
|
+
if (sourceForModule !== undefined) {
|
|
1767
|
+
snapshot.sources[moduleFilePath] = sourceForModule;
|
|
1768
|
+
}
|
|
1932
1769
|
if (serialized.type === "record" && serialized.mediaType && serialized.directory) {
|
|
1933
1770
|
const dir = serialized.directory;
|
|
1934
1771
|
const existing = galleryDirectoryToModules.get(dir);
|
|
1935
1772
|
if (existing) {
|
|
1936
|
-
existing.push(
|
|
1773
|
+
existing.push(moduleFilePath);
|
|
1937
1774
|
} else {
|
|
1938
|
-
galleryDirectoryToModules.set(dir, [
|
|
1775
|
+
galleryDirectoryToModules.set(dir, [moduleFilePath]);
|
|
1939
1776
|
}
|
|
1940
1777
|
}
|
|
1941
1778
|
}
|
|
@@ -1993,78 +1830,12 @@ class ValOps {
|
|
|
1993
1830
|
}
|
|
1994
1831
|
} else if ((_validationError$fixe = validationError.fixes) !== null && _validationError$fixe !== void 0 && _validationError$fixe.includes("image:check-remote") || (_validationError$fixe2 = validationError.fixes) !== null && _validationError$fixe2 !== void 0 && _validationError$fixe2.includes("file:check-remote")) {
|
|
1995
1832
|
remoteFiles[sourcePath] = validationError.value;
|
|
1996
|
-
} else if ((_validationError$fixe3 = validationError.fixes) !== null && _validationError$fixe3 !== void 0 && _validationError$fixe3.includes("keyof:check-keys")) {
|
|
1997
|
-
const
|
|
1998
|
-
if (
|
|
1999
|
-
addError(
|
|
2000
|
-
message: `Could not find a value for keyOf at ${sourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2001
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2002
|
-
typeError: true
|
|
2003
|
-
});
|
|
2004
|
-
} else {
|
|
2005
|
-
if (typeof validationError.value !== "object") {
|
|
2006
|
-
addError({
|
|
2007
|
-
message: `Expected keyOf validation error to have a 'value' property of type 'object'. Found: ${typeof validationError.value}. ${TYPE_ERROR_MESSAGE}`,
|
|
2008
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2009
|
-
typeError: true
|
|
2010
|
-
});
|
|
2011
|
-
} else {
|
|
2012
|
-
const key = "key" in validationError.value && validationError.value.key;
|
|
2013
|
-
const validationErrorSourcePath = "sourcePath" in validationError.value && validationError.value.sourcePath;
|
|
2014
|
-
if (typeof key !== "string") {
|
|
2015
|
-
addError({
|
|
2016
|
-
message: `Expected keyOf validation error 'value' to have property 'key' of type 'string'. Found: ${typeof key}. ${TYPE_ERROR_MESSAGE}`,
|
|
2017
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2018
|
-
typeError: true
|
|
2019
|
-
});
|
|
2020
|
-
} else if (typeof validationErrorSourcePath !== "string") {
|
|
2021
|
-
addError({
|
|
2022
|
-
message: `Expected keyOf validation error 'value' to have property 'sourcePath' of type 'string'. Found: ${typeof validationErrorSourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2023
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
2024
|
-
typeError: true
|
|
2025
|
-
});
|
|
2026
|
-
} else {
|
|
2027
|
-
const res = await checkKeyIsValid(key, validationErrorSourcePath);
|
|
2028
|
-
if (res.error) {
|
|
2029
|
-
addError({
|
|
2030
|
-
message: res.message
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
} else if ((_validationError$fixe4 = validationError.fixes) !== null && _validationError$fixe4 !== void 0 && _validationError$fixe4.includes("router:check-route")) {
|
|
2037
|
-
const TYPE_ERROR_MESSAGE = `This is most likely a Val version mismatch or Val bug.`;
|
|
2038
|
-
if (!validationError.value) {
|
|
2039
|
-
addError({
|
|
2040
|
-
message: `Could not find a value for route at ${sourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2041
|
-
typeError: true
|
|
2042
|
-
});
|
|
2043
|
-
} else {
|
|
2044
|
-
if (typeof validationError.value !== "object") {
|
|
2045
|
-
addError({
|
|
2046
|
-
message: `Expected route validation error to have a 'value' property of type 'object'. Found: ${typeof validationError.value}. ${TYPE_ERROR_MESSAGE}`,
|
|
2047
|
-
typeError: true
|
|
2048
|
-
});
|
|
2049
|
-
} else {
|
|
2050
|
-
const route = "route" in validationError.value && validationError.value.route;
|
|
2051
|
-
const includePattern = "include" in validationError.value && validationError.value.include;
|
|
2052
|
-
const excludePattern = "exclude" in validationError.value && validationError.value.exclude;
|
|
2053
|
-
if (typeof route !== "string") {
|
|
2054
|
-
addError({
|
|
2055
|
-
message: `Expected route validation error 'value' to have property 'route' of type 'string'. Found: ${typeof route}. ${TYPE_ERROR_MESSAGE}`,
|
|
2056
|
-
typeError: true
|
|
2057
|
-
});
|
|
2058
|
-
} else {
|
|
2059
|
-
const res = await checkRouteIsValid(route, includePattern && typeof includePattern === "object" && "source" in includePattern && "flags" in includePattern ? includePattern : undefined, excludePattern && typeof excludePattern === "object" && "source" in excludePattern && "flags" in excludePattern ? excludePattern : undefined);
|
|
2060
|
-
if (res.error) {
|
|
2061
|
-
addError({
|
|
2062
|
-
message: res.message
|
|
2063
|
-
});
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
1833
|
+
} else if ((_validationError$fixe3 = validationError.fixes) !== null && _validationError$fixe3 !== void 0 && _validationError$fixe3.includes("keyof:check-keys") || (_validationError$fixe4 = validationError.fixes) !== null && _validationError$fixe4 !== void 0 && _validationError$fixe4.includes("router:check-route")) {
|
|
1834
|
+
const resolved = internal.resolveSchemaSourceFixForError(validationError, snapshot);
|
|
1835
|
+
if (resolved && resolved.status === "remaining") {
|
|
1836
|
+
addError(resolved.error);
|
|
2067
1837
|
}
|
|
1838
|
+
// resolved.status === "resolved" → drop silently
|
|
2068
1839
|
} else if ((_validationError$fixe5 = validationError.fixes) !== null && _validationError$fixe5 !== void 0 && _validationError$fixe5.includes("images:check-unique-folder") || (_validationError$fixe6 = validationError.fixes) !== null && _validationError$fixe6 !== void 0 && _validationError$fixe6.includes("files:check-unique-folder")) {
|
|
2069
1840
|
const TYPE_ERROR_MESSAGE = `This is most likely a Val version mismatch or Val bug.`;
|
|
2070
1841
|
if (!validationError.value || typeof validationError.value !== "object") {
|
|
@@ -5915,21 +5686,29 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
5915
5686
|
const schemasRes = await serverOps.getSchemas();
|
|
5916
5687
|
let sourcesRes = await serverOps.getSources();
|
|
5917
5688
|
const unpatchedSources = sourcesRes.sources;
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
...
|
|
5925
|
-
...
|
|
5926
|
-
}
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5689
|
+
// Default to true to keep the legacy contract for older clients.
|
|
5690
|
+
// The studio client always passes false: it owns patch application
|
|
5691
|
+
// and rendering, and treats /sources/~ as a pure un-patched read.
|
|
5692
|
+
const applyPatches = query.apply_patches !== false;
|
|
5693
|
+
if (applyPatches) {
|
|
5694
|
+
const onlyPatchedTreeModules = await serverOps.getSources({
|
|
5695
|
+
...patchAnalysis,
|
|
5696
|
+
...patchOps
|
|
5697
|
+
});
|
|
5698
|
+
sourcesRes = {
|
|
5699
|
+
sources: {
|
|
5700
|
+
...sourcesRes.sources,
|
|
5701
|
+
...(onlyPatchedTreeModules.sources || {})
|
|
5702
|
+
},
|
|
5703
|
+
errors: {
|
|
5704
|
+
...sourcesRes.errors,
|
|
5705
|
+
...(onlyPatchedTreeModules.errors || {})
|
|
5706
|
+
}
|
|
5707
|
+
};
|
|
5708
|
+
}
|
|
5709
|
+
const renderRes = applyPatches ? await serverOps.getRenders(schemasRes, sourcesRes.sources) : {
|
|
5710
|
+
renders: {}
|
|
5931
5711
|
};
|
|
5932
|
-
const renderRes = await serverOps.getRenders(schemasRes, sourcesRes.sources);
|
|
5933
5712
|
let sourcesValidation = {
|
|
5934
5713
|
errors: {},
|
|
5935
5714
|
files: {},
|
|
@@ -5977,7 +5756,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
5977
5756
|
const hasPatches = (((_patchAnalysis$patche2 = patchAnalysis.patchesByModule[moduleFilePath]) === null || _patchAnalysis$patche2 === void 0 ? void 0 : _patchAnalysis$patche2.length) ?? 0) > 0;
|
|
5978
5757
|
modules[moduleFilePath] = {
|
|
5979
5758
|
source: module,
|
|
5980
|
-
baseSource
|
|
5759
|
+
// baseSource is only meaningful when the server applied patches:
|
|
5760
|
+
// with apply_patches=false, `source` is already un-patched.
|
|
5761
|
+
baseSource: applyPatches && hasPatches ? unpatchedSources[moduleFilePath] : undefined,
|
|
5981
5762
|
render: renderRes.renders[moduleFilePath] || null,
|
|
5982
5763
|
patches: appliedPatches.length > 0 || skippedPatches.length > 0 || Object.keys(patchErrors).length > 0 ? {
|
|
5983
5764
|
applied: appliedPatches,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { newQuickJSWASMModule } from 'quickjs-emscripten';
|
|
2
2
|
import ts from 'typescript';
|
|
3
3
|
import { result, pipe } from '@valbuild/core/fp';
|
|
4
|
-
import { FILE_REF_PROP, FILE_REF_SUBTYPE_TAG, VAL_EXTENSION, derefPatch, Internal, Schema, ImageSchema, DEFAULT_CONTENT_HOST } from '@valbuild/core';
|
|
4
|
+
import { FILE_REF_PROP, FILE_REF_SUBTYPE_TAG, VAL_EXTENSION, derefPatch, Internal, Schema, extractValModules, ImageSchema, DEFAULT_CONTENT_HOST } from '@valbuild/core';
|
|
5
5
|
import { deepEqual, isNotRoot, PatchError, parseAndValidateArrayIndex, applyPatch, JSONOps, deepClone, sourceToPatchPath } from '@valbuild/core/patch';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import path__default from 'path';
|
|
8
8
|
import fs, { promises } from 'fs';
|
|
9
9
|
import { transform } from 'sucrase';
|
|
10
10
|
import { VAL_CSS_PATH, VAL_APP_ID, VAL_OVERLAY_ID } from '@valbuild/ui';
|
|
11
|
-
import {
|
|
11
|
+
import { resolveSchemaSourceFixForError, getErrorMessageFromUnknownJson, Patch, ParentRef, VAL_ENABLE_COOKIE_NAME, VAL_STATE_COOKIE, VAL_SESSION_COOKIE, Api } from '@valbuild/shared/internal';
|
|
12
12
|
import { createUIRequestHandler } from '@valbuild/ui/server';
|
|
13
13
|
import crypto$1 from 'crypto';
|
|
14
14
|
import { z } from 'zod';
|
|
@@ -1258,6 +1258,11 @@ export default new Proxy({}, {
|
|
|
1258
1258
|
value: "export const ValApp = new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'ValApp' in this file`) } } } )"
|
|
1259
1259
|
};
|
|
1260
1260
|
}
|
|
1261
|
+
if (modulePath.includes("/ValModulesClient")) {
|
|
1262
|
+
return {
|
|
1263
|
+
value: "export const ValModulesClient = new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'ValModulesClient' in this file`) } } } ); export const useRegisterValModules = () => { throw new Error(`Cannot use 'useRegisterValModules' in this type of file`) };"
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1261
1266
|
return {
|
|
1262
1267
|
value: moduleLoader.getModule(modulePath)
|
|
1263
1268
|
};
|
|
@@ -1328,6 +1333,11 @@ export default new Proxy({}, {
|
|
|
1328
1333
|
value: requestedName
|
|
1329
1334
|
};
|
|
1330
1335
|
}
|
|
1336
|
+
if (requestedName.includes("/ValModulesClient")) {
|
|
1337
|
+
return {
|
|
1338
|
+
value: requestedName
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1331
1341
|
const modulePath = moduleLoader.resolveModulePath(baseModuleName, requestedName);
|
|
1332
1342
|
return {
|
|
1333
1343
|
value: modulePath
|
|
@@ -1462,7 +1472,6 @@ function encodeJwt(payload, sessionKey) {
|
|
|
1462
1472
|
}
|
|
1463
1473
|
|
|
1464
1474
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1465
|
-
const textEncoder$2 = new TextEncoder();
|
|
1466
1475
|
const jsonOps = new JSONOps();
|
|
1467
1476
|
const tsOps = new TSOps(document => {
|
|
1468
1477
|
return pipe(analyzeValModule(document), result.map(({
|
|
@@ -1494,47 +1503,6 @@ class ValOps {
|
|
|
1494
1503
|
this.configSha = null;
|
|
1495
1504
|
this.modulesErrors = null;
|
|
1496
1505
|
}
|
|
1497
|
-
hash(input) {
|
|
1498
|
-
if (typeof input === "object") {
|
|
1499
|
-
return this.hashObject(input);
|
|
1500
|
-
}
|
|
1501
|
-
return Internal.getSHA256Hash(textEncoder$2.encode(input));
|
|
1502
|
-
}
|
|
1503
|
-
hashObject(obj) {
|
|
1504
|
-
const collector = [];
|
|
1505
|
-
this.collectObjectRecursive(obj, collector);
|
|
1506
|
-
return Internal.getSHA256Hash(textEncoder$2.encode(collector.join("")));
|
|
1507
|
-
}
|
|
1508
|
-
collectObjectRecursive(item, collector) {
|
|
1509
|
-
if (typeof item === "string") {
|
|
1510
|
-
collector.push(`"`, item, `"`);
|
|
1511
|
-
return;
|
|
1512
|
-
} else if (typeof item === "number") {
|
|
1513
|
-
collector.push(item.toString());
|
|
1514
|
-
return;
|
|
1515
|
-
} else if (typeof item === "object") {
|
|
1516
|
-
if (Array.isArray(item)) {
|
|
1517
|
-
collector.push("[");
|
|
1518
|
-
for (let i = 0; i < item.length; i++) {
|
|
1519
|
-
this.collectObjectRecursive(item[i], collector);
|
|
1520
|
-
if (i !== item.length - 1) collector.push(",");
|
|
1521
|
-
}
|
|
1522
|
-
collector.push("]");
|
|
1523
|
-
} else {
|
|
1524
|
-
collector.push("{");
|
|
1525
|
-
const keys = Object.keys(item).sort();
|
|
1526
|
-
keys.forEach((key, i) => {
|
|
1527
|
-
collector.push(`"${key}":`);
|
|
1528
|
-
this.collectObjectRecursive(item[key], collector);
|
|
1529
|
-
if (i !== keys.length - 1) collector.push(",");
|
|
1530
|
-
});
|
|
1531
|
-
collector.push("}");
|
|
1532
|
-
}
|
|
1533
|
-
return;
|
|
1534
|
-
} else {
|
|
1535
|
-
console.warn("Unknown type encountered when hashing object", typeof item, item);
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
1506
|
|
|
1539
1507
|
// #region stat
|
|
1540
1508
|
/**
|
|
@@ -1550,93 +1518,23 @@ class ValOps {
|
|
|
1550
1518
|
// #region initTree
|
|
1551
1519
|
async initSources() {
|
|
1552
1520
|
if (this.baseSha === null || this.sourcesSha === null || this.configSha === null || this.schemaSha === null || this.sources === null || this.schemas === null || this.modulesErrors === null) {
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1521
|
+
const extracted = await extractValModules(this.valModules);
|
|
1522
|
+
this.sources = extracted.sources;
|
|
1523
|
+
this.schemas = extracted.schemas;
|
|
1524
|
+
this.baseSha = extracted.baseSha;
|
|
1525
|
+
this.schemaSha = extracted.schemaSha;
|
|
1526
|
+
this.sourcesSha = extracted.sourcesSha;
|
|
1527
|
+
this.configSha = extracted.configSha;
|
|
1528
|
+
this.modulesErrors = extracted.moduleErrors;
|
|
1529
|
+
return {
|
|
1530
|
+
baseSha: this.baseSha,
|
|
1531
|
+
schemaSha: this.schemaSha,
|
|
1532
|
+
sourcesSha: this.sourcesSha,
|
|
1533
|
+
configSha: this.configSha,
|
|
1534
|
+
sources: extracted.sources,
|
|
1535
|
+
schemas: extracted.schemas,
|
|
1536
|
+
moduleErrors: extracted.moduleErrors
|
|
1559
1537
|
};
|
|
1560
|
-
const currentSources = {};
|
|
1561
|
-
const currentSchemas = {};
|
|
1562
|
-
const configSha = this.hash(JSON.stringify(this.valModules.config));
|
|
1563
|
-
let sourcesSha = "";
|
|
1564
|
-
let baseSha = configSha;
|
|
1565
|
-
let schemaSha = configSha;
|
|
1566
|
-
for (let moduleIdx = 0; moduleIdx < this.valModules.modules.length; moduleIdx++) {
|
|
1567
|
-
const module = this.valModules.modules[moduleIdx];
|
|
1568
|
-
if (!module.def) {
|
|
1569
|
-
addModuleError("val.modules is missing 'def' property", moduleIdx);
|
|
1570
|
-
continue;
|
|
1571
|
-
}
|
|
1572
|
-
if (typeof module.def !== "function") {
|
|
1573
|
-
addModuleError("val.modules 'def' property is not a function", moduleIdx);
|
|
1574
|
-
continue;
|
|
1575
|
-
}
|
|
1576
|
-
await module.def().then(value => {
|
|
1577
|
-
if (!value) {
|
|
1578
|
-
addModuleError(`val.modules 'def' did not return a value`, moduleIdx);
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1581
|
-
if (!value.default) {
|
|
1582
|
-
addModuleError(`val.modules 'def' did not return a default export`, moduleIdx);
|
|
1583
|
-
return;
|
|
1584
|
-
}
|
|
1585
|
-
const path = Internal.getValPath(value.default);
|
|
1586
|
-
if (path === undefined) {
|
|
1587
|
-
addModuleError(`path is undefined`, moduleIdx);
|
|
1588
|
-
return;
|
|
1589
|
-
}
|
|
1590
|
-
const schema = Internal.getSchema(value.default);
|
|
1591
|
-
if (schema === undefined) {
|
|
1592
|
-
addModuleError(`schema in path '${path}' is undefined`, moduleIdx, path);
|
|
1593
|
-
return;
|
|
1594
|
-
}
|
|
1595
|
-
if (!(schema instanceof Schema)) {
|
|
1596
|
-
addModuleError(`schema in path '${path}' is not an instance of Schema`, moduleIdx, path);
|
|
1597
|
-
return;
|
|
1598
|
-
}
|
|
1599
|
-
if (typeof schema["executeSerialize"] !== "function") {
|
|
1600
|
-
addModuleError(`schema.serialize in path '${path}' is not a function`, moduleIdx, path);
|
|
1601
|
-
return;
|
|
1602
|
-
}
|
|
1603
|
-
const source = Internal.getSource(value.default);
|
|
1604
|
-
if (source === undefined) {
|
|
1605
|
-
addModuleError(`source in ${path} is undefined`, moduleIdx, path);
|
|
1606
|
-
return;
|
|
1607
|
-
}
|
|
1608
|
-
let serializedSchema;
|
|
1609
|
-
try {
|
|
1610
|
-
serializedSchema = schema["executeSerialize"]();
|
|
1611
|
-
} catch (e) {
|
|
1612
|
-
const message = e instanceof Error ? e.message : JSON.stringify(e);
|
|
1613
|
-
addModuleError(`Could not serialize module: '${path}'. Error: ${message}`, moduleIdx, path);
|
|
1614
|
-
return;
|
|
1615
|
-
}
|
|
1616
|
-
const pathM = path;
|
|
1617
|
-
currentSources[pathM] = source;
|
|
1618
|
-
currentSchemas[pathM] = schema;
|
|
1619
|
-
// make sure the checks above is enough that this does not fail - even if val modules are not set up correctly
|
|
1620
|
-
sourcesSha = this.hash(sourcesSha + JSON.stringify({
|
|
1621
|
-
path,
|
|
1622
|
-
source
|
|
1623
|
-
}));
|
|
1624
|
-
baseSha = this.hash(baseSha + JSON.stringify({
|
|
1625
|
-
path,
|
|
1626
|
-
schema: serializedSchema,
|
|
1627
|
-
source,
|
|
1628
|
-
modulesErrors: currentModulesErrors
|
|
1629
|
-
}));
|
|
1630
|
-
schemaSha = this.hash(schemaSha + JSON.stringify(serializedSchema));
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1633
|
-
this.sources = currentSources;
|
|
1634
|
-
this.schemas = currentSchemas;
|
|
1635
|
-
this.baseSha = baseSha;
|
|
1636
|
-
this.schemaSha = schemaSha;
|
|
1637
|
-
this.sourcesSha = sourcesSha;
|
|
1638
|
-
this.configSha = configSha;
|
|
1639
|
-
this.modulesErrors = currentModulesErrors;
|
|
1640
1538
|
}
|
|
1641
1539
|
return {
|
|
1642
1540
|
baseSha: this.baseSha,
|
|
@@ -1816,79 +1714,6 @@ class ValOps {
|
|
|
1816
1714
|
|
|
1817
1715
|
// #region validateSources
|
|
1818
1716
|
async validateSources(schemas, sources, patchesByModule) {
|
|
1819
|
-
const checkKeyIsValid = async (key, sourcePath) => {
|
|
1820
|
-
var _schemas$moduleFilePa;
|
|
1821
|
-
const [moduleFilePath] = Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
1822
|
-
const keyOfModuleSource = sources[moduleFilePath];
|
|
1823
|
-
const keyOfModuleSchema = (_schemas$moduleFilePa = schemas[moduleFilePath]) === null || _schemas$moduleFilePa === void 0 ? void 0 : _schemas$moduleFilePa["executeSerialize"]();
|
|
1824
|
-
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
1825
|
-
return {
|
|
1826
|
-
error: true,
|
|
1827
|
-
message: `Expected key at ${sourcePath} to be of type 'record'`
|
|
1828
|
-
};
|
|
1829
|
-
}
|
|
1830
|
-
if (keyOfModuleSource && typeof keyOfModuleSource === "object" && key in keyOfModuleSource) {
|
|
1831
|
-
return {
|
|
1832
|
-
error: false
|
|
1833
|
-
};
|
|
1834
|
-
}
|
|
1835
|
-
if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
|
|
1836
|
-
return {
|
|
1837
|
-
error: true,
|
|
1838
|
-
message: `Expected ${sourcePath} to be a truthy object`
|
|
1839
|
-
};
|
|
1840
|
-
}
|
|
1841
|
-
return {
|
|
1842
|
-
error: true,
|
|
1843
|
-
message: `Key '${key}' does not exist in ${sourcePath}.`
|
|
1844
|
-
};
|
|
1845
|
-
};
|
|
1846
|
-
const checkRouteIsValid = async (route, includePattern, excludePattern) => {
|
|
1847
|
-
// Find all router modules (record schemas with router property)
|
|
1848
|
-
const routerModules = [];
|
|
1849
|
-
for (const [moduleFilePath, schema] of Object.entries(schemas)) {
|
|
1850
|
-
const serializedSchema = schema["executeSerialize"]();
|
|
1851
|
-
if (serializedSchema.type === "record" && serializedSchema.router) {
|
|
1852
|
-
const source = sources[moduleFilePath];
|
|
1853
|
-
if (source && typeof source === "object") {
|
|
1854
|
-
routerModules.push({
|
|
1855
|
-
path: moduleFilePath,
|
|
1856
|
-
routes: Object.keys(source)
|
|
1857
|
-
});
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
}
|
|
1861
|
-
if (routerModules.length === 0) {
|
|
1862
|
-
return {
|
|
1863
|
-
error: true,
|
|
1864
|
-
message: `No router modules found. Route validation requires at least one s.record().router() module.`
|
|
1865
|
-
};
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
// Check if route exists in any router module
|
|
1869
|
-
const allRoutes = routerModules.flatMap(m => m.routes);
|
|
1870
|
-
const routeExists = allRoutes.includes(route);
|
|
1871
|
-
if (!routeExists) {
|
|
1872
|
-
// Filter routes by include/exclude patterns for suggestions
|
|
1873
|
-
const validRoutes = filterRoutesByPatterns(allRoutes, includePattern, excludePattern);
|
|
1874
|
-
return {
|
|
1875
|
-
error: true,
|
|
1876
|
-
message: `Route '${route}' does not exist in any router module. Available routes: ${validRoutes.slice(0, 10).join(", ")}${validRoutes.length > 10 ? "..." : ""}`
|
|
1877
|
-
};
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
// Validate against include/exclude patterns
|
|
1881
|
-
const patternValidation = validateRoutePatterns(route, includePattern, excludePattern);
|
|
1882
|
-
if (!patternValidation.valid) {
|
|
1883
|
-
return {
|
|
1884
|
-
error: true,
|
|
1885
|
-
message: patternValidation.message
|
|
1886
|
-
};
|
|
1887
|
-
}
|
|
1888
|
-
return {
|
|
1889
|
-
error: false
|
|
1890
|
-
};
|
|
1891
|
-
};
|
|
1892
1717
|
const errors = {};
|
|
1893
1718
|
const files = {};
|
|
1894
1719
|
const remoteFiles = {};
|
|
@@ -1896,15 +1721,27 @@ class ValOps {
|
|
|
1896
1721
|
// Build a map of gallery directory → [ModuleFilePath, ...] across ALL modules
|
|
1897
1722
|
// (must include all modules, not just those being validated, since conflicts can come from any module)
|
|
1898
1723
|
const galleryDirectoryToModules = new Map();
|
|
1724
|
+
// Build a schema/source snapshot so the shared resolver can cross-reference
|
|
1725
|
+
// keyof:check-keys and router:check-route against every module's data.
|
|
1726
|
+
const snapshot = {
|
|
1727
|
+
schemas: {},
|
|
1728
|
+
sources: {}
|
|
1729
|
+
};
|
|
1899
1730
|
for (const [moduleFilePathS, schema] of entries) {
|
|
1731
|
+
const moduleFilePath = moduleFilePathS;
|
|
1900
1732
|
const serialized = schema["executeSerialize"]();
|
|
1733
|
+
snapshot.schemas[moduleFilePath] = serialized;
|
|
1734
|
+
const sourceForModule = sources[moduleFilePath];
|
|
1735
|
+
if (sourceForModule !== undefined) {
|
|
1736
|
+
snapshot.sources[moduleFilePath] = sourceForModule;
|
|
1737
|
+
}
|
|
1901
1738
|
if (serialized.type === "record" && serialized.mediaType && serialized.directory) {
|
|
1902
1739
|
const dir = serialized.directory;
|
|
1903
1740
|
const existing = galleryDirectoryToModules.get(dir);
|
|
1904
1741
|
if (existing) {
|
|
1905
|
-
existing.push(
|
|
1742
|
+
existing.push(moduleFilePath);
|
|
1906
1743
|
} else {
|
|
1907
|
-
galleryDirectoryToModules.set(dir, [
|
|
1744
|
+
galleryDirectoryToModules.set(dir, [moduleFilePath]);
|
|
1908
1745
|
}
|
|
1909
1746
|
}
|
|
1910
1747
|
}
|
|
@@ -1962,78 +1799,12 @@ class ValOps {
|
|
|
1962
1799
|
}
|
|
1963
1800
|
} else if ((_validationError$fixe = validationError.fixes) !== null && _validationError$fixe !== void 0 && _validationError$fixe.includes("image:check-remote") || (_validationError$fixe2 = validationError.fixes) !== null && _validationError$fixe2 !== void 0 && _validationError$fixe2.includes("file:check-remote")) {
|
|
1964
1801
|
remoteFiles[sourcePath] = validationError.value;
|
|
1965
|
-
} else if ((_validationError$fixe3 = validationError.fixes) !== null && _validationError$fixe3 !== void 0 && _validationError$fixe3.includes("keyof:check-keys")) {
|
|
1966
|
-
const
|
|
1967
|
-
if (
|
|
1968
|
-
addError(
|
|
1969
|
-
message: `Could not find a value for keyOf at ${sourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
1970
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
1971
|
-
typeError: true
|
|
1972
|
-
});
|
|
1973
|
-
} else {
|
|
1974
|
-
if (typeof validationError.value !== "object") {
|
|
1975
|
-
addError({
|
|
1976
|
-
message: `Expected keyOf validation error to have a 'value' property of type 'object'. Found: ${typeof validationError.value}. ${TYPE_ERROR_MESSAGE}`,
|
|
1977
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
1978
|
-
typeError: true
|
|
1979
|
-
});
|
|
1980
|
-
} else {
|
|
1981
|
-
const key = "key" in validationError.value && validationError.value.key;
|
|
1982
|
-
const validationErrorSourcePath = "sourcePath" in validationError.value && validationError.value.sourcePath;
|
|
1983
|
-
if (typeof key !== "string") {
|
|
1984
|
-
addError({
|
|
1985
|
-
message: `Expected keyOf validation error 'value' to have property 'key' of type 'string'. Found: ${typeof key}. ${TYPE_ERROR_MESSAGE}`,
|
|
1986
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
1987
|
-
typeError: true
|
|
1988
|
-
});
|
|
1989
|
-
} else if (typeof validationErrorSourcePath !== "string") {
|
|
1990
|
-
addError({
|
|
1991
|
-
message: `Expected keyOf validation error 'value' to have property 'sourcePath' of type 'string'. Found: ${typeof validationErrorSourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
1992
|
-
// Not sure this is a type error, but it shouldn't happen in a normally functioning Val system
|
|
1993
|
-
typeError: true
|
|
1994
|
-
});
|
|
1995
|
-
} else {
|
|
1996
|
-
const res = await checkKeyIsValid(key, validationErrorSourcePath);
|
|
1997
|
-
if (res.error) {
|
|
1998
|
-
addError({
|
|
1999
|
-
message: res.message
|
|
2000
|
-
});
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
} else if ((_validationError$fixe4 = validationError.fixes) !== null && _validationError$fixe4 !== void 0 && _validationError$fixe4.includes("router:check-route")) {
|
|
2006
|
-
const TYPE_ERROR_MESSAGE = `This is most likely a Val version mismatch or Val bug.`;
|
|
2007
|
-
if (!validationError.value) {
|
|
2008
|
-
addError({
|
|
2009
|
-
message: `Could not find a value for route at ${sourcePath}. ${TYPE_ERROR_MESSAGE}`,
|
|
2010
|
-
typeError: true
|
|
2011
|
-
});
|
|
2012
|
-
} else {
|
|
2013
|
-
if (typeof validationError.value !== "object") {
|
|
2014
|
-
addError({
|
|
2015
|
-
message: `Expected route validation error to have a 'value' property of type 'object'. Found: ${typeof validationError.value}. ${TYPE_ERROR_MESSAGE}`,
|
|
2016
|
-
typeError: true
|
|
2017
|
-
});
|
|
2018
|
-
} else {
|
|
2019
|
-
const route = "route" in validationError.value && validationError.value.route;
|
|
2020
|
-
const includePattern = "include" in validationError.value && validationError.value.include;
|
|
2021
|
-
const excludePattern = "exclude" in validationError.value && validationError.value.exclude;
|
|
2022
|
-
if (typeof route !== "string") {
|
|
2023
|
-
addError({
|
|
2024
|
-
message: `Expected route validation error 'value' to have property 'route' of type 'string'. Found: ${typeof route}. ${TYPE_ERROR_MESSAGE}`,
|
|
2025
|
-
typeError: true
|
|
2026
|
-
});
|
|
2027
|
-
} else {
|
|
2028
|
-
const res = await checkRouteIsValid(route, includePattern && typeof includePattern === "object" && "source" in includePattern && "flags" in includePattern ? includePattern : undefined, excludePattern && typeof excludePattern === "object" && "source" in excludePattern && "flags" in excludePattern ? excludePattern : undefined);
|
|
2029
|
-
if (res.error) {
|
|
2030
|
-
addError({
|
|
2031
|
-
message: res.message
|
|
2032
|
-
});
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
1802
|
+
} else if ((_validationError$fixe3 = validationError.fixes) !== null && _validationError$fixe3 !== void 0 && _validationError$fixe3.includes("keyof:check-keys") || (_validationError$fixe4 = validationError.fixes) !== null && _validationError$fixe4 !== void 0 && _validationError$fixe4.includes("router:check-route")) {
|
|
1803
|
+
const resolved = resolveSchemaSourceFixForError(validationError, snapshot);
|
|
1804
|
+
if (resolved && resolved.status === "remaining") {
|
|
1805
|
+
addError(resolved.error);
|
|
2036
1806
|
}
|
|
1807
|
+
// resolved.status === "resolved" → drop silently
|
|
2037
1808
|
} else if ((_validationError$fixe5 = validationError.fixes) !== null && _validationError$fixe5 !== void 0 && _validationError$fixe5.includes("images:check-unique-folder") || (_validationError$fixe6 = validationError.fixes) !== null && _validationError$fixe6 !== void 0 && _validationError$fixe6.includes("files:check-unique-folder")) {
|
|
2038
1809
|
const TYPE_ERROR_MESSAGE = `This is most likely a Val version mismatch or Val bug.`;
|
|
2039
1810
|
if (!validationError.value || typeof validationError.value !== "object") {
|
|
@@ -5884,21 +5655,29 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
5884
5655
|
const schemasRes = await serverOps.getSchemas();
|
|
5885
5656
|
let sourcesRes = await serverOps.getSources();
|
|
5886
5657
|
const unpatchedSources = sourcesRes.sources;
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
...
|
|
5894
|
-
...
|
|
5895
|
-
}
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5658
|
+
// Default to true to keep the legacy contract for older clients.
|
|
5659
|
+
// The studio client always passes false: it owns patch application
|
|
5660
|
+
// and rendering, and treats /sources/~ as a pure un-patched read.
|
|
5661
|
+
const applyPatches = query.apply_patches !== false;
|
|
5662
|
+
if (applyPatches) {
|
|
5663
|
+
const onlyPatchedTreeModules = await serverOps.getSources({
|
|
5664
|
+
...patchAnalysis,
|
|
5665
|
+
...patchOps
|
|
5666
|
+
});
|
|
5667
|
+
sourcesRes = {
|
|
5668
|
+
sources: {
|
|
5669
|
+
...sourcesRes.sources,
|
|
5670
|
+
...(onlyPatchedTreeModules.sources || {})
|
|
5671
|
+
},
|
|
5672
|
+
errors: {
|
|
5673
|
+
...sourcesRes.errors,
|
|
5674
|
+
...(onlyPatchedTreeModules.errors || {})
|
|
5675
|
+
}
|
|
5676
|
+
};
|
|
5677
|
+
}
|
|
5678
|
+
const renderRes = applyPatches ? await serverOps.getRenders(schemasRes, sourcesRes.sources) : {
|
|
5679
|
+
renders: {}
|
|
5900
5680
|
};
|
|
5901
|
-
const renderRes = await serverOps.getRenders(schemasRes, sourcesRes.sources);
|
|
5902
5681
|
let sourcesValidation = {
|
|
5903
5682
|
errors: {},
|
|
5904
5683
|
files: {},
|
|
@@ -5946,7 +5725,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
|
5946
5725
|
const hasPatches = (((_patchAnalysis$patche2 = patchAnalysis.patchesByModule[moduleFilePath]) === null || _patchAnalysis$patche2 === void 0 ? void 0 : _patchAnalysis$patche2.length) ?? 0) > 0;
|
|
5947
5726
|
modules[moduleFilePath] = {
|
|
5948
5727
|
source: module,
|
|
5949
|
-
baseSource
|
|
5728
|
+
// baseSource is only meaningful when the server applied patches:
|
|
5729
|
+
// with apply_patches=false, `source` is already un-patched.
|
|
5730
|
+
baseSource: applyPatches && hasPatches ? unpatchedSources[moduleFilePath] : undefined,
|
|
5950
5731
|
render: renderRes.renders[moduleFilePath] || null,
|
|
5951
5732
|
patches: appliedPatches.length > 0 || skippedPatches.length > 0 || Object.keys(patchErrors).length > 0 ? {
|
|
5952
5733
|
applied: appliedPatches,
|
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.97.
|
|
19
|
+
"version": "0.97.2",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@prettier/sync": "^0.6.1",
|
|
22
22
|
"@types/jest": "^30.0.0"
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"typescript": "^5.9.3",
|
|
31
31
|
"zod": "^4.3.5",
|
|
32
32
|
"zod-validation-error": "^5.0.0",
|
|
33
|
-
"@valbuild/core": "0.97.
|
|
34
|
-
"@valbuild/shared": "0.97.
|
|
35
|
-
"@valbuild/ui": "0.97.
|
|
33
|
+
"@valbuild/core": "0.97.1",
|
|
34
|
+
"@valbuild/shared": "0.97.1",
|
|
35
|
+
"@valbuild/ui": "0.97.2"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">=18.17.0"
|