@valbuild/shared 0.146.4 → 0.148.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.
- package/CHANGELOG.md +128 -0
- package/client/dist/valbuild-shared-client.cjs.dev.js +2 -1
- package/client/dist/valbuild-shared-client.cjs.prod.js +2 -1
- package/client/dist/valbuild-shared-client.esm.js +1 -1
- package/dist/declarations/src/internal/ApiRoutes.d.ts +148 -0
- package/dist/declarations/src/internal/ValClient.d.ts +11 -1
- package/dist/declarations/src/internal/demo.d.ts +31 -0
- package/dist/declarations/src/internal/index.d.ts +2 -0
- package/dist/declarations/src/internal/localeAt.d.ts +29 -2
- package/dist/declarations/src/internal/media/encodeImageDecisions.d.ts +47 -0
- package/dist/declarations/src/internal/parseRoutePattern.d.ts +6 -0
- package/dist/declarations/src/internal/validation/partitionValidationErrors.d.ts +7 -0
- package/dist/declarations/src/internal/validation/studioFixes.d.ts +14 -0
- package/dist/{getSitemapTree-95b00d3f.cjs.dev.js → getSitemapTree-109be3b8.cjs.prod.js} +16 -0
- package/dist/{getSitemapTree-e65acefe.esm.js → getSitemapTree-c70ea145.esm.js} +16 -1
- package/dist/{getSitemapTree-b8dce0e2.cjs.prod.js → getSitemapTree-f6254b32.cjs.dev.js} +16 -0
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +387 -31
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +387 -31
- package/internal/dist/valbuild-shared-internal.esm.js +379 -34
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var getSitemapTree = require('../../dist/getSitemapTree-
|
|
5
|
+
var getSitemapTree = require('../../dist/getSitemapTree-f6254b32.cjs.dev.js');
|
|
6
6
|
var core = require('@valbuild/core');
|
|
7
7
|
var zod = require('zod');
|
|
8
8
|
var zodValidationError = require('zod-validation-error');
|
|
@@ -273,7 +273,7 @@ function convertImageNode(path, node, files, configDirectory, remoteOptions) {
|
|
|
273
273
|
} else {
|
|
274
274
|
console.error("Patched image URL does not start with /api/val/files: " + url);
|
|
275
275
|
}
|
|
276
|
-
} else if (
|
|
276
|
+
} else if (core.Internal.remote.splitRemoteRef(noParamsUrl).status === "success") ; else if (!noParamsUrl.startsWith("/public")) {
|
|
277
277
|
noParamsUrl = "/public".concat(noParamsUrl);
|
|
278
278
|
} else {
|
|
279
279
|
console.error("Unpatched image URL starts with /public: " + url);
|
|
@@ -1054,6 +1054,10 @@ var PatchBlock = zod.z.object({
|
|
|
1054
1054
|
parentRef: ParentRef$1
|
|
1055
1055
|
});
|
|
1056
1056
|
|
|
1057
|
+
var SourcePath = zod.z.string().transform(function (path) {
|
|
1058
|
+
return path;
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1057
1061
|
function _objectWithoutPropertiesLoose(r, e) {
|
|
1058
1062
|
if (null == r) return {};
|
|
1059
1063
|
var t = {};
|
|
@@ -1076,10 +1080,6 @@ function _objectWithoutProperties(e, t) {
|
|
|
1076
1080
|
return i;
|
|
1077
1081
|
}
|
|
1078
1082
|
|
|
1079
|
-
var SourcePath = zod.z.string().transform(function (path) {
|
|
1080
|
-
return path;
|
|
1081
|
-
});
|
|
1082
|
-
|
|
1083
1083
|
var ModuleFilePath$1 = zod.z.string().transform(function (path) {
|
|
1084
1084
|
return path;
|
|
1085
1085
|
});
|
|
@@ -1196,6 +1196,8 @@ var SerializedDiscriminatedUnionSchema = zod.z.lazy(function () {
|
|
|
1196
1196
|
var SerializedEnumSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
1197
1197
|
type: zod.z.literal("enum"),
|
|
1198
1198
|
values: zod.z.array(zod.z.string()),
|
|
1199
|
+
locales: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
1200
|
+
nullLocale: zod.z.string().optional(),
|
|
1199
1201
|
opt: zod.z["boolean"]()
|
|
1200
1202
|
}));
|
|
1201
1203
|
var ImageEncodeOption = zod.z.union([zod.z.literal(false), zod.z.object({
|
|
@@ -1275,6 +1277,7 @@ var SerializedRecordSchema = zod.z.lazy(function () {
|
|
|
1275
1277
|
render: FieldRender,
|
|
1276
1278
|
type: zod.z.literal("record"),
|
|
1277
1279
|
item: SerializedSchema,
|
|
1280
|
+
params: zod.z.record(zod.z.string(), SerializedSchema).optional(),
|
|
1278
1281
|
opt: zod.z["boolean"](),
|
|
1279
1282
|
// Optional gallery marker for files/images/videos
|
|
1280
1283
|
mediaType: zod.z.union([zod.z.literal("files"), zod.z.literal("images"), zod.z.literal("videos")]).optional(),
|
|
@@ -1618,7 +1621,7 @@ var ValConfig = zod.z.object({
|
|
|
1618
1621
|
gitCommit: zod.z.string().optional(),
|
|
1619
1622
|
gitBranch: zod.z.string().optional()
|
|
1620
1623
|
});
|
|
1621
|
-
var ValidationFixZ = zod.z.union([zod.z.literal("image:add-metadata"), zod.z.literal("image:check-metadata"), zod.z.literal("image:check-remote"), zod.z.literal("image:upload-remote"), zod.z.literal("image:download-remote"), zod.z.literal("images:check-remote"), zod.z.literal("images:upload-remote"), zod.z.literal("file:add-metadata"), zod.z.literal("video:add-metadata"), zod.z.literal("video:upload-remote"), zod.z.literal("video:download-remote"), zod.z.literal("videos:add-metadata"), zod.z.literal("videos:check-remote"), zod.z.literal("videos:upload-remote"), zod.z.literal("file:check-metadata"), zod.z.literal("file:check-remote"), zod.z.literal("file:upload-remote"), zod.z.literal("file:download-remote"), zod.z.literal("files:check-remote"), zod.z.literal("files:upload-remote"), zod.z.literal("keyof:check-keys"), zod.z.literal("image:check-gallery"), zod.z.literal("file:check-gallery"), zod.z.literal("video:check-gallery"), zod.z.literal("router:check-route"), zod.z.literal("locale:check-locale"), zod.z.literal("record:fill-keys"), zod.z.literal("images:check-unique-folder"), zod.z.literal("files:check-unique-folder"), zod.z.literal("images:check-all-files"), zod.z.literal("files:check-all-files"), zod.z.literal("videos:check-unique-folder"), zod.z.literal("videos:check-all-files"), zod.z.literal("jsonValues:extract-entry"), zod.z.literal("view:check-module")]);
|
|
1624
|
+
var ValidationFixZ = zod.z.union([zod.z.literal("image:add-metadata"), zod.z.literal("image:check-metadata"), zod.z.literal("image:check-remote"), zod.z.literal("image:upload-remote"), zod.z.literal("image:download-remote"), zod.z.literal("images:check-remote"), zod.z.literal("images:upload-remote"), zod.z.literal("file:add-metadata"), zod.z.literal("video:add-metadata"), zod.z.literal("video:upload-remote"), zod.z.literal("video:download-remote"), zod.z.literal("videos:add-metadata"), zod.z.literal("videos:check-remote"), zod.z.literal("videos:upload-remote"), zod.z.literal("file:check-metadata"), zod.z.literal("file:check-remote"), zod.z.literal("file:upload-remote"), zod.z.literal("file:download-remote"), zod.z.literal("files:check-remote"), zod.z.literal("files:upload-remote"), zod.z.literal("keyof:check-keys"), zod.z.literal("image:check-gallery"), zod.z.literal("file:check-gallery"), zod.z.literal("video:check-gallery"), zod.z.literal("router:check-route"), zod.z.literal("locale:check-locale"), zod.z.literal("router:check-locale-param"), zod.z.literal("record:fill-keys"), zod.z.literal("images:check-unique-folder"), zod.z.literal("files:check-unique-folder"), zod.z.literal("images:check-all-files"), zod.z.literal("files:check-all-files"), zod.z.literal("videos:check-unique-folder"), zod.z.literal("videos:check-all-files"), zod.z.literal("jsonValues:extract-entry"), zod.z.literal("view:check-module"), zod.z.literal("external:upload"), zod.z.literal("remote:rewrite-host")]);
|
|
1622
1625
|
var ValidationError = zod.z.object({
|
|
1623
1626
|
message: zod.z.string(),
|
|
1624
1627
|
value: zod.z.unknown().optional(),
|
|
@@ -2020,7 +2023,13 @@ var Api = {
|
|
|
2020
2023
|
coreVersion: zod.z.string(),
|
|
2021
2024
|
remoteFileBuckets: zod.z.array(zod.z.object({
|
|
2022
2025
|
bucket: zod.z.string()
|
|
2023
|
-
}))
|
|
2026
|
+
})),
|
|
2027
|
+
/**
|
|
2028
|
+
* The host new refs name, from the project's settings: its own
|
|
2029
|
+
* address for a Hosted project whose files are in R2. Optional,
|
|
2030
|
+
* for a content service that predates it.
|
|
2031
|
+
*/
|
|
2032
|
+
remoteHost: zod.z.string().optional()
|
|
2024
2033
|
})
|
|
2025
2034
|
}), zod.z.object({
|
|
2026
2035
|
status: zod.z.literal(400),
|
|
@@ -2766,6 +2775,105 @@ var Api = {
|
|
|
2766
2775
|
})])
|
|
2767
2776
|
}
|
|
2768
2777
|
},
|
|
2778
|
+
/**
|
|
2779
|
+
* The Studio's full check, one module per request: its sources against its
|
|
2780
|
+
* schema and its local files against their bytes, on the content the caller
|
|
2781
|
+
* is looking at. See `docs/plans/studio-validate.md`.
|
|
2782
|
+
*/
|
|
2783
|
+
"/validate": {
|
|
2784
|
+
POST: {
|
|
2785
|
+
req: {
|
|
2786
|
+
body: zod.z.object({
|
|
2787
|
+
moduleFilePath: ModuleFilePath,
|
|
2788
|
+
/**
|
|
2789
|
+
* The patches the caller is showing, applied over base. Omitted
|
|
2790
|
+
* means every pending patch, as `/sources/~`; empty means base.
|
|
2791
|
+
*/
|
|
2792
|
+
patchIds: zod.z.array(PatchId).optional()
|
|
2793
|
+
}),
|
|
2794
|
+
cookies: {
|
|
2795
|
+
val_session: zod.z.string().optional()
|
|
2796
|
+
}
|
|
2797
|
+
},
|
|
2798
|
+
res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
|
|
2799
|
+
status: zod.z.literal(500),
|
|
2800
|
+
json: zod.z.object({
|
|
2801
|
+
message: zod.z.string()
|
|
2802
|
+
})
|
|
2803
|
+
}), /** No full check on this server (one running in a browser tab). */
|
|
2804
|
+
zod.z.object({
|
|
2805
|
+
status: zod.z.literal(501),
|
|
2806
|
+
json: zod.z.object({
|
|
2807
|
+
message: zod.z.string()
|
|
2808
|
+
})
|
|
2809
|
+
}), zod.z.object({
|
|
2810
|
+
status: zod.z.literal(200),
|
|
2811
|
+
json: zod.z.object({
|
|
2812
|
+
moduleFilePath: ModuleFilePath,
|
|
2813
|
+
errors: zod.z.record(zod.z.string(), zod.z.array(ValidationError)),
|
|
2814
|
+
/** Set when the module's source could not be read at all. */
|
|
2815
|
+
invalidSource: zod.z.string().optional(),
|
|
2816
|
+
/**
|
|
2817
|
+
* Hosts that did not serve this module's remote files: one entry
|
|
2818
|
+
* per host, however many files it holds. Optional so a server
|
|
2819
|
+
* from before remote checks still parses.
|
|
2820
|
+
*/
|
|
2821
|
+
remoteHosts: zod.z.array(zod.z.object({
|
|
2822
|
+
host: zod.z.string(),
|
|
2823
|
+
status: zod.z.union([zod.z.literal("missing"), zod.z.literal("unreachable")]),
|
|
2824
|
+
details: zod.z.string(),
|
|
2825
|
+
sourcePaths: zod.z.array(SourcePath)
|
|
2826
|
+
})).optional()
|
|
2827
|
+
})
|
|
2828
|
+
})])
|
|
2829
|
+
}
|
|
2830
|
+
},
|
|
2831
|
+
/**
|
|
2832
|
+
* The patch that fixes one error the full check reported. The server finds
|
|
2833
|
+
* the error again rather than trusting the caller's copy, and builds only the
|
|
2834
|
+
* fixes `STUDIO_FIXES` lists. The patch is returned, not applied: the Studio
|
|
2835
|
+
* adds it as a pending change like any edit.
|
|
2836
|
+
*/
|
|
2837
|
+
"/validate/fix": {
|
|
2838
|
+
POST: {
|
|
2839
|
+
req: {
|
|
2840
|
+
body: zod.z.object({
|
|
2841
|
+
moduleFilePath: ModuleFilePath,
|
|
2842
|
+
sourcePath: SourcePath,
|
|
2843
|
+
fix: ValidationFixZ,
|
|
2844
|
+
patchIds: zod.z.array(PatchId).optional()
|
|
2845
|
+
}),
|
|
2846
|
+
cookies: {
|
|
2847
|
+
val_session: zod.z.string().optional()
|
|
2848
|
+
}
|
|
2849
|
+
},
|
|
2850
|
+
res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
|
|
2851
|
+
status: zod.z.literal(400),
|
|
2852
|
+
json: zod.z.object({
|
|
2853
|
+
message: zod.z.string()
|
|
2854
|
+
})
|
|
2855
|
+
}), zod.z.object({
|
|
2856
|
+
status: zod.z.literal(500),
|
|
2857
|
+
json: zod.z.object({
|
|
2858
|
+
message: zod.z.string()
|
|
2859
|
+
})
|
|
2860
|
+
}), /** No full check on this server (one running in a browser tab). */
|
|
2861
|
+
zod.z.object({
|
|
2862
|
+
status: zod.z.literal(501),
|
|
2863
|
+
json: zod.z.object({
|
|
2864
|
+
message: zod.z.string()
|
|
2865
|
+
})
|
|
2866
|
+
}), zod.z.object({
|
|
2867
|
+
status: zod.z.literal(200),
|
|
2868
|
+
json: zod.z.object({
|
|
2869
|
+
patch: Patch,
|
|
2870
|
+
remainingErrors: zod.z.array(ValidationError.extend({
|
|
2871
|
+
sourcePath: zod.z.string().optional()
|
|
2872
|
+
}))
|
|
2873
|
+
})
|
|
2874
|
+
})])
|
|
2875
|
+
}
|
|
2876
|
+
},
|
|
2769
2877
|
"/publish-job-prepare": {
|
|
2770
2878
|
POST: {
|
|
2771
2879
|
req: {
|
|
@@ -3745,8 +3853,11 @@ function detailsOf(json) {
|
|
|
3745
3853
|
}
|
|
3746
3854
|
var DEFAULT_ERROR_MESSAGE = "Unknown error with unknown message from server";
|
|
3747
3855
|
|
|
3748
|
-
var createValClient = function createValClient(host, config
|
|
3749
|
-
|
|
3856
|
+
var createValClient = function createValClient(host, config, options) {
|
|
3857
|
+
var _options$fetch;
|
|
3858
|
+
var send = (_options$fetch = options === null || options === void 0 ? void 0 : options.fetch) !== null && _options$fetch !== void 0 ? _options$fetch : function (input, init) {
|
|
3859
|
+
return fetch(input, init);
|
|
3860
|
+
};
|
|
3750
3861
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3751
3862
|
var anyApi = Api;
|
|
3752
3863
|
return /*#__PURE__*/function () {
|
|
@@ -3837,7 +3948,7 @@ var createValClient = function createValClient(host, config // We want to use th
|
|
|
3837
3948
|
case 2:
|
|
3838
3949
|
_context2.p = 2;
|
|
3839
3950
|
_context2.n = 3;
|
|
3840
|
-
return
|
|
3951
|
+
return send("".concat(host).concat(fullPath), {
|
|
3841
3952
|
method: method,
|
|
3842
3953
|
headers: {
|
|
3843
3954
|
"Content-Type": "application/json"
|
|
@@ -3971,6 +4082,29 @@ function isRetryable(error) {
|
|
|
3971
4082
|
return false;
|
|
3972
4083
|
}
|
|
3973
4084
|
|
|
4085
|
+
/**
|
|
4086
|
+
* A Val demo, as the page hands it to the Studio.
|
|
4087
|
+
*
|
|
4088
|
+
* In a demo the Studio talks to Val's own server running in the same tab
|
|
4089
|
+
* (`@valbuild/server/browser`) instead of to an API route, and the page that
|
|
4090
|
+
* starts that server is the app's (`<ValApp demo>`) while the Studio is a
|
|
4091
|
+
* separate bundle loaded by a script tag. A window property is how the two
|
|
4092
|
+
* meet, the same way `window.__VAL_MODULES__` hands the Studio the project's
|
|
4093
|
+
* modules. See `docs/plans/demo-mode.md`.
|
|
4094
|
+
*/
|
|
4095
|
+
|
|
4096
|
+
/*
|
|
4097
|
+
* A global `var` rather than a `Window` member: this package is compiled
|
|
4098
|
+
* without the DOM's types, and a `var` in global scope is also a property of
|
|
4099
|
+
* `window` where they exist.
|
|
4100
|
+
*/
|
|
4101
|
+
|
|
4102
|
+
/** The demo this page was started with, or null outside a demo. */
|
|
4103
|
+
function getValDemo() {
|
|
4104
|
+
var _globalThis$__VAL_DEM;
|
|
4105
|
+
return (_globalThis$__VAL_DEM = globalThis.__VAL_DEMO__) !== null && _globalThis$__VAL_DEM !== void 0 ? _globalThis$__VAL_DEM : null;
|
|
4106
|
+
}
|
|
4107
|
+
|
|
3974
4108
|
function _arrayWithHoles(r) {
|
|
3975
4109
|
if (Array.isArray(r)) return r;
|
|
3976
4110
|
}
|
|
@@ -4850,7 +4984,7 @@ function declaredLocales(snapshot) {
|
|
|
4850
4984
|
* these has to resolve all of them, and the two that leaked did so by adding a
|
|
4851
4985
|
* fix here and not to a condition somewhere else.
|
|
4852
4986
|
*/
|
|
4853
|
-
var SCHEMA_SOURCE_FIXES = ["keyof:check-keys", "image:check-gallery", "file:check-gallery", "video:check-gallery", "router:check-route", "locale:check-locale", "record:fill-keys"];
|
|
4987
|
+
var SCHEMA_SOURCE_FIXES = ["keyof:check-keys", "image:check-gallery", "file:check-gallery", "video:check-gallery", "router:check-route", "locale:check-locale", "router:check-locale-param", "record:fill-keys"];
|
|
4854
4988
|
|
|
4855
4989
|
/** Whether an error is a marker only the whole project can answer. */
|
|
4856
4990
|
function isSchemaSourceFixError(error) {
|
|
@@ -5040,21 +5174,51 @@ function resolveSchemaSourceFixForError(error, snapshot) {
|
|
|
5040
5174
|
})
|
|
5041
5175
|
};
|
|
5042
5176
|
}
|
|
5043
|
-
if (fixes.includes("
|
|
5177
|
+
if (fixes.includes("router:check-locale-param")) {
|
|
5044
5178
|
var _value = error.value;
|
|
5045
|
-
|
|
5179
|
+
var _ref7 = getSitemapTree._typeof(_value) === "object" && _value !== null ? _value : {},
|
|
5180
|
+
name = _ref7.name,
|
|
5181
|
+
segment = _ref7.segment;
|
|
5182
|
+
if (typeof name !== "string" || typeof segment !== "string") {
|
|
5183
|
+
return {
|
|
5184
|
+
status: "remaining",
|
|
5185
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
5186
|
+
message: "Expected route locale parameter validation error to have a 'value' with 'name' and 'segment'. ".concat(TYPE_ERROR_MESSAGE),
|
|
5187
|
+
typeError: true,
|
|
5188
|
+
fixes: undefined
|
|
5189
|
+
})
|
|
5190
|
+
};
|
|
5191
|
+
}
|
|
5192
|
+
// A project that declares no languages is not translated, and a
|
|
5193
|
+
// `[locale]` segment there is the app's own business.
|
|
5194
|
+
if (declaredLocales(snapshot).length === 0) {
|
|
5195
|
+
return {
|
|
5196
|
+
status: "resolved"
|
|
5197
|
+
};
|
|
5198
|
+
}
|
|
5199
|
+
return {
|
|
5200
|
+
status: "remaining",
|
|
5201
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
5202
|
+
message: "This route has a '".concat(name, "' segment (").concat(segment, "), but nothing says which of the project's languages it can be, so its pages are not in any language and '/xx/\u2026' validates. Give the parameter a locale schema: s.router(router, { ").concat(name, ": urlLocale, \u2026 }, item), where urlLocale is an s.enum(\u2026).locales({ \u2026 }) or s.locale(). If '").concat(name, "' is not a language here, give it a schema of its own instead, e.g. { ").concat(name, ": s.enum(\u2026) }."),
|
|
5203
|
+
fixes: undefined
|
|
5204
|
+
})
|
|
5205
|
+
};
|
|
5206
|
+
}
|
|
5207
|
+
if (fixes.includes("record:fill-keys")) {
|
|
5208
|
+
var _value2 = error.value;
|
|
5209
|
+
if (getSitemapTree._typeof(_value2) !== "object" || _value2 === null) {
|
|
5046
5210
|
return {
|
|
5047
5211
|
status: "remaining",
|
|
5048
5212
|
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
5049
|
-
message: "Expected record key validation error to have a 'value' object. Found: ".concat(getSitemapTree._typeof(
|
|
5213
|
+
message: "Expected record key validation error to have a 'value' object. Found: ".concat(getSitemapTree._typeof(_value2), ". ").concat(TYPE_ERROR_MESSAGE),
|
|
5050
5214
|
typeError: true,
|
|
5051
5215
|
fixes: undefined
|
|
5052
5216
|
})
|
|
5053
5217
|
};
|
|
5054
5218
|
}
|
|
5055
|
-
var
|
|
5056
|
-
present =
|
|
5057
|
-
declared =
|
|
5219
|
+
var _ref8 = _value2,
|
|
5220
|
+
present = _ref8.present,
|
|
5221
|
+
declared = _ref8.declared;
|
|
5058
5222
|
if (!Array.isArray(present)) {
|
|
5059
5223
|
return {
|
|
5060
5224
|
status: "remaining",
|
|
@@ -5206,7 +5370,8 @@ function resolveSchemaSourceFixes(validationErrors, snapshot) {
|
|
|
5206
5370
|
*
|
|
5207
5371
|
* THE question the whole feature turns on. A locale scope is a subtree in one
|
|
5208
5372
|
* language, and three things open one: a `locale` field on an object, a record
|
|
5209
|
-
* keyed by `s.locale()`, and a locale
|
|
5373
|
+
* keyed by `s.locale()`, and a locale parameter in a router's key
|
|
5374
|
+
* (`s.router(router, { locale: … }, item)`, where the URL names the language). Once this can
|
|
5210
5375
|
* be answered from the schema and the source alone, everything downstream falls
|
|
5211
5376
|
* out of it — the Studio's locale filter, deep links, `<html lang>`, and knowing
|
|
5212
5377
|
* what to translate from and into.
|
|
@@ -5235,7 +5400,79 @@ function localeAt(path, snapshot) {
|
|
|
5235
5400
|
return null;
|
|
5236
5401
|
}
|
|
5237
5402
|
var segments = modulePath ? core.Internal.splitModulePath(modulePath) : [];
|
|
5238
|
-
return walk(schema, source, segments, available);
|
|
5403
|
+
return walk(schema, source, segments, available, moduleFilePath);
|
|
5404
|
+
}
|
|
5405
|
+
|
|
5406
|
+
/**
|
|
5407
|
+
* The language a locale schema's value MEANS, or `null` if it means none of
|
|
5408
|
+
* the project's.
|
|
5409
|
+
*
|
|
5410
|
+
* `s.locale()` stores the tag itself. An enum with `.locales(...)` stores a
|
|
5411
|
+
* value that stands for one — `nb` for `nb-NO` — and, on a router parameter,
|
|
5412
|
+
* `null` for a URL that left the segment out, which `{ null: tag }` names.
|
|
5413
|
+
* Anything else is not a locale and means nothing here.
|
|
5414
|
+
*
|
|
5415
|
+
* Callers reading a FIELD pass only strings: a field that holds `null` has no
|
|
5416
|
+
* language, whatever its schema says about URLs.
|
|
5417
|
+
*/
|
|
5418
|
+
function localeMeantBy(schema, value, available) {
|
|
5419
|
+
if (schema.type === "locale") {
|
|
5420
|
+
return value === null ? null : core.localeOfValue(value, available);
|
|
5421
|
+
}
|
|
5422
|
+
if (schema.type === "enum" && schema.locales !== undefined) {
|
|
5423
|
+
var tag = enumLocaleTag(schema, value);
|
|
5424
|
+
return tag === undefined ? null : core.localeOfValue(tag, available);
|
|
5425
|
+
}
|
|
5426
|
+
return null;
|
|
5427
|
+
}
|
|
5428
|
+
|
|
5429
|
+
/**
|
|
5430
|
+
* The tag an enum's `.locales(...)` maps a value to, as written — `null` is
|
|
5431
|
+
* the `{ null }` mapping — or `undefined` where it maps none.
|
|
5432
|
+
*
|
|
5433
|
+
* An own property: a plain object inherits `toString` and the rest, and an
|
|
5434
|
+
* enum value is allowed to be spelled like one.
|
|
5435
|
+
*/
|
|
5436
|
+
function enumLocaleTag(schema, value) {
|
|
5437
|
+
if (value === null) {
|
|
5438
|
+
return schema.nullLocale;
|
|
5439
|
+
}
|
|
5440
|
+
return schema.locales !== undefined && Object.prototype.hasOwnProperty.call(schema.locales, value) ? schema.locales[value] : undefined;
|
|
5441
|
+
}
|
|
5442
|
+
|
|
5443
|
+
/**
|
|
5444
|
+
* Whether a schema is a locale: `s.locale()`, or an enum `.locales(...)` made
|
|
5445
|
+
* one.
|
|
5446
|
+
*/
|
|
5447
|
+
function isLocaleSchema(schema) {
|
|
5448
|
+
return schema.type === "locale" || schema.type === "enum" && schema.locales !== undefined;
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5451
|
+
/**
|
|
5452
|
+
* The language a router's key is in, where one of its route parameters is a
|
|
5453
|
+
* locale — `/nb/blog/hei` is `nb-NO` when `locale` maps `nb` to it.
|
|
5454
|
+
*/
|
|
5455
|
+
function localeOfRouteKey(schema, moduleFilePath, key, available) {
|
|
5456
|
+
if (schema.params === undefined || schema.router === undefined) {
|
|
5457
|
+
return null;
|
|
5458
|
+
}
|
|
5459
|
+
var pattern = core.routePatternOf(schema.router, moduleFilePath);
|
|
5460
|
+
if (pattern === null) {
|
|
5461
|
+
return null;
|
|
5462
|
+
}
|
|
5463
|
+
var values = core.matchRoutePattern(key, pattern);
|
|
5464
|
+
if (values === null) {
|
|
5465
|
+
return null;
|
|
5466
|
+
}
|
|
5467
|
+
for (var _i = 0, _Object$entries = Object.entries(schema.params); _i < _Object$entries.length; _i++) {
|
|
5468
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
5469
|
+
name = _Object$entries$_i[0],
|
|
5470
|
+
param = _Object$entries$_i[1];
|
|
5471
|
+
if (isLocaleSchema(param) && Object.prototype.hasOwnProperty.call(values, name)) {
|
|
5472
|
+
return localeMeantBy(param, values[name], available);
|
|
5473
|
+
}
|
|
5474
|
+
}
|
|
5475
|
+
return null;
|
|
5239
5476
|
}
|
|
5240
5477
|
|
|
5241
5478
|
/**
|
|
@@ -5250,7 +5487,7 @@ function localeAt(path, snapshot) {
|
|
|
5250
5487
|
* these can fire on a well-formed path; taking the innermost is what makes the
|
|
5251
5488
|
* answer well-defined while a project is mid-fix.
|
|
5252
5489
|
*/
|
|
5253
|
-
function walk(schema, source, segments, available) {
|
|
5490
|
+
function walk(schema, source, segments, available, moduleFilePath) {
|
|
5254
5491
|
var entered = enter(schema, source, available);
|
|
5255
5492
|
var locale = entered.locale;
|
|
5256
5493
|
var currentSchema = entered.schema;
|
|
@@ -5264,14 +5501,21 @@ function walk(schema, source, segments, available) {
|
|
|
5264
5501
|
return locale;
|
|
5265
5502
|
}
|
|
5266
5503
|
if (currentSchema.type === "record") {
|
|
5267
|
-
|
|
5268
|
-
if (((_currentSchema$key = currentSchema.key) === null || _currentSchema$key === void 0 ? void 0 : _currentSchema$key.type) === "locale") {
|
|
5504
|
+
if (currentSchema.key !== undefined && isLocaleSchema(currentSchema.key)) {
|
|
5269
5505
|
// In a locale-keyed record the KEY is the language, so the segment we
|
|
5270
|
-
// are about to take is the answer.
|
|
5271
|
-
|
|
5506
|
+
// are about to take is the answer — the tag itself for `s.locale()`,
|
|
5507
|
+
// the tag it stands for when the key is an enum with `.locales()`.
|
|
5508
|
+
var resolved = localeMeantBy(currentSchema.key, segment, available);
|
|
5272
5509
|
if (resolved !== null) {
|
|
5273
5510
|
locale = resolved;
|
|
5274
5511
|
}
|
|
5512
|
+
} else if (currentSchema.params !== undefined) {
|
|
5513
|
+
// A router whose URL names the language: the key is a URL, and one of
|
|
5514
|
+
// its parameters is the answer.
|
|
5515
|
+
var _resolved = localeOfRouteKey(currentSchema, moduleFilePath, segment, available);
|
|
5516
|
+
if (_resolved !== null) {
|
|
5517
|
+
locale = _resolved;
|
|
5518
|
+
}
|
|
5275
5519
|
}
|
|
5276
5520
|
currentSchema = currentSchema.item;
|
|
5277
5521
|
} else if (currentSchema.type === "array") {
|
|
@@ -5327,18 +5571,18 @@ function localeOfObjectField(schema, source, available) {
|
|
|
5327
5571
|
if (schema.type !== "object" || !isJsonObject(source)) {
|
|
5328
5572
|
return null;
|
|
5329
5573
|
}
|
|
5330
|
-
for (var
|
|
5331
|
-
var _Object$
|
|
5332
|
-
key = _Object$
|
|
5333
|
-
item = _Object$
|
|
5334
|
-
if (item
|
|
5574
|
+
for (var _i2 = 0, _Object$entries2 = Object.entries(schema.items); _i2 < _Object$entries2.length; _i2++) {
|
|
5575
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
5576
|
+
key = _Object$entries2$_i[0],
|
|
5577
|
+
item = _Object$entries2$_i[1];
|
|
5578
|
+
if (!isLocaleSchema(item)) {
|
|
5335
5579
|
continue;
|
|
5336
5580
|
}
|
|
5337
5581
|
var value = source[key];
|
|
5338
5582
|
if (typeof value !== "string") {
|
|
5339
5583
|
return null;
|
|
5340
5584
|
}
|
|
5341
|
-
return
|
|
5585
|
+
return localeMeantBy(item, value, available);
|
|
5342
5586
|
}
|
|
5343
5587
|
return null;
|
|
5344
5588
|
}
|
|
@@ -6173,6 +6417,16 @@ function partitionValidationErrors(validationErrors) {
|
|
|
6173
6417
|
skipped: skipped
|
|
6174
6418
|
};
|
|
6175
6419
|
}
|
|
6420
|
+
|
|
6421
|
+
/**
|
|
6422
|
+
* Whether the Studio leaves this error to the server, which repairs it on
|
|
6423
|
+
* save, rather than showing it and holding a publish back for it. One rule
|
|
6424
|
+
* for every gate: `val publish` asks the same question, so the CLI does not
|
|
6425
|
+
* refuse what the Studio would publish.
|
|
6426
|
+
*/
|
|
6427
|
+
function isRepairedOnSave(error) {
|
|
6428
|
+
return isSkippedFix(error);
|
|
6429
|
+
}
|
|
6176
6430
|
function isSkippedFix(error) {
|
|
6177
6431
|
var _error$fixes;
|
|
6178
6432
|
var fixes = (_error$fixes = error.fixes) !== null && _error$fixes !== void 0 ? _error$fixes : [];
|
|
@@ -6227,6 +6481,7 @@ function isSkippableFixCode(fix) {
|
|
|
6227
6481
|
case "video:check-gallery":
|
|
6228
6482
|
case "router:check-route":
|
|
6229
6483
|
case "locale:check-locale":
|
|
6484
|
+
case "router:check-locale-param":
|
|
6230
6485
|
case "record:fill-keys":
|
|
6231
6486
|
case "jsonValues:extract-entry":
|
|
6232
6487
|
// `jsonValues:extract-entry` is an entry inlined in the `.val.ts`. The
|
|
@@ -6241,6 +6496,12 @@ function isSkippableFixCode(fix) {
|
|
|
6241
6496
|
// under `val external upload` and never under a blanket `--fix`. Surfacing
|
|
6242
6497
|
// it is the whole point: someone has to decide.
|
|
6243
6498
|
return false;
|
|
6499
|
+
case "remote:rewrite-host":
|
|
6500
|
+
// Reported only by the server's full check (the Studio's Validate page,
|
|
6501
|
+
// `val validate`), which asks the ref's host -- never by a schema, so
|
|
6502
|
+
// the Studio's own validator never holds one. Were it to, a person has
|
|
6503
|
+
// to see it: the host is gone, and nothing on save repoints the ref.
|
|
6504
|
+
return false;
|
|
6244
6505
|
default:
|
|
6245
6506
|
{
|
|
6246
6507
|
return false;
|
|
@@ -6280,6 +6541,33 @@ function filterBlockingValidationErrors(validationErrors, schemas, sources) {
|
|
|
6280
6541
|
return partitionValidationErrors(resolved).surfaced;
|
|
6281
6542
|
}
|
|
6282
6543
|
|
|
6544
|
+
/**
|
|
6545
|
+
* The fixes the Studio's full check offers a **Fix** button for.
|
|
6546
|
+
*
|
|
6547
|
+
* Each is one `createFixPatch` can build without a disk: it reads a file's
|
|
6548
|
+
* bytes through `FixFiles`, or needs no bytes at all. The server refuses any
|
|
6549
|
+
* other code on `/validate/fix`, and the Studio shows those errors with the
|
|
6550
|
+
* command to run instead of a button — so a code is added here when its fix
|
|
6551
|
+
* can run in http mode and on the platform, not before. See
|
|
6552
|
+
* `docs/plans/studio-validate.md`, "Order of work".
|
|
6553
|
+
*/
|
|
6554
|
+
var STUDIO_FIXES = ["image:add-metadata", "image:check-metadata", "file:add-metadata", "file:check-metadata", "video:add-metadata", "videos:add-metadata", "view:check-module",
|
|
6555
|
+
// A stale remote ref: re-read through `FixFiles.readRemoteFile`, rewritten
|
|
6556
|
+
// on the host it was already on.
|
|
6557
|
+
"image:check-remote", "file:check-remote",
|
|
6558
|
+
// One entry of an `s.imagedir()` / `s.filedir()`: removed when its file is
|
|
6559
|
+
// gone, rewritten from its bytes when they disagree. Built for that entry
|
|
6560
|
+
// alone, never the whole directory (`fixForStudio`).
|
|
6561
|
+
"images:check-all-files", "files:check-all-files",
|
|
6562
|
+
// A platform ref on a host that no longer serves its project, pointed at
|
|
6563
|
+
// the project's own `valstart.dev` address. Derived from the ref alone.
|
|
6564
|
+
"remote:rewrite-host"];
|
|
6565
|
+
function isStudioFix(fix) {
|
|
6566
|
+
return STUDIO_FIXES.some(function (studioFix) {
|
|
6567
|
+
return studioFix === fix;
|
|
6568
|
+
});
|
|
6569
|
+
}
|
|
6570
|
+
|
|
6283
6571
|
/**
|
|
6284
6572
|
* Every decision `encode` makes, with none of the pixels.
|
|
6285
6573
|
*
|
|
@@ -6388,6 +6676,63 @@ function isSkippedSource(sourceMimeType, targetMimeType, needsDownscale) {
|
|
|
6388
6676
|
return sourceMimeType === targetMimeType && !needsDownscale;
|
|
6389
6677
|
}
|
|
6390
6678
|
|
|
6679
|
+
/**
|
|
6680
|
+
* The types the Studio can write with WebAssembly when the canvas cannot.
|
|
6681
|
+
*
|
|
6682
|
+
* libwebp, compiled to WebAssembly (`@jsquash/webp`, loaded by
|
|
6683
|
+
* `packages/ui/spa/utils/webpWasm.ts`). One entry because `encode` has one
|
|
6684
|
+
* `type`; a second type is a second encoder to host, not a second string here.
|
|
6685
|
+
*/
|
|
6686
|
+
var WASM_ENCODED_MIME_TYPES = ["image/webp"];
|
|
6687
|
+
|
|
6688
|
+
/**
|
|
6689
|
+
* Whether to encode the canvas's pixels with WebAssembly, given what the
|
|
6690
|
+
* canvas's own encoder handed back.
|
|
6691
|
+
*
|
|
6692
|
+
* `canvas.toBlob` answers a type it cannot write with a PNG instead of an error,
|
|
6693
|
+
* and Safari -- the browser people take their photos in -- cannot write WebP.
|
|
6694
|
+
* The pixels on that canvas are already decoded, oriented and scaled, so the
|
|
6695
|
+
* only thing missing is the encoder, and libwebp in WebAssembly is that.
|
|
6696
|
+
*
|
|
6697
|
+
* Only then, and that is what keeps the WebAssembly lazy: a browser whose
|
|
6698
|
+
* canvas wrote the type is never asked to download an encoder, even when its
|
|
6699
|
+
* WebP then loses to the original on size -- a second encoder of the same
|
|
6700
|
+
* format would lose for the same reason.
|
|
6701
|
+
*
|
|
6702
|
+
* `null` -- no blob at all -- is not "cannot write this type" either. It is a
|
|
6703
|
+
* canvas that failed to serialize anything, under memory pressure for instance,
|
|
6704
|
+
* and says nothing about WebP: a Chromium tab that hits it is still a browser
|
|
6705
|
+
* that writes WebP, and must not start downloading an encoder because of it.
|
|
6706
|
+
*/
|
|
6707
|
+
function shouldEncodeWithWasm(input) {
|
|
6708
|
+
return WASM_ENCODED_MIME_TYPES.includes(input.targetMimeType) && input.canvasOutputType !== null && input.canvasOutputType !== input.targetMimeType;
|
|
6709
|
+
}
|
|
6710
|
+
|
|
6711
|
+
/**
|
|
6712
|
+
* What to scale an image down to when nothing could write the type asked for:
|
|
6713
|
+
* the source's own format, when it is one every canvas can write.
|
|
6714
|
+
*
|
|
6715
|
+
* The second fallback, after {@link shouldEncodeWithWasm}: it is what a browser
|
|
6716
|
+
* whose canvas cannot write WebP gets when the WebAssembly encoder could not be
|
|
6717
|
+
* loaded either (offline, a blocked host, a failed instantiation). Without it,
|
|
6718
|
+
* `chooseEncoded` would rightly refuse the canvas's PNG and upload the original
|
|
6719
|
+
* -- every photo at the camera's full size, the one case `maxWidth` exists
|
|
6720
|
+
* for. Scaling it down as a JPEG keeps the half of `encode` this browser can do.
|
|
6721
|
+
*
|
|
6722
|
+
* Only when a downscale is needed: re-encoding a JPEG that already fits, as a
|
|
6723
|
+
* JPEG, is a second generation of loss for a few percent. And never into a
|
|
6724
|
+
* type `accept` refuses, for the reason `isMimeTypeAccepted` gives.
|
|
6725
|
+
*/
|
|
6726
|
+
function fallbackMimeType(sourceMimeType, needsDownscale, accept) {
|
|
6727
|
+
if (!needsDownscale) {
|
|
6728
|
+
return null;
|
|
6729
|
+
}
|
|
6730
|
+
if (sourceMimeType !== "image/jpeg" && sourceMimeType !== "image/png") {
|
|
6731
|
+
return null;
|
|
6732
|
+
}
|
|
6733
|
+
return isMimeTypeAccepted(sourceMimeType, accept) ? sourceMimeType : null;
|
|
6734
|
+
}
|
|
6735
|
+
|
|
6391
6736
|
/**
|
|
6392
6737
|
* Whether to upload what the encoder produced, or the file that was picked.
|
|
6393
6738
|
*
|
|
@@ -8584,6 +8929,7 @@ exports.VAL_CANVAS_MESSAGE = getSitemapTree.VAL_CANVAS_MESSAGE;
|
|
|
8584
8929
|
exports.VAL_CANVAS_PARAM = getSitemapTree.VAL_CANVAS_PARAM;
|
|
8585
8930
|
exports.VAL_CONFIG_SESSION_STORAGE_KEY = getSitemapTree.VAL_CONFIG_SESSION_STORAGE_KEY;
|
|
8586
8931
|
exports.VAL_THEME_SESSION_STORAGE_KEY = getSitemapTree.VAL_THEME_SESSION_STORAGE_KEY;
|
|
8932
|
+
exports.formatRoutePattern = getSitemapTree.formatRoutePattern;
|
|
8587
8933
|
exports.getNextAppRouterSourceFolder = getSitemapTree.getNextAppRouterSourceFolder;
|
|
8588
8934
|
exports.getPageRouterSitemapTree = getSitemapTree.getPageRouterSitemapTree;
|
|
8589
8935
|
exports.getPageRouterSourceFolder = getSitemapTree.getPageRouterSourceFolder;
|
|
@@ -8640,6 +8986,7 @@ exports.RemirrorTextMark = RemirrorTextMark;
|
|
|
8640
8986
|
exports.RestoreVerdict = RestoreVerdict;
|
|
8641
8987
|
exports.RichTextOptions = RichTextOptions;
|
|
8642
8988
|
exports.SCHEMA_SOURCE_FIXES = SCHEMA_SOURCE_FIXES;
|
|
8989
|
+
exports.STUDIO_FIXES = STUDIO_FIXES;
|
|
8643
8990
|
exports.SerializedArraySchema = SerializedArraySchema;
|
|
8644
8991
|
exports.SerializedBooleanSchema = SerializedBooleanSchema;
|
|
8645
8992
|
exports.SerializedCodeSchema = SerializedCodeSchema;
|
|
@@ -8673,6 +9020,7 @@ exports.ValCommit = ValCommit;
|
|
|
8673
9020
|
exports.ValDeployment = ValDeployment;
|
|
8674
9021
|
exports.VideoOptions = VideoOptions;
|
|
8675
9022
|
exports.VideoStreamOption = VideoStreamOption;
|
|
9023
|
+
exports.WASM_ENCODED_MIME_TYPES = WASM_ENCODED_MIME_TYPES;
|
|
8676
9024
|
exports.accentRamp = accentRamp;
|
|
8677
9025
|
exports.buildDuplicatePatch = buildDuplicatePatch;
|
|
8678
9026
|
exports.buildEmptyAtPathPatch = buildEmptyAtPathPatch;
|
|
@@ -8691,7 +9039,9 @@ exports.createValClient = createValClient;
|
|
|
8691
9039
|
exports.declaredLocales = declaredLocales;
|
|
8692
9040
|
exports.describeContainerAtPath = describeContainerAtPath;
|
|
8693
9041
|
exports.emptyOf = emptyOf;
|
|
9042
|
+
exports.enumLocaleTag = enumLocaleTag;
|
|
8694
9043
|
exports.explainIncompatible = explainIncompatible;
|
|
9044
|
+
exports.fallbackMimeType = fallbackMimeType;
|
|
8695
9045
|
exports.filterBlockingValidationErrors = filterBlockingValidationErrors;
|
|
8696
9046
|
exports.filterRoutesByPatterns = filterRoutesByPatterns;
|
|
8697
9047
|
exports.findSimilar = findSimilar;
|
|
@@ -8706,16 +9056,21 @@ exports.getRefParts = getRefParts;
|
|
|
8706
9056
|
exports.getRoutesOf = getRoutesOf;
|
|
8707
9057
|
exports.getRoutesWithModulePaths = getRoutesWithModulePaths;
|
|
8708
9058
|
exports.getSourceAt = getSourceAt;
|
|
9059
|
+
exports.getValDemo = getValDemo;
|
|
8709
9060
|
exports.indexModule = indexModule;
|
|
8710
9061
|
exports.isInsidePatchSetPath = isInsidePatchSetPath;
|
|
9062
|
+
exports.isLocaleSchema = isLocaleSchema;
|
|
8711
9063
|
exports.isMimeTypeAccepted = isMimeTypeAccepted;
|
|
8712
9064
|
exports.isRemoteSchema = isRemoteSchema;
|
|
9065
|
+
exports.isRepairedOnSave = isRepairedOnSave;
|
|
8713
9066
|
exports.isSchemaSourceFixError = isSchemaSourceFixError;
|
|
8714
9067
|
exports.isSkippedSource = isSkippedSource;
|
|
9068
|
+
exports.isStudioFix = isStudioFix;
|
|
8715
9069
|
exports.joinSharedChanges = joinSharedChanges;
|
|
8716
9070
|
exports.keyOfRecordPath = keyOfRecordPath;
|
|
8717
9071
|
exports.levenshtein = levenshtein;
|
|
8718
9072
|
exports.localeAt = localeAt;
|
|
9073
|
+
exports.localeMeantBy = localeMeantBy;
|
|
8719
9074
|
exports.memoizePerRequest = memoizePerRequest;
|
|
8720
9075
|
exports.newestCommitSha = newestCommitSha;
|
|
8721
9076
|
exports.parseArtifacts = parseArtifacts;
|
|
@@ -8751,6 +9106,7 @@ exports.safeParsePatch = safeParsePatch;
|
|
|
8751
9106
|
exports.schemaErrorsOf = schemaErrorsOf;
|
|
8752
9107
|
exports.schemaTypesOfPath = schemaTypesOfPath;
|
|
8753
9108
|
exports.selectionClosure = selectionClosure;
|
|
9109
|
+
exports.shouldEncodeWithWasm = shouldEncodeWithWasm;
|
|
8754
9110
|
exports.sideFiles = sideFiles;
|
|
8755
9111
|
exports.sideSource = sideSource;
|
|
8756
9112
|
exports.sourcePathOfChild = sourcePathOfChild;
|