@valbuild/shared 0.126.0 → 0.128.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 +133 -0
- package/client/dist/valbuild-shared-client.esm.js +1 -1
- package/dist/declarations/src/internal/ApiRoutes.d.ts +1 -1
- package/dist/declarations/src/internal/aiTools/aiImageToolPatches.d.ts +1 -1
- package/dist/declarations/src/internal/aiTools/aiSourceToolPatches.d.ts +2 -1
- package/dist/declarations/src/internal/emptyOf.d.ts +24 -1
- package/dist/declarations/src/internal/index.d.ts +1 -0
- package/dist/declarations/src/internal/localeAt.d.ts +19 -0
- package/dist/declarations/src/internal/resolveSchemaSourceFixes.d.ts +32 -8
- package/dist/declarations/src/internal/zod/SerializedSchema.d.ts +5 -4
- package/dist/{getSitemapTree-a6cb37cb.esm.js → getSitemapTree-6777bdfa.esm.js} +1 -1
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +517 -37
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +517 -37
- package/internal/dist/valbuild-shared-internal.esm.js +516 -41
- package/package.json +2 -2
|
@@ -897,10 +897,34 @@ var PatchBlock = zod.z.object({
|
|
|
897
897
|
parentRef: ParentRef$1
|
|
898
898
|
});
|
|
899
899
|
|
|
900
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
901
|
+
if (null == r) return {};
|
|
902
|
+
var t = {};
|
|
903
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
904
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
905
|
+
t[n] = r[n];
|
|
906
|
+
}
|
|
907
|
+
return t;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function _objectWithoutProperties(e, t) {
|
|
911
|
+
if (null == e) return {};
|
|
912
|
+
var o,
|
|
913
|
+
r,
|
|
914
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
915
|
+
if (Object.getOwnPropertySymbols) {
|
|
916
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
917
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
918
|
+
}
|
|
919
|
+
return i;
|
|
920
|
+
}
|
|
921
|
+
|
|
900
922
|
var SourcePath = zod.z.string().transform(function (path) {
|
|
901
923
|
return path;
|
|
902
924
|
});
|
|
903
925
|
|
|
926
|
+
var _excluded = ["directory"];
|
|
927
|
+
|
|
904
928
|
// A render is static config, so unlike a `preview` it travels WHOLE — this
|
|
905
929
|
// is the field the editor reads the layout from. See `core/src/render.ts`.
|
|
906
930
|
// Every field can carry `{ as: "inline" }`, and that is all a render says.
|
|
@@ -1008,11 +1032,35 @@ var ImageEncodeOption = zod.z.union([zod.z.literal(false), zod.z.object({
|
|
|
1008
1032
|
maxWidth: zod.z.number().optional(),
|
|
1009
1033
|
maxHeight: zod.z.number().optional()
|
|
1010
1034
|
})]);
|
|
1011
|
-
|
|
1012
|
-
|
|
1035
|
+
/**
|
|
1036
|
+
* Accept the pre-rename `directory` key and read it as `dir`.
|
|
1037
|
+
*
|
|
1038
|
+
* Serialized schemas are not only computed from live code: a commit record
|
|
1039
|
+
* stores the schema each module was under (`StoredModuleVersion`), and the
|
|
1040
|
+
* history view parses those back. Commits made before `directory` became `dir`
|
|
1041
|
+
* therefore still carry the old key, and dropping it would show a historical
|
|
1042
|
+
* gallery with no directory at all — silently, since the rest of the schema
|
|
1043
|
+
* parses fine.
|
|
1044
|
+
*
|
|
1045
|
+
* Only fills `dir` when it is absent, so a schema carrying both (which should
|
|
1046
|
+
* not happen) keeps the current key.
|
|
1047
|
+
*/
|
|
1048
|
+
var readLegacyDirectoryAsDir = function readLegacyDirectoryAsDir(value) {
|
|
1049
|
+
if (!value || getSitemapTree._typeof(value) !== "object" || Array.isArray(value) || !("directory" in value) || "dir" in value) {
|
|
1050
|
+
return value;
|
|
1051
|
+
}
|
|
1052
|
+
var _ref = value,
|
|
1053
|
+
directory = _ref.directory,
|
|
1054
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
1055
|
+
return getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, rest), {}, {
|
|
1056
|
+
dir: directory
|
|
1057
|
+
});
|
|
1058
|
+
};
|
|
1059
|
+
var ImageOptions = zod.z.preprocess(readLegacyDirectoryAsDir, zod.z.object({
|
|
1060
|
+
dir: zod.z.string().optional(),
|
|
1013
1061
|
accept: zod.z.string().optional(),
|
|
1014
1062
|
encode: ImageEncodeOption.optional()
|
|
1015
|
-
});
|
|
1063
|
+
}));
|
|
1016
1064
|
var SerializedImageSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
1017
1065
|
type: zod.z.literal("image"),
|
|
1018
1066
|
options: ImageOptions.optional(),
|
|
@@ -1051,7 +1099,7 @@ var SerializedRichTextSchema = zod.z.object(getSitemapTree._objectSpread2(getSit
|
|
|
1051
1099
|
opt: zod.z["boolean"]()
|
|
1052
1100
|
}));
|
|
1053
1101
|
var SerializedRecordSchema = zod.z.lazy(function () {
|
|
1054
|
-
return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
1102
|
+
return zod.z.preprocess(readLegacyDirectoryAsDir, zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
1055
1103
|
type: zod.z.literal("record"),
|
|
1056
1104
|
item: SerializedSchema,
|
|
1057
1105
|
opt: zod.z["boolean"](),
|
|
@@ -1059,12 +1107,12 @@ var SerializedRecordSchema = zod.z.lazy(function () {
|
|
|
1059
1107
|
mediaType: zod.z.union([zod.z.literal("files"), zod.z.literal("images")]).optional(),
|
|
1060
1108
|
// Optional legacy gallery metadata
|
|
1061
1109
|
accept: zod.z.string().optional(),
|
|
1062
|
-
|
|
1110
|
+
dir: zod.z.string().optional(),
|
|
1063
1111
|
remote: zod.z["boolean"]().optional(),
|
|
1064
1112
|
encode: ImageEncodeOption.optional(),
|
|
1065
1113
|
alt: SerializedSchema.optional(),
|
|
1066
1114
|
moduleMetadata: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.any())).optional()
|
|
1067
|
-
})).passthrough();
|
|
1115
|
+
})).passthrough());
|
|
1068
1116
|
});
|
|
1069
1117
|
var SerializedKeyOfSchema = zod.z.lazy(function () {
|
|
1070
1118
|
return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
@@ -1125,6 +1173,16 @@ var SerializedCodeSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemap
|
|
|
1125
1173
|
options: CodeOptions.optional(),
|
|
1126
1174
|
opt: zod.z["boolean"]()
|
|
1127
1175
|
}));
|
|
1176
|
+
var SerializedLocaleSchema = zod.z.object({
|
|
1177
|
+
type: zod.z.literal("locale"),
|
|
1178
|
+
render: FieldRender,
|
|
1179
|
+
preview: zod.z.literal(true).optional(),
|
|
1180
|
+
opt: zod.z["boolean"](),
|
|
1181
|
+
customValidate: zod.z["boolean"]().optional(),
|
|
1182
|
+
readonly: zod.z["boolean"]().optional(),
|
|
1183
|
+
hidden: zod.z["boolean"]().optional(),
|
|
1184
|
+
description: zod.z.string().optional()
|
|
1185
|
+
});
|
|
1128
1186
|
var SerializedRouteSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
1129
1187
|
type: zod.z.literal("route"),
|
|
1130
1188
|
options: zod.z.object({
|
|
@@ -1150,10 +1208,15 @@ var SerializedSettingsSchema = zod.z.lazy(function () {
|
|
|
1150
1208
|
return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
|
|
1151
1209
|
type: zod.z.literal("settings"),
|
|
1152
1210
|
items: zod.z.record(zod.z.string(), SerializedSchema),
|
|
1153
|
-
opt: zod.z["boolean"]()
|
|
1211
|
+
opt: zod.z["boolean"](),
|
|
1212
|
+
// Which section this is, where Val has rules about it beyond its keys.
|
|
1213
|
+
// Dropping it would leave the Studio's validation worker running every
|
|
1214
|
+
// field's own rules and none of the cross-field ones — see
|
|
1215
|
+
// `sectionValidators` in core/src/schema/settings.ts.
|
|
1216
|
+
section: zod.z.string().optional()
|
|
1154
1217
|
}));
|
|
1155
1218
|
});
|
|
1156
|
-
var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema]);
|
|
1219
|
+
var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema]);
|
|
1157
1220
|
|
|
1158
1221
|
var ValCommit = zod.z.object({
|
|
1159
1222
|
commitSha: zod.z.string(),
|
|
@@ -1329,7 +1392,7 @@ var ValConfig = zod.z.object({
|
|
|
1329
1392
|
gitCommit: zod.z.string().optional(),
|
|
1330
1393
|
gitBranch: zod.z.string().optional()
|
|
1331
1394
|
});
|
|
1332
|
-
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("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("router:check-route"), 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("jsonValues:extract-entry")]);
|
|
1395
|
+
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("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("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("jsonValues:extract-entry")]);
|
|
1333
1396
|
var ValidationError = zod.z.object({
|
|
1334
1397
|
message: zod.z.string(),
|
|
1335
1398
|
value: zod.z.unknown().optional(),
|
|
@@ -3236,7 +3299,7 @@ var compatible = {
|
|
|
3236
3299
|
* `readonly Json[]` — so the check that reads naturally does not type. This
|
|
3237
3300
|
* predicate is that check, said once.
|
|
3238
3301
|
*/
|
|
3239
|
-
function isJsonObject(value) {
|
|
3302
|
+
function isJsonObject$1(value) {
|
|
3240
3303
|
return getSitemapTree._typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
3241
3304
|
}
|
|
3242
3305
|
function incompatible(reason) {
|
|
@@ -3293,7 +3356,7 @@ function variantOf(schema, value) {
|
|
|
3293
3356
|
return undefined;
|
|
3294
3357
|
}
|
|
3295
3358
|
var discriminator = schema.key;
|
|
3296
|
-
if (!isJsonObject(value)) {
|
|
3359
|
+
if (!isJsonObject$1(value)) {
|
|
3297
3360
|
return undefined;
|
|
3298
3361
|
}
|
|
3299
3362
|
var tag = value[discriminator];
|
|
@@ -3421,7 +3484,7 @@ function checkCompatibility(from, to) {
|
|
|
3421
3484
|
}
|
|
3422
3485
|
case "object":
|
|
3423
3486
|
{
|
|
3424
|
-
if (from.schema.type !== "object" || !isJsonObject(from.value)) {
|
|
3487
|
+
if (from.schema.type !== "object" || !isJsonObject$1(from.value)) {
|
|
3425
3488
|
return {
|
|
3426
3489
|
status: "unknown",
|
|
3427
3490
|
message: "The old value is not shaped like an object."
|
|
@@ -3524,7 +3587,7 @@ function checkCompatibility(from, to) {
|
|
|
3524
3587
|
}
|
|
3525
3588
|
case "record":
|
|
3526
3589
|
{
|
|
3527
|
-
if (from.schema.type !== "record" || !isJsonObject(from.value)) {
|
|
3590
|
+
if (from.schema.type !== "record" || !isJsonObject$1(from.value)) {
|
|
3528
3591
|
return {
|
|
3529
3592
|
status: "unknown",
|
|
3530
3593
|
message: "The old value is not a record."
|
|
@@ -3960,6 +4023,59 @@ function checkRouteIsValid(route, includePattern, excludePattern, snapshot) {
|
|
|
3960
4023
|
error: false
|
|
3961
4024
|
};
|
|
3962
4025
|
}
|
|
4026
|
+
|
|
4027
|
+
/**
|
|
4028
|
+
* The languages the project declares, from its settings module.
|
|
4029
|
+
*
|
|
4030
|
+
* Empty where there is no settings module, no `locales` section, or nothing in
|
|
4031
|
+
* it — all of which mean the same thing: this project has not said it is
|
|
4032
|
+
* translated.
|
|
4033
|
+
*/
|
|
4034
|
+
function declaredLocales(snapshot) {
|
|
4035
|
+
var _resolveSettingsModul = core.resolveSettingsModule(snapshot.schemas),
|
|
4036
|
+
moduleFilePath = _resolveSettingsModul.moduleFilePath;
|
|
4037
|
+
if (moduleFilePath === null) {
|
|
4038
|
+
return [];
|
|
4039
|
+
}
|
|
4040
|
+
var source = snapshot.sources[moduleFilePath];
|
|
4041
|
+
if (getSitemapTree._typeof(source) !== "object" || source === null || Array.isArray(source)) {
|
|
4042
|
+
return [];
|
|
4043
|
+
}
|
|
4044
|
+
var locales = source["locales"];
|
|
4045
|
+
if (getSitemapTree._typeof(locales) !== "object" || locales === null || Array.isArray(locales)) {
|
|
4046
|
+
return [];
|
|
4047
|
+
}
|
|
4048
|
+
var available = locales["available"];
|
|
4049
|
+
if (!Array.isArray(available)) {
|
|
4050
|
+
return [];
|
|
4051
|
+
}
|
|
4052
|
+
return available.filter(function (tag) {
|
|
4053
|
+
return typeof tag === "string";
|
|
4054
|
+
});
|
|
4055
|
+
}
|
|
4056
|
+
/**
|
|
4057
|
+
* The fixes {@link resolveSchemaSourceFixForError} answers for.
|
|
4058
|
+
*
|
|
4059
|
+
* A marker error carrying one of these is NOT a message: it says "ask the whole
|
|
4060
|
+
* project about this" and carries the value to ask with, because the schema
|
|
4061
|
+
* that raised it can only see its own module. Left unresolved, what a user sees
|
|
4062
|
+
* is the marker's own placeholder text — "should typically be processed by Val
|
|
4063
|
+
* internally … version mismatch" — which is alarming and says nothing.
|
|
4064
|
+
*
|
|
4065
|
+
* A list rather than a check per call site: every caller that resolves some of
|
|
4066
|
+
* these has to resolve all of them, and the two that leaked did so by adding a
|
|
4067
|
+
* fix here and not to a condition somewhere else.
|
|
4068
|
+
*/
|
|
4069
|
+
var SCHEMA_SOURCE_FIXES = ["keyof:check-keys", "router:check-route", "locale:check-locale", "record:fill-keys"];
|
|
4070
|
+
|
|
4071
|
+
/** Whether an error is a marker only the whole project can answer. */
|
|
4072
|
+
function isSchemaSourceFixError(error) {
|
|
4073
|
+
var _error$fixes;
|
|
4074
|
+
return ((_error$fixes = error.fixes) !== null && _error$fixes !== void 0 ? _error$fixes : []).some(function (fix) {
|
|
4075
|
+
return SCHEMA_SOURCE_FIXES.includes(fix);
|
|
4076
|
+
});
|
|
4077
|
+
}
|
|
4078
|
+
|
|
3963
4079
|
/**
|
|
3964
4080
|
* The record a `keyof:check-keys` error resolves against, or null for any other
|
|
3965
4081
|
* error — including a malformed marker, which
|
|
@@ -3971,8 +4087,8 @@ function checkRouteIsValid(route, includePattern, excludePattern, snapshot) {
|
|
|
3971
4087
|
* to the referenced record can invalidate the module holding the reference.
|
|
3972
4088
|
*/
|
|
3973
4089
|
function keyOfRecordPath(error) {
|
|
3974
|
-
var _error$
|
|
3975
|
-
if (!((_error$
|
|
4090
|
+
var _error$fixes2;
|
|
4091
|
+
if (!((_error$fixes2 = error.fixes) !== null && _error$fixes2 !== void 0 ? _error$fixes2 : []).includes("keyof:check-keys")) {
|
|
3976
4092
|
return null;
|
|
3977
4093
|
}
|
|
3978
4094
|
var value = error.value;
|
|
@@ -3984,15 +4100,15 @@ function keyOfRecordPath(error) {
|
|
|
3984
4100
|
}
|
|
3985
4101
|
|
|
3986
4102
|
/**
|
|
3987
|
-
* Resolves a single
|
|
3988
|
-
*
|
|
4103
|
+
* Resolves a single marker error (see {@link SCHEMA_SOURCE_FIXES}) against the
|
|
4104
|
+
* given schema/source snapshot. Returns:
|
|
3989
4105
|
* - null if the error is not one of these fixes (caller should pass through)
|
|
3990
|
-
* - { status: "resolved" } if the
|
|
4106
|
+
* - { status: "resolved" } if the reference is valid (drop error)
|
|
3991
4107
|
* - { status: "remaining"; error } if invalid (rewritten error to surface)
|
|
3992
4108
|
*/
|
|
3993
4109
|
function resolveSchemaSourceFixForError(error, snapshot) {
|
|
3994
|
-
var _error$
|
|
3995
|
-
var fixes = (_error$
|
|
4110
|
+
var _error$fixes3;
|
|
4111
|
+
var fixes = (_error$fixes3 = error.fixes) !== null && _error$fixes3 !== void 0 ? _error$fixes3 : [];
|
|
3996
4112
|
if (fixes.includes("keyof:check-keys")) {
|
|
3997
4113
|
if (!error.value) {
|
|
3998
4114
|
return {
|
|
@@ -4051,6 +4167,120 @@ function resolveSchemaSourceFixForError(error, snapshot) {
|
|
|
4051
4167
|
status: "resolved"
|
|
4052
4168
|
};
|
|
4053
4169
|
}
|
|
4170
|
+
if (fixes.includes("locale:check-locale")) {
|
|
4171
|
+
var value = error.value;
|
|
4172
|
+
if (getSitemapTree._typeof(value) !== "object" || value === null) {
|
|
4173
|
+
return {
|
|
4174
|
+
status: "remaining",
|
|
4175
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4176
|
+
message: "Expected locale validation error to have a 'value' object. Found: ".concat(getSitemapTree._typeof(value), ". ").concat(TYPE_ERROR_MESSAGE),
|
|
4177
|
+
typeError: true,
|
|
4178
|
+
fixes: undefined
|
|
4179
|
+
})
|
|
4180
|
+
};
|
|
4181
|
+
}
|
|
4182
|
+
var _ref6 = value,
|
|
4183
|
+
locale = _ref6.locale;
|
|
4184
|
+
if (typeof locale !== "string") {
|
|
4185
|
+
return {
|
|
4186
|
+
status: "remaining",
|
|
4187
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4188
|
+
message: "Expected locale validation error 'value' to have property 'locale' of type 'string'. Found: ".concat(getSitemapTree._typeof(locale), ". ").concat(TYPE_ERROR_MESSAGE),
|
|
4189
|
+
typeError: true,
|
|
4190
|
+
fixes: undefined
|
|
4191
|
+
})
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
var available = declaredLocales(snapshot);
|
|
4195
|
+
if (available.length === 0) {
|
|
4196
|
+
return {
|
|
4197
|
+
status: "remaining",
|
|
4198
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4199
|
+
// The project has not said it is translated, so the value is not
|
|
4200
|
+
// wrong so much as premature — and the fix is in another file.
|
|
4201
|
+
message: "This project has no languages. Declare them under 'locales.available' in the settings module before using s.locale().",
|
|
4202
|
+
fixes: undefined
|
|
4203
|
+
})
|
|
4204
|
+
};
|
|
4205
|
+
}
|
|
4206
|
+
if (available.includes(locale)) {
|
|
4207
|
+
return {
|
|
4208
|
+
status: "resolved"
|
|
4209
|
+
};
|
|
4210
|
+
}
|
|
4211
|
+
return {
|
|
4212
|
+
status: "remaining",
|
|
4213
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4214
|
+
message: "'".concat(locale, "' is not one of this project's languages: ").concat(available.map(function (each) {
|
|
4215
|
+
return "'".concat(each, "'");
|
|
4216
|
+
}).join(", ")),
|
|
4217
|
+
fixes: undefined
|
|
4218
|
+
})
|
|
4219
|
+
};
|
|
4220
|
+
}
|
|
4221
|
+
if (fixes.includes("record:fill-keys")) {
|
|
4222
|
+
var _value = error.value;
|
|
4223
|
+
if (getSitemapTree._typeof(_value) !== "object" || _value === null) {
|
|
4224
|
+
return {
|
|
4225
|
+
status: "remaining",
|
|
4226
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4227
|
+
message: "Expected record key validation error to have a 'value' object. Found: ".concat(getSitemapTree._typeof(_value), ". ").concat(TYPE_ERROR_MESSAGE),
|
|
4228
|
+
typeError: true,
|
|
4229
|
+
fixes: undefined
|
|
4230
|
+
})
|
|
4231
|
+
};
|
|
4232
|
+
}
|
|
4233
|
+
var _ref7 = _value,
|
|
4234
|
+
present = _ref7.present,
|
|
4235
|
+
declared = _ref7.declared;
|
|
4236
|
+
if (!Array.isArray(present)) {
|
|
4237
|
+
return {
|
|
4238
|
+
status: "remaining",
|
|
4239
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4240
|
+
message: "Expected record key validation error 'value' to have property 'present' of type 'array'. Found: ".concat(getSitemapTree._typeof(present), ". ").concat(TYPE_ERROR_MESSAGE),
|
|
4241
|
+
typeError: true,
|
|
4242
|
+
fixes: undefined
|
|
4243
|
+
})
|
|
4244
|
+
};
|
|
4245
|
+
}
|
|
4246
|
+
var presentKeys = present.filter(function (key) {
|
|
4247
|
+
return typeof key === "string";
|
|
4248
|
+
});
|
|
4249
|
+
// A literal union brought its keys along; a locale record left them to be
|
|
4250
|
+
// read out of the settings module, which is the whole reason this check is
|
|
4251
|
+
// resolved here rather than in the schema.
|
|
4252
|
+
var declaredKeys = Array.isArray(declared) ? declared.filter(function (key) {
|
|
4253
|
+
return typeof key === "string";
|
|
4254
|
+
}) : declaredLocales(snapshot);
|
|
4255
|
+
if (declaredKeys.length === 0) {
|
|
4256
|
+
// A locale record on a project that has declared no languages. There is
|
|
4257
|
+
// nothing to require, and the locale field's own check already says the
|
|
4258
|
+
// project has not declared any — saying it twice on one record would not
|
|
4259
|
+
// add anything.
|
|
4260
|
+
return {
|
|
4261
|
+
status: "resolved"
|
|
4262
|
+
};
|
|
4263
|
+
}
|
|
4264
|
+
var missing = core.missingDeclaredKeys(declaredKeys, presentKeys);
|
|
4265
|
+
if (missing.length === 0) {
|
|
4266
|
+
return {
|
|
4267
|
+
status: "resolved"
|
|
4268
|
+
};
|
|
4269
|
+
}
|
|
4270
|
+
return {
|
|
4271
|
+
status: "remaining",
|
|
4272
|
+
error: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, error), {}, {
|
|
4273
|
+
message: "Missing ".concat(missing.length === 1 ? "key" : "keys", ": ").concat(missing.map(function (each) {
|
|
4274
|
+
return "'".concat(each, "'");
|
|
4275
|
+
}).join(", "), ". This record's keys are declared by its schema, so every one of them is an entry \u2014 an entry nobody has written yet is null, not absent."),
|
|
4276
|
+
value: {
|
|
4277
|
+
missing: missing,
|
|
4278
|
+
declared: declaredKeys
|
|
4279
|
+
},
|
|
4280
|
+
fixes: undefined
|
|
4281
|
+
})
|
|
4282
|
+
};
|
|
4283
|
+
}
|
|
4054
4284
|
if (fixes.includes("router:check-route")) {
|
|
4055
4285
|
if (!error.value) {
|
|
4056
4286
|
return {
|
|
@@ -4112,10 +4342,10 @@ function asRegExpPattern(value) {
|
|
|
4112
4342
|
/**
|
|
4113
4343
|
* Apply schema/source fix resolution across a map of validation errors.
|
|
4114
4344
|
*
|
|
4115
|
-
* Errors
|
|
4116
|
-
*
|
|
4117
|
-
*
|
|
4118
|
-
*
|
|
4345
|
+
* Errors carrying one of {@link SCHEMA_SOURCE_FIXES} are resolved against the
|
|
4346
|
+
* in-memory schema/source snapshot — valid references drop the error, invalid
|
|
4347
|
+
* ones are rewritten with a "did you mean…" message and have their `fixes`
|
|
4348
|
+
* cleared (so downstream code reports them as plain validation errors).
|
|
4119
4349
|
* All other errors pass through untouched.
|
|
4120
4350
|
*
|
|
4121
4351
|
* Source paths with no remaining errors are removed from the result.
|
|
@@ -4149,6 +4379,189 @@ function resolveSchemaSourceFixes(validationErrors, snapshot) {
|
|
|
4149
4379
|
return result;
|
|
4150
4380
|
}
|
|
4151
4381
|
|
|
4382
|
+
/**
|
|
4383
|
+
* Which of the project's languages governs a path, or `null` for none.
|
|
4384
|
+
*
|
|
4385
|
+
* THE question the whole feature turns on. A locale scope is a subtree in one
|
|
4386
|
+
* language, and three things open one: a `locale` field on an object, a record
|
|
4387
|
+
* keyed by `s.locale()`, and a locale segment in a segmented key. Once this can
|
|
4388
|
+
* be answered from the schema and the source alone, everything downstream falls
|
|
4389
|
+
* out of it — the Studio's locale filter, deep links, `<html lang>`, and knowing
|
|
4390
|
+
* what to translate from and into.
|
|
4391
|
+
*
|
|
4392
|
+
* One implementation, so the Studio, the server and the validation worker cannot
|
|
4393
|
+
* disagree about what language a piece of content is in.
|
|
4394
|
+
*
|
|
4395
|
+
* `null` means no scope governs the path — which is the answer for most content
|
|
4396
|
+
* in most projects, and for every project that has not declared any languages.
|
|
4397
|
+
*/
|
|
4398
|
+
function localeAt(path, snapshot) {
|
|
4399
|
+
var available = declaredLocales(snapshot);
|
|
4400
|
+
if (available.length === 0) {
|
|
4401
|
+
// Nothing can be one of no languages. Answering `null` rather than reading
|
|
4402
|
+
// the content is also what makes this cheap for the projects that are not
|
|
4403
|
+
// translated at all.
|
|
4404
|
+
return null;
|
|
4405
|
+
}
|
|
4406
|
+
var _Internal$splitModule = core.Internal.splitModuleFilePathAndModulePath(path),
|
|
4407
|
+
_Internal$splitModule2 = _slicedToArray(_Internal$splitModule, 2),
|
|
4408
|
+
moduleFilePath = _Internal$splitModule2[0],
|
|
4409
|
+
modulePath = _Internal$splitModule2[1];
|
|
4410
|
+
var schema = snapshot.schemas[moduleFilePath];
|
|
4411
|
+
var source = snapshot.sources[moduleFilePath];
|
|
4412
|
+
if (schema === undefined || source === undefined) {
|
|
4413
|
+
return null;
|
|
4414
|
+
}
|
|
4415
|
+
var segments = modulePath ? core.Internal.splitModulePath(modulePath) : [];
|
|
4416
|
+
return walk(schema, source, segments, available);
|
|
4417
|
+
}
|
|
4418
|
+
|
|
4419
|
+
/**
|
|
4420
|
+
* Walk from a node towards `segments`, answering with the innermost scope.
|
|
4421
|
+
*
|
|
4422
|
+
* The scope is read on ARRIVAL at each node — the node the path names included,
|
|
4423
|
+
* not only the ones passed through on the way to it. So `localeAt` of a
|
|
4424
|
+
* scope-opening object is that object's own locale rather than its parent's,
|
|
4425
|
+
* and a path that stops AT a block still answers with the block's language.
|
|
4426
|
+
*
|
|
4427
|
+
* A scope may not contain another (see `localeScopeErrors`), so at most one of
|
|
4428
|
+
* these can fire on a well-formed path; taking the innermost is what makes the
|
|
4429
|
+
* answer well-defined while a project is mid-fix.
|
|
4430
|
+
*/
|
|
4431
|
+
function walk(schema, source, segments, available) {
|
|
4432
|
+
var entered = enter(schema, source, available);
|
|
4433
|
+
var locale = entered.locale;
|
|
4434
|
+
var currentSchema = entered.schema;
|
|
4435
|
+
var currentSource = source;
|
|
4436
|
+
var _iterator = getSitemapTree._createForOfIteratorHelper(segments),
|
|
4437
|
+
_step;
|
|
4438
|
+
try {
|
|
4439
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
4440
|
+
var segment = _step.value;
|
|
4441
|
+
if (currentSchema === undefined) {
|
|
4442
|
+
return locale;
|
|
4443
|
+
}
|
|
4444
|
+
if (currentSchema.type === "record") {
|
|
4445
|
+
var _currentSchema$key;
|
|
4446
|
+
if (((_currentSchema$key = currentSchema.key) === null || _currentSchema$key === void 0 ? void 0 : _currentSchema$key.type) === "locale") {
|
|
4447
|
+
// In a locale-keyed record the KEY is the language, so the segment we
|
|
4448
|
+
// are about to take is the answer.
|
|
4449
|
+
var resolved = core.localeOfValue(segment, available);
|
|
4450
|
+
if (resolved !== null) {
|
|
4451
|
+
locale = resolved;
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
currentSchema = currentSchema.item;
|
|
4455
|
+
} else if (currentSchema.type === "array") {
|
|
4456
|
+
currentSchema = currentSchema.item;
|
|
4457
|
+
} else if (currentSchema.type === "object" || currentSchema.type === "settings") {
|
|
4458
|
+
currentSchema = currentSchema.items[segment];
|
|
4459
|
+
} else {
|
|
4460
|
+
// A leaf, or richtext's internal structure. Nothing below opens a scope.
|
|
4461
|
+
return locale;
|
|
4462
|
+
}
|
|
4463
|
+
currentSource = childSource(currentSource, segment);
|
|
4464
|
+
entered = enter(currentSchema, currentSource, available);
|
|
4465
|
+
currentSchema = entered.schema;
|
|
4466
|
+
if (entered.locale !== null) {
|
|
4467
|
+
locale = entered.locale;
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
} catch (err) {
|
|
4471
|
+
_iterator.e(err);
|
|
4472
|
+
} finally {
|
|
4473
|
+
_iterator.f();
|
|
4474
|
+
}
|
|
4475
|
+
return locale;
|
|
4476
|
+
}
|
|
4477
|
+
|
|
4478
|
+
/**
|
|
4479
|
+
* Arrive at a node: resolve what it really is, and read the scope it opens.
|
|
4480
|
+
*
|
|
4481
|
+
* A discriminated union is a fork rather than a level — the variant the value
|
|
4482
|
+
* takes IS the node — so it is resolved here, before anything asks what the
|
|
4483
|
+
* node holds. Doing that on arrival rather than on the way down is the
|
|
4484
|
+
* difference between a block's own path answering with its language and
|
|
4485
|
+
* answering with nothing.
|
|
4486
|
+
*/
|
|
4487
|
+
function enter(schema, source, available) {
|
|
4488
|
+
var resolved = (schema === null || schema === void 0 ? void 0 : schema.type) === "discriminated-union" ? variantOfUnion(schema, source) : schema;
|
|
4489
|
+
return {
|
|
4490
|
+
schema: resolved,
|
|
4491
|
+
locale: resolved === undefined ? null : localeOfObjectField(resolved, source, available)
|
|
4492
|
+
};
|
|
4493
|
+
}
|
|
4494
|
+
|
|
4495
|
+
/**
|
|
4496
|
+
* The language an object's own `locale` field says it is in, if it has one.
|
|
4497
|
+
*
|
|
4498
|
+
* Reads the SOURCE, since unlike a record key the value is content rather than
|
|
4499
|
+
* part of the path. A field that has not been filled in, or holds something
|
|
4500
|
+
* that is not one of the project's languages, is not an answer — validation is
|
|
4501
|
+
* already reporting that, and guessing here would put a language in
|
|
4502
|
+
* `<html lang>` that nobody chose.
|
|
4503
|
+
*/
|
|
4504
|
+
function localeOfObjectField(schema, source, available) {
|
|
4505
|
+
if (schema.type !== "object" || !isJsonObject(source)) {
|
|
4506
|
+
return null;
|
|
4507
|
+
}
|
|
4508
|
+
for (var _i = 0, _Object$entries = Object.entries(schema.items); _i < _Object$entries.length; _i++) {
|
|
4509
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
4510
|
+
key = _Object$entries$_i[0],
|
|
4511
|
+
item = _Object$entries$_i[1];
|
|
4512
|
+
if (item.type !== "locale") {
|
|
4513
|
+
continue;
|
|
4514
|
+
}
|
|
4515
|
+
var value = source[key];
|
|
4516
|
+
if (typeof value !== "string") {
|
|
4517
|
+
return null;
|
|
4518
|
+
}
|
|
4519
|
+
return core.localeOfValue(value, available);
|
|
4520
|
+
}
|
|
4521
|
+
return null;
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
/**
|
|
4525
|
+
* The variant a value takes, or `undefined` if the tag matches none.
|
|
4526
|
+
*
|
|
4527
|
+
* The tag is read off the source here; picking the variant is
|
|
4528
|
+
* {@link discriminatedUnionBranchOf}, shared with the Studio's locale filter so
|
|
4529
|
+
* the two cannot disagree about which variant a row is. `s.enum()` never
|
|
4530
|
+
* reaches this — it is a leaf, with nothing under it to walk into.
|
|
4531
|
+
*/
|
|
4532
|
+
function variantOfUnion(schema, source) {
|
|
4533
|
+
if (!isJsonObject(source)) {
|
|
4534
|
+
return undefined;
|
|
4535
|
+
}
|
|
4536
|
+
return core.discriminatedUnionBranchOf(schema, source[schema.key]);
|
|
4537
|
+
}
|
|
4538
|
+
|
|
4539
|
+
/** The child of a source value at a segment, or `null` where there is none. */
|
|
4540
|
+
function childSource(source, segment) {
|
|
4541
|
+
var _source$segment;
|
|
4542
|
+
if (Array.isArray(source)) {
|
|
4543
|
+
var _source$index;
|
|
4544
|
+
var index = Number(segment);
|
|
4545
|
+
return Number.isInteger(index) ? (_source$index = source[index]) !== null && _source$index !== void 0 ? _source$index : null : null;
|
|
4546
|
+
}
|
|
4547
|
+
if (!isJsonObject(source)) {
|
|
4548
|
+
return null;
|
|
4549
|
+
}
|
|
4550
|
+
return (_source$segment = source[segment]) !== null && _source$segment !== void 0 ? _source$segment : null;
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4553
|
+
/**
|
|
4554
|
+
* Whether `source` is a JSON object rather than an array or a primitive.
|
|
4555
|
+
*
|
|
4556
|
+
* A type predicate rather than the inline checks, because `Array.isArray` does
|
|
4557
|
+
* NOT narrow `JsonArray` out of `Json` — it is `readonly Json[]`, and the
|
|
4558
|
+
* built-in guard only narrows mutable arrays. Without this, every read of a
|
|
4559
|
+
* property would need an assertion.
|
|
4560
|
+
*/
|
|
4561
|
+
function isJsonObject(source) {
|
|
4562
|
+
return getSitemapTree._typeof(source) === "object" && source !== null && !Array.isArray(source);
|
|
4563
|
+
}
|
|
4564
|
+
|
|
4152
4565
|
/**
|
|
4153
4566
|
* Local `yyyy-MM-dd`, which is the one thing this module used `date-fns` for.
|
|
4154
4567
|
*
|
|
@@ -4185,15 +4598,27 @@ function clampDateTimeString(value, options) {
|
|
|
4185
4598
|
}
|
|
4186
4599
|
return value;
|
|
4187
4600
|
}
|
|
4188
|
-
|
|
4601
|
+
|
|
4602
|
+
/**
|
|
4603
|
+
* What `emptyOf` cannot read off a serialized schema.
|
|
4604
|
+
*
|
|
4605
|
+
* The project's languages, and which one is being worked in. Neither is in the
|
|
4606
|
+
* schema: a locale-keyed record has one entry per language and the languages
|
|
4607
|
+
* are declared in the settings module, and "which language am I writing" is a
|
|
4608
|
+
* fact about the editor, not about the content. Optional throughout: a caller
|
|
4609
|
+
* that has no context gets an empty record and an unset locale, which
|
|
4610
|
+
* validation then reports, rather than wrong ones.
|
|
4611
|
+
*/
|
|
4612
|
+
|
|
4613
|
+
function emptyOf(schema, context) {
|
|
4189
4614
|
if (schema.type === "object") {
|
|
4190
4615
|
return Object.fromEntries(Object.keys(schema.items).map(function (key) {
|
|
4191
|
-
return [key, emptyOf(schema.items[key])];
|
|
4616
|
+
return [key, emptyOf(schema.items[key], context)];
|
|
4192
4617
|
}));
|
|
4193
4618
|
} else if (schema.type === "array") {
|
|
4194
4619
|
return [];
|
|
4195
4620
|
} else if (schema.type === "record") {
|
|
4196
|
-
return
|
|
4621
|
+
return emptyRecord(schema, context);
|
|
4197
4622
|
} else if (schema.type === "settings") {
|
|
4198
4623
|
// Not an object of empty sections: every settings key is optional, and
|
|
4199
4624
|
// absent IS the empty value. Filling the sections in would write a shape
|
|
@@ -4217,6 +4642,16 @@ function emptyOf(schema) {
|
|
|
4217
4642
|
}
|
|
4218
4643
|
} else if (schema.type === "route") {
|
|
4219
4644
|
return ""; // Empty string as default route value
|
|
4645
|
+
} else if (schema.type === "locale") {
|
|
4646
|
+
var _context$selectedLoca;
|
|
4647
|
+
// Which languages exist is in the settings module, which `emptyOf` has no
|
|
4648
|
+
// access to — it works from a serialized schema alone. So a caller that
|
|
4649
|
+
// has narrowed to one language says so and gets it; a caller that has not
|
|
4650
|
+
// gets the empty string, which is not a language and which validation
|
|
4651
|
+
// reports. Guessing `locales[0]` instead would file content under a
|
|
4652
|
+
// language nobody chose, which is the thing this whole feature exists to
|
|
4653
|
+
// make visible.
|
|
4654
|
+
return (_context$selectedLoca = context === null || context === void 0 ? void 0 : context.selectedLocale) !== null && _context$selectedLoca !== void 0 ? _context$selectedLoca : "";
|
|
4220
4655
|
} else if (schema.type === "file" || schema.type === "image") {
|
|
4221
4656
|
return null; // returning null is the only thing we can do, however, it means that the patches cannot be applied yet since that might fail
|
|
4222
4657
|
} else if (schema.type === "literal") {
|
|
@@ -4229,7 +4664,7 @@ function emptyOf(schema) {
|
|
|
4229
4664
|
if (schema.items.length === 0) {
|
|
4230
4665
|
throw Error("Cannot create an empty value for a discriminated union with no variants");
|
|
4231
4666
|
}
|
|
4232
|
-
return emptyOf(schema.items[0]);
|
|
4667
|
+
return emptyOf(schema.items[0], context);
|
|
4233
4668
|
} else if (schema.type === "enum") {
|
|
4234
4669
|
if (schema.values.length === 0) {
|
|
4235
4670
|
throw Error("Cannot create an empty value for an enum with no values");
|
|
@@ -4255,6 +4690,32 @@ function emptyOf(schema) {
|
|
|
4255
4690
|
throw Error("Unexpected schema type: " + JSON.stringify(_exhaustiveCheck));
|
|
4256
4691
|
}
|
|
4257
4692
|
|
|
4693
|
+
/**
|
|
4694
|
+
* An empty record — with every key its schema declares already in it.
|
|
4695
|
+
*
|
|
4696
|
+
* An open record (`s.record(s.string(), item)`) starts empty, because there is
|
|
4697
|
+
* no key anyone could mean. A record whose key schema enumerates its keys is
|
|
4698
|
+
* the opposite: the keys are part of the schema, so an empty one is already
|
|
4699
|
+
* missing them, and handing back `{}` would create content that fails
|
|
4700
|
+
* validation the moment it is written.
|
|
4701
|
+
*
|
|
4702
|
+
* The entries are `null` rather than `emptyOf(item)`. A null entry reads as "not
|
|
4703
|
+
* filled in yet", which is what a language nobody has translated into IS —
|
|
4704
|
+
* whereas an entry of empty strings claims someone wrote it and left it blank,
|
|
4705
|
+
* and would count as translated in every list and filter downstream.
|
|
4706
|
+
*/
|
|
4707
|
+
function emptyRecord(schema, context) {
|
|
4708
|
+
var _context$locales;
|
|
4709
|
+
var declared = core.declaredKeySetOf(schema.key);
|
|
4710
|
+
if (declared === null) {
|
|
4711
|
+
return {};
|
|
4712
|
+
}
|
|
4713
|
+
var keys = declared.kind === "literals" ? declared.keys : (_context$locales = context === null || context === void 0 ? void 0 : context.locales) !== null && _context$locales !== void 0 ? _context$locales : [];
|
|
4714
|
+
return Object.fromEntries(keys.map(function (key) {
|
|
4715
|
+
return [key, null];
|
|
4716
|
+
}));
|
|
4717
|
+
}
|
|
4718
|
+
|
|
4258
4719
|
var toolNames = ["get_all_schema", "get_source", "search_content", "validate_content", "create_patch", "add_session_image_to_gallery", "remove_image_gallery_entry", "navigate_to", "get_current_context", "get_patches", "get_source_path_from_route", "set_session_name", "show_compare_view", "ask_user_question", "duplicate_source", "empty_at_path", "count_entries", "get_record_keys"];
|
|
4259
4720
|
|
|
4260
4721
|
function buildFileRefValue(filePath, metadata) {
|
|
@@ -4291,7 +4752,7 @@ function getSourceAt(source, path) {
|
|
|
4291
4752
|
* Walks `schema` along `path`, returning a structured result:
|
|
4292
4753
|
* - `leaf`: walked the full path; resolved schema at the end.
|
|
4293
4754
|
* - `richtext`: hit a richtext mid-walk; richtext is the resolved schema.
|
|
4294
|
-
* - `gallery-traversed`: hit an `s.
|
|
4755
|
+
* - `gallery-traversed`: hit an `s.imageset()` record and walked past it (i.e. the
|
|
4295
4756
|
* path tries to address an entry inside the gallery — a clue the AI should
|
|
4296
4757
|
* have used the gallery tool instead).
|
|
4297
4758
|
* - `unresolved`: the path could not be walked.
|
|
@@ -4422,7 +4883,7 @@ function buildImageGalleryPatch(args, moduleSchema) {
|
|
|
4422
4883
|
op: "add",
|
|
4423
4884
|
path: [args.filePath],
|
|
4424
4885
|
value: getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, args.metadata), {}, {
|
|
4425
|
-
// `alt` is a REQUIRED field of a gallery entry (`s.
|
|
4886
|
+
// `alt` is a REQUIRED field of a gallery entry (`s.imageset()` gives it a
|
|
4426
4887
|
// nullable string schema), so an entry written without one is invalid
|
|
4427
4888
|
// the moment it lands — and the caller that had no alt to give is the
|
|
4428
4889
|
// common case, not the odd one. Null is what the Studio's own upload
|
|
@@ -4485,10 +4946,10 @@ function buildRemoveImageGalleryEntryPatch(args, moduleSchema, moduleSource) {
|
|
|
4485
4946
|
var GALLERY_REDIRECT = {
|
|
4486
4947
|
kind: "wrong-tool",
|
|
4487
4948
|
suggestedTool: "add_session_image_to_gallery",
|
|
4488
|
-
reason: "Destination is a media gallery (s.
|
|
4949
|
+
reason: "Destination is a media gallery (s.imageset() / s.fileset()). Gallery entries are keyed by file path and carry a file on disk, so they cannot be created with a plain patch. Use add_session_image_to_gallery."
|
|
4489
4950
|
};
|
|
4490
4951
|
|
|
4491
|
-
/** An `s.
|
|
4952
|
+
/** An `s.imageset()` / `s.fileset()` record: a gallery, not an ordinary record. */
|
|
4492
4953
|
function isGallery(schema) {
|
|
4493
4954
|
return schema.type === "record" && schema.mediaType !== undefined;
|
|
4494
4955
|
}
|
|
@@ -4631,7 +5092,13 @@ function buildEmptyAtPathPatch(args, moduleSchema,
|
|
|
4631
5092
|
// Required, not optional: the occupied-key check below is the only thing
|
|
4632
5093
|
// standing between "scaffold an entry" and "delete the entry that was there",
|
|
4633
5094
|
// and an optional argument is one a caller forgets.
|
|
4634
|
-
moduleSource
|
|
5095
|
+
moduleSource,
|
|
5096
|
+
// The project's languages, for a locale-keyed record: its entries ARE the
|
|
5097
|
+
// languages, and they are declared in another module, so an empty one built
|
|
5098
|
+
// without them is `{}` — which the completeness rule then reports as every
|
|
5099
|
+
// language missing. Both callers can answer: the Studio from the context, the
|
|
5100
|
+
// MCP tools from the snapshot they already hold. See `EmptyOfContext`.
|
|
5101
|
+
context) {
|
|
4635
5102
|
var destinationSchema;
|
|
4636
5103
|
if (args.destinationPath.length === 0) {
|
|
4637
5104
|
destinationSchema = moduleSchema;
|
|
@@ -4677,7 +5144,7 @@ moduleSource) {
|
|
|
4677
5144
|
if (occupied) {
|
|
4678
5145
|
return occupied;
|
|
4679
5146
|
}
|
|
4680
|
-
var value = emptyOf(destinationSchema);
|
|
5147
|
+
var value = emptyOf(destinationSchema, context);
|
|
4681
5148
|
return safeParsePatch([{
|
|
4682
5149
|
op: decision.op,
|
|
4683
5150
|
path: args.destinationPath,
|
|
@@ -4868,6 +5335,8 @@ function isSkippableFixCode(fix) {
|
|
|
4868
5335
|
return true;
|
|
4869
5336
|
case "keyof:check-keys":
|
|
4870
5337
|
case "router:check-route":
|
|
5338
|
+
case "locale:check-locale":
|
|
5339
|
+
case "record:fill-keys":
|
|
4871
5340
|
case "jsonValues:extract-entry":
|
|
4872
5341
|
// `jsonValues:extract-entry` is an entry inlined in the `.val.ts`. The
|
|
4873
5342
|
// browser cannot fix it (that means writing a new `*.val.json` and
|
|
@@ -5275,8 +5744,8 @@ function traverseSchemaSource(source, schema, path, callback) {
|
|
|
5275
5744
|
return;
|
|
5276
5745
|
}
|
|
5277
5746
|
|
|
5278
|
-
// Handle route
|
|
5279
|
-
if (schema.type === "route") {
|
|
5747
|
+
// Handle route and locale: both are plain strings at a leaf
|
|
5748
|
+
if (schema.type === "route" || schema.type === "locale") {
|
|
5280
5749
|
if (typeof source === "string") {
|
|
5281
5750
|
callback({
|
|
5282
5751
|
source: source,
|
|
@@ -5503,7 +5972,13 @@ function indexModule(searchIndex, moduleFilePath, source, schema) {
|
|
|
5503
5972
|
// An enum's value is a string the editor chose; it is as searchable as
|
|
5504
5973
|
// any other string leaf. The old string union was never indexed at all,
|
|
5505
5974
|
// which is the gap this closes.
|
|
5506
|
-
schema.type === "enum"
|
|
5975
|
+
schema.type === "enum" ||
|
|
5976
|
+
// A locale tag, for the same reason: it is what the editor picked and
|
|
5977
|
+
// what they see in the field, so searching "nb-NO" has to find the
|
|
5978
|
+
// Norwegian rows. `traverseSchemaSource` visits these, and visiting a
|
|
5979
|
+
// leaf only to index it as the empty string is worse than not visiting
|
|
5980
|
+
// it — it looks like content that does not exist.
|
|
5981
|
+
schema.type === "locale") {
|
|
5507
5982
|
var _source$toString, _source$toString2;
|
|
5508
5983
|
searchText = (_source$toString = source === null || source === void 0 ? void 0 : source.toString()) !== null && _source$toString !== void 0 ? _source$toString : "";
|
|
5509
5984
|
label = (_source$toString2 = source === null || source === void 0 ? void 0 : source.toString()) !== null && _source$toString2 !== void 0 ? _source$toString2 : "";
|
|
@@ -5698,6 +6173,7 @@ exports.RemirrorText = RemirrorText;
|
|
|
5698
6173
|
exports.RemirrorTextMark = RemirrorTextMark;
|
|
5699
6174
|
exports.RestoreVerdict = RestoreVerdict;
|
|
5700
6175
|
exports.RichTextOptions = RichTextOptions;
|
|
6176
|
+
exports.SCHEMA_SOURCE_FIXES = SCHEMA_SOURCE_FIXES;
|
|
5701
6177
|
exports.SerializedArraySchema = SerializedArraySchema;
|
|
5702
6178
|
exports.SerializedBooleanSchema = SerializedBooleanSchema;
|
|
5703
6179
|
exports.SerializedCodeSchema = SerializedCodeSchema;
|
|
@@ -5710,6 +6186,7 @@ exports.SerializedFileSchema = SerializedFileSchema;
|
|
|
5710
6186
|
exports.SerializedImageSchema = SerializedImageSchema;
|
|
5711
6187
|
exports.SerializedKeyOfSchema = SerializedKeyOfSchema;
|
|
5712
6188
|
exports.SerializedLiteralSchema = SerializedLiteralSchema;
|
|
6189
|
+
exports.SerializedLocaleSchema = SerializedLocaleSchema;
|
|
5713
6190
|
exports.SerializedNumberSchema = SerializedNumberSchema;
|
|
5714
6191
|
exports.SerializedObjectSchema = SerializedObjectSchema;
|
|
5715
6192
|
exports.SerializedRecordSchema = SerializedRecordSchema;
|
|
@@ -5736,6 +6213,7 @@ exports.concatModulePath = concatModulePath;
|
|
|
5736
6213
|
exports.createRegExpFromPattern = createRegExpFromPattern;
|
|
5737
6214
|
exports.createSearchIndex = createSearchIndex;
|
|
5738
6215
|
exports.createValClient = createValClient;
|
|
6216
|
+
exports.declaredLocales = declaredLocales;
|
|
5739
6217
|
exports.describeContainerAtPath = describeContainerAtPath;
|
|
5740
6218
|
exports.emptyOf = emptyOf;
|
|
5741
6219
|
exports.explainIncompatible = explainIncompatible;
|
|
@@ -5755,9 +6233,11 @@ exports.getSourceAt = getSourceAt;
|
|
|
5755
6233
|
exports.indexModule = indexModule;
|
|
5756
6234
|
exports.isMimeTypeAccepted = isMimeTypeAccepted;
|
|
5757
6235
|
exports.isRemoteSchema = isRemoteSchema;
|
|
6236
|
+
exports.isSchemaSourceFixError = isSchemaSourceFixError;
|
|
5758
6237
|
exports.isSkippedSource = isSkippedSource;
|
|
5759
6238
|
exports.keyOfRecordPath = keyOfRecordPath;
|
|
5760
6239
|
exports.levenshtein = levenshtein;
|
|
6240
|
+
exports.localeAt = localeAt;
|
|
5761
6241
|
exports.newestCommitSha = newestCommitSha;
|
|
5762
6242
|
exports.partitionValidationErrors = partitionValidationErrors;
|
|
5763
6243
|
exports.performSearch = performSearch;
|