@valbuild/shared 0.113.0 → 0.116.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/dist/declarations/src/internal/ApiRoutes.d.ts +1 -30
- package/dist/declarations/src/internal/aiTools/aiImageToolPatches.d.ts +60 -0
- package/dist/declarations/src/internal/aiTools/aiSourceToolPatches.d.ts +44 -0
- package/dist/declarations/src/internal/aiTools/toolNames.d.ts +2 -0
- package/dist/declarations/src/internal/emptyOf.d.ts +2 -0
- package/dist/declarations/src/internal/index.d.ts +6 -0
- package/dist/declarations/src/internal/validation/blockingValidationErrors.d.ts +26 -0
- package/dist/declarations/src/internal/validation/partitionValidationErrors.d.ts +27 -0
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +777 -26
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +777 -26
- package/internal/dist/valbuild-shared-internal.esm.js +764 -28
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Internal, CODE_LANGUAGES } from '@valbuild/core';
|
|
1
|
+
import { Internal, CODE_LANGUAGES, DEFAULT_COLOR_FORMAT } from '@valbuild/core';
|
|
2
2
|
import { b as base64DataUrlToUint8Array } from '../../dist/utils-00f3e1df.esm.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { fromError } from 'zod-validation-error';
|
|
@@ -2014,31 +2014,6 @@ var Api = {
|
|
|
2014
2014
|
})])
|
|
2015
2015
|
}
|
|
2016
2016
|
},
|
|
2017
|
-
"/commit-summary": {
|
|
2018
|
-
GET: {
|
|
2019
|
-
req: {
|
|
2020
|
-
query: {
|
|
2021
|
-
patch_id: z.array(PatchId)
|
|
2022
|
-
},
|
|
2023
|
-
cookies: {
|
|
2024
|
-
val_session: z.string().optional()
|
|
2025
|
-
}
|
|
2026
|
-
},
|
|
2027
|
-
res: z.union([unauthorizedResponse, z.object({
|
|
2028
|
-
status: z.literal(400),
|
|
2029
|
-
json: z.object({
|
|
2030
|
-
message: z.string()
|
|
2031
|
-
})
|
|
2032
|
-
}), z.object({
|
|
2033
|
-
status: z.literal(200),
|
|
2034
|
-
json: z.object({
|
|
2035
|
-
patchIds: z.array(PatchId),
|
|
2036
|
-
baseSha: z.string(),
|
|
2037
|
-
commitSummary: z.string().nullable()
|
|
2038
|
-
})
|
|
2039
|
-
})])
|
|
2040
|
-
}
|
|
2041
|
-
},
|
|
2042
2017
|
"/save": {
|
|
2043
2018
|
POST: {
|
|
2044
2019
|
req: {
|
|
@@ -2210,7 +2185,21 @@ var Api = {
|
|
|
2210
2185
|
status: z.literal(200),
|
|
2211
2186
|
json: z.object({
|
|
2212
2187
|
nonce: z.string(),
|
|
2213
|
-
wsUrl: z.string()
|
|
2188
|
+
wsUrl: z.string(),
|
|
2189
|
+
/**
|
|
2190
|
+
* The AI providers this project can actually reach.
|
|
2191
|
+
*
|
|
2192
|
+
* AI runs on a key the org or the user brought, so an org with only
|
|
2193
|
+
* an Anthropic key cannot use a GPT model — asking for one gets a
|
|
2194
|
+
* refusal. The client owns the model catalog and picks a model whose
|
|
2195
|
+
* provider is in here.
|
|
2196
|
+
*
|
|
2197
|
+
* `string[]` and not an enum on purpose: the content server may add
|
|
2198
|
+
* a provider before the Studio knows of it, and a strict enum would
|
|
2199
|
+
* reject the whole response over a name this version has not heard
|
|
2200
|
+
* of. Unknown entries are simply ignored.
|
|
2201
|
+
*/
|
|
2202
|
+
providers: z.array(z.string()).optional()
|
|
2214
2203
|
})
|
|
2215
2204
|
}), z.object({
|
|
2216
2205
|
status: z.literal(500),
|
|
@@ -3456,4 +3445,751 @@ function withValCanvasParam(url) {
|
|
|
3456
3445
|
return "".concat(url).concat(separator).concat(VAL_CANVAS_PARAM, "=1");
|
|
3457
3446
|
}
|
|
3458
3447
|
|
|
3459
|
-
|
|
3448
|
+
/**
|
|
3449
|
+
* Local `yyyy-MM-dd`, which is the one thing this module used `date-fns` for.
|
|
3450
|
+
*
|
|
3451
|
+
* Inlined rather than carried along: `@valbuild/shared` depends on nothing but
|
|
3452
|
+
* `@valbuild/core` and zod, and a whole date library is not worth adding to
|
|
3453
|
+
* that for a single format string. Deliberately the *local* date, not
|
|
3454
|
+
* `toISOString().slice(0, 10)` — the latter is UTC, so anyone west of
|
|
3455
|
+
* Greenwich would get yesterday's date as their "today" default.
|
|
3456
|
+
*/
|
|
3457
|
+
function formatLocalDate(date) {
|
|
3458
|
+
var year = String(date.getFullYear()).padStart(4, "0");
|
|
3459
|
+
var month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3460
|
+
var day = String(date.getDate()).padStart(2, "0");
|
|
3461
|
+
return "".concat(year, "-").concat(month, "-").concat(day);
|
|
3462
|
+
}
|
|
3463
|
+
function clampDateString(value, options) {
|
|
3464
|
+
if (options !== null && options !== void 0 && options.to && value > options.to) return options.to;
|
|
3465
|
+
if (options !== null && options !== void 0 && options.from && value < options.from) return options.from;
|
|
3466
|
+
return value;
|
|
3467
|
+
}
|
|
3468
|
+
function clampDateTimeString(value, options) {
|
|
3469
|
+
if (!options) return value;
|
|
3470
|
+
var ms = Date.parse(value);
|
|
3471
|
+
if (Number.isNaN(ms)) return value;
|
|
3472
|
+
// Stored datetime values are always UTC ISO strings, so normalize the
|
|
3473
|
+
// clamped bound (which may carry a timezone offset) via toISOString().
|
|
3474
|
+
if (options.to) {
|
|
3475
|
+
var toMs = Date.parse(options.to);
|
|
3476
|
+
if (!Number.isNaN(toMs) && ms > toMs) return new Date(toMs).toISOString();
|
|
3477
|
+
}
|
|
3478
|
+
if (options.from) {
|
|
3479
|
+
var fromMs = Date.parse(options.from);
|
|
3480
|
+
if (!Number.isNaN(fromMs) && ms < fromMs) return new Date(fromMs).toISOString();
|
|
3481
|
+
}
|
|
3482
|
+
return value;
|
|
3483
|
+
}
|
|
3484
|
+
function emptyOf(schema) {
|
|
3485
|
+
if (schema.type === "object") {
|
|
3486
|
+
return Object.fromEntries(Object.keys(schema.items).map(function (key) {
|
|
3487
|
+
return [key, emptyOf(schema.items[key])];
|
|
3488
|
+
}));
|
|
3489
|
+
} else if (schema.type === "array") {
|
|
3490
|
+
return [];
|
|
3491
|
+
} else if (schema.type === "record") {
|
|
3492
|
+
return {};
|
|
3493
|
+
} else if (schema.opt) {
|
|
3494
|
+
return null;
|
|
3495
|
+
} else if (schema.type === "richtext") {
|
|
3496
|
+
return [];
|
|
3497
|
+
} else if (schema.type === "string") {
|
|
3498
|
+
return "";
|
|
3499
|
+
} else if (schema.type === "boolean") {
|
|
3500
|
+
return false;
|
|
3501
|
+
} else if (schema.type === "number") {
|
|
3502
|
+
return 0;
|
|
3503
|
+
} else if (schema.type === "keyOf") {
|
|
3504
|
+
if (schema.values === "string") {
|
|
3505
|
+
return ""; // TODO: figure out this: user code might very well fail in this case
|
|
3506
|
+
} else {
|
|
3507
|
+
return schema.values[0];
|
|
3508
|
+
}
|
|
3509
|
+
} else if (schema.type === "route") {
|
|
3510
|
+
return ""; // Empty string as default route value
|
|
3511
|
+
} else if (schema.type === "file" || schema.type === "image") {
|
|
3512
|
+
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
|
|
3513
|
+
} else if (schema.type === "literal") {
|
|
3514
|
+
return schema.value;
|
|
3515
|
+
} else if (schema.type === "union") {
|
|
3516
|
+
if (typeof schema.key === "string") {
|
|
3517
|
+
return emptyOf(schema.items[0]);
|
|
3518
|
+
}
|
|
3519
|
+
return schema.key.value;
|
|
3520
|
+
} else if (schema.type === "date") {
|
|
3521
|
+
return clampDateString(formatLocalDate(new Date()), schema.options);
|
|
3522
|
+
} else if (schema.type === "dateTime") {
|
|
3523
|
+
return clampDateTimeString(new Date().toISOString(), schema.options);
|
|
3524
|
+
} else if (schema.type === "color") {
|
|
3525
|
+
var _schema$options$forma, _schema$options;
|
|
3526
|
+
// Mid grey: visible against both a light and a dark canvas
|
|
3527
|
+
return Internal.color.formatColor({
|
|
3528
|
+
r: 128,
|
|
3529
|
+
g: 128,
|
|
3530
|
+
b: 128,
|
|
3531
|
+
a: 1
|
|
3532
|
+
}, (_schema$options$forma = (_schema$options = schema.options) === null || _schema$options === void 0 ? void 0 : _schema$options.format) !== null && _schema$options$forma !== void 0 ? _schema$options$forma : DEFAULT_COLOR_FORMAT);
|
|
3533
|
+
} else if (schema.type === "code") {
|
|
3534
|
+
return ""; // An empty editor: no language has a sensible starting snippet
|
|
3535
|
+
}
|
|
3536
|
+
var _exhaustiveCheck = schema;
|
|
3537
|
+
throw Error("Unexpected schema type: " + JSON.stringify(_exhaustiveCheck));
|
|
3538
|
+
}
|
|
3539
|
+
|
|
3540
|
+
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"];
|
|
3541
|
+
|
|
3542
|
+
function buildFileRefValue(filePath, metadata) {
|
|
3543
|
+
return _objectSpread2({
|
|
3544
|
+
path: filePath
|
|
3545
|
+
}, metadata);
|
|
3546
|
+
}
|
|
3547
|
+
function getSourceAt(source, path) {
|
|
3548
|
+
var current = source;
|
|
3549
|
+
var _iterator = _createForOfIteratorHelper(path),
|
|
3550
|
+
_step;
|
|
3551
|
+
try {
|
|
3552
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
3553
|
+
var part = _step.value;
|
|
3554
|
+
if (current === null || current === undefined) return undefined;
|
|
3555
|
+
if (Array.isArray(current)) {
|
|
3556
|
+
var idx = Number(part);
|
|
3557
|
+
if (!Number.isInteger(idx)) return undefined;
|
|
3558
|
+
current = current[idx];
|
|
3559
|
+
} else if (_typeof(current) === "object") {
|
|
3560
|
+
current = current[part];
|
|
3561
|
+
} else {
|
|
3562
|
+
return undefined;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
} catch (err) {
|
|
3566
|
+
_iterator.e(err);
|
|
3567
|
+
} finally {
|
|
3568
|
+
_iterator.f();
|
|
3569
|
+
}
|
|
3570
|
+
return current;
|
|
3571
|
+
}
|
|
3572
|
+
/**
|
|
3573
|
+
* Walks `schema` along `path`, returning a structured result:
|
|
3574
|
+
* - `leaf`: walked the full path; resolved schema at the end.
|
|
3575
|
+
* - `richtext`: hit a richtext mid-walk; richtext is the resolved schema.
|
|
3576
|
+
* - `gallery-traversed`: hit an `s.images()` record and walked past it (i.e. the
|
|
3577
|
+
* path tries to address an entry inside the gallery — a clue the AI should
|
|
3578
|
+
* have used the gallery tool instead).
|
|
3579
|
+
* - `unresolved`: the path could not be walked.
|
|
3580
|
+
*/
|
|
3581
|
+
function resolveSerializedSchemaAtPath(schema, path) {
|
|
3582
|
+
var current = schema;
|
|
3583
|
+
for (var i = 0; i < path.length; i++) {
|
|
3584
|
+
var part = path[i];
|
|
3585
|
+
if (current.type === "object") {
|
|
3586
|
+
var next = current.items[part];
|
|
3587
|
+
if (!next) return {
|
|
3588
|
+
kind: "unresolved"
|
|
3589
|
+
};
|
|
3590
|
+
current = next;
|
|
3591
|
+
} else if (current.type === "array") {
|
|
3592
|
+
current = current.item;
|
|
3593
|
+
} else if (current.type === "record") {
|
|
3594
|
+
if (current.mediaType === "images") {
|
|
3595
|
+
return {
|
|
3596
|
+
kind: "gallery-traversed",
|
|
3597
|
+
schema: current
|
|
3598
|
+
};
|
|
3599
|
+
}
|
|
3600
|
+
current = current.item;
|
|
3601
|
+
} else if (current.type === "richtext") {
|
|
3602
|
+
return {
|
|
3603
|
+
kind: "richtext",
|
|
3604
|
+
schema: current,
|
|
3605
|
+
remainingPath: path.slice(i)
|
|
3606
|
+
};
|
|
3607
|
+
} else if (current.type === "union") {
|
|
3608
|
+
if (typeof current.key === "string") {
|
|
3609
|
+
var _iterator2 = _createForOfIteratorHelper(current.items),
|
|
3610
|
+
_step2;
|
|
3611
|
+
try {
|
|
3612
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
3613
|
+
var variant = _step2.value;
|
|
3614
|
+
var resolved = resolveSerializedSchemaAtPath(variant, path.slice(i));
|
|
3615
|
+
if (resolved.kind !== "unresolved") return resolved;
|
|
3616
|
+
}
|
|
3617
|
+
} catch (err) {
|
|
3618
|
+
_iterator2.e(err);
|
|
3619
|
+
} finally {
|
|
3620
|
+
_iterator2.f();
|
|
3621
|
+
}
|
|
3622
|
+
return {
|
|
3623
|
+
kind: "unresolved"
|
|
3624
|
+
};
|
|
3625
|
+
}
|
|
3626
|
+
return {
|
|
3627
|
+
kind: "unresolved"
|
|
3628
|
+
};
|
|
3629
|
+
} else {
|
|
3630
|
+
return {
|
|
3631
|
+
kind: "unresolved"
|
|
3632
|
+
};
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
return {
|
|
3636
|
+
kind: "leaf",
|
|
3637
|
+
schema: current
|
|
3638
|
+
};
|
|
3639
|
+
}
|
|
3640
|
+
function getInlineImgInfo(richtextSchema) {
|
|
3641
|
+
var _richtextSchema$optio;
|
|
3642
|
+
if (richtextSchema.type !== "richtext") return {
|
|
3643
|
+
kind: "not-allowed"
|
|
3644
|
+
};
|
|
3645
|
+
var img = (_richtextSchema$optio = richtextSchema.options) === null || _richtextSchema$optio === void 0 || (_richtextSchema$optio = _richtextSchema$optio.inline) === null || _richtextSchema$optio === void 0 ? void 0 : _richtextSchema$optio.img;
|
|
3646
|
+
if (!img) return {
|
|
3647
|
+
kind: "not-allowed"
|
|
3648
|
+
};
|
|
3649
|
+
if (img === true) return {
|
|
3650
|
+
kind: "allowed",
|
|
3651
|
+
remote: false
|
|
3652
|
+
};
|
|
3653
|
+
return {
|
|
3654
|
+
kind: "allowed",
|
|
3655
|
+
remote: img.remote === true
|
|
3656
|
+
};
|
|
3657
|
+
}
|
|
3658
|
+
function isRemoteSchema(schema) {
|
|
3659
|
+
if (schema.type === "image" || schema.type === "file") {
|
|
3660
|
+
return schema.remote === true;
|
|
3661
|
+
}
|
|
3662
|
+
if (schema.type === "record") {
|
|
3663
|
+
return schema.remote === true;
|
|
3664
|
+
}
|
|
3665
|
+
return false;
|
|
3666
|
+
}
|
|
3667
|
+
function safeParsePatch(patch) {
|
|
3668
|
+
var parsed = Patch.safeParse(patch);
|
|
3669
|
+
if (!parsed.success) {
|
|
3670
|
+
return {
|
|
3671
|
+
kind: "error",
|
|
3672
|
+
message: "Built patch failed schema validation: ".concat(JSON.stringify(parsed.error))
|
|
3673
|
+
};
|
|
3674
|
+
}
|
|
3675
|
+
return {
|
|
3676
|
+
kind: "ok",
|
|
3677
|
+
patch: parsed.data
|
|
3678
|
+
};
|
|
3679
|
+
}
|
|
3680
|
+
function checkGallerySchema(moduleSchema) {
|
|
3681
|
+
if (moduleSchema.type === "record" && moduleSchema.mediaType === "images") {
|
|
3682
|
+
return null;
|
|
3683
|
+
}
|
|
3684
|
+
if (moduleSchema.type === "image") {
|
|
3685
|
+
return {
|
|
3686
|
+
kind: "wrong-tool",
|
|
3687
|
+
suggestedTool: "create_patch",
|
|
3688
|
+
reason: "Module is a plain image field, not an images gallery. Use create_patch with a SessionKey value."
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
if (moduleSchema.type === "richtext") {
|
|
3692
|
+
return {
|
|
3693
|
+
kind: "wrong-tool",
|
|
3694
|
+
suggestedTool: "create_patch",
|
|
3695
|
+
reason: "Module is a richtext, not an images gallery. Use create_patch with a SessionKey inside a {tag:'img', src: SessionKey} node."
|
|
3696
|
+
};
|
|
3697
|
+
}
|
|
3698
|
+
return {
|
|
3699
|
+
kind: "error",
|
|
3700
|
+
message: "Module schema is not an images gallery (expected record with mediaType=\"images\", got '".concat(moduleSchema.type, "').")
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
function buildImageGalleryPatch(args, moduleSchema) {
|
|
3704
|
+
var wrong = checkGallerySchema(moduleSchema);
|
|
3705
|
+
if (wrong) return wrong;
|
|
3706
|
+
var remote = isRemoteSchema(moduleSchema);
|
|
3707
|
+
var patch = [{
|
|
3708
|
+
op: "add",
|
|
3709
|
+
path: [args.filePath],
|
|
3710
|
+
value: _objectSpread2({}, args.metadata)
|
|
3711
|
+
}, {
|
|
3712
|
+
op: "file",
|
|
3713
|
+
path: [args.filePath],
|
|
3714
|
+
filePath: args.filePath,
|
|
3715
|
+
value: args.imageKey,
|
|
3716
|
+
remote: remote,
|
|
3717
|
+
metadata: args.metadata
|
|
3718
|
+
}];
|
|
3719
|
+
return safeParsePatch(patch);
|
|
3720
|
+
}
|
|
3721
|
+
function buildRemoveImageGalleryEntryPatch(args, moduleSchema, moduleSource) {
|
|
3722
|
+
var wrong = checkGallerySchema(moduleSchema);
|
|
3723
|
+
if (wrong) return wrong;
|
|
3724
|
+
if (!moduleSource || _typeof(moduleSource) !== "object" || Array.isArray(moduleSource)) {
|
|
3725
|
+
return {
|
|
3726
|
+
kind: "error",
|
|
3727
|
+
message: "Cannot remove from gallery: module source is not an object."
|
|
3728
|
+
};
|
|
3729
|
+
}
|
|
3730
|
+
var entries = moduleSource;
|
|
3731
|
+
if (!Object.prototype.hasOwnProperty.call(entries, args.filePath)) {
|
|
3732
|
+
var availableKeys = Object.keys(entries);
|
|
3733
|
+
var hint = availableKeys.length > 0 ? " Available entries: ".concat(availableKeys.map(function (k) {
|
|
3734
|
+
return "\"".concat(k, "\"");
|
|
3735
|
+
}).join(", "), ".") : " The gallery is empty.";
|
|
3736
|
+
return {
|
|
3737
|
+
kind: "error",
|
|
3738
|
+
message: "No gallery entry with file_path \"".concat(args.filePath, "\".").concat(hint)
|
|
3739
|
+
};
|
|
3740
|
+
}
|
|
3741
|
+
var remote = Internal.remote.splitRemoteRef(args.filePath).status === "success";
|
|
3742
|
+
var patch = [{
|
|
3743
|
+
op: "remove",
|
|
3744
|
+
path: [args.filePath]
|
|
3745
|
+
}, {
|
|
3746
|
+
op: "file",
|
|
3747
|
+
path: [args.filePath],
|
|
3748
|
+
filePath: args.filePath,
|
|
3749
|
+
value: null,
|
|
3750
|
+
remote: remote
|
|
3751
|
+
}];
|
|
3752
|
+
return safeParsePatch(patch);
|
|
3753
|
+
}
|
|
3754
|
+
|
|
3755
|
+
/**
|
|
3756
|
+
* Decides whether the duplicate/empty operation should produce an "add" or
|
|
3757
|
+
* "replace" JSON patch op by inspecting the destination's *parent* schema.
|
|
3758
|
+
*
|
|
3759
|
+
* - array / record parent → "add" (creating a new slot)
|
|
3760
|
+
* - object parent → "replace" (slot exists by schema definition)
|
|
3761
|
+
* - empty path → "replace" (overwriting the whole module)
|
|
3762
|
+
* - richtext / gallery parent → not supported; redirect to the right tool
|
|
3763
|
+
*/
|
|
3764
|
+
var GALLERY_REDIRECT = {
|
|
3765
|
+
kind: "wrong-tool",
|
|
3766
|
+
suggestedTool: "add_session_image_to_gallery",
|
|
3767
|
+
reason: "Destination is a media gallery (s.images() / s.files()). 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."
|
|
3768
|
+
};
|
|
3769
|
+
|
|
3770
|
+
/** An `s.images()` / `s.files()` record: a gallery, not an ordinary record. */
|
|
3771
|
+
function isGallery(schema) {
|
|
3772
|
+
return schema.type === "record" && schema.mediaType !== undefined;
|
|
3773
|
+
}
|
|
3774
|
+
function decideOp(moduleSchema, destinationPath) {
|
|
3775
|
+
// The DESTINATION itself, checked before its parent: `["gallery"]` resolves
|
|
3776
|
+
// its parent to the enclosing object and would otherwise look like an
|
|
3777
|
+
// ordinary `replace` that overwrites a whole gallery.
|
|
3778
|
+
var destination = resolveSerializedSchemaAtPath(moduleSchema, destinationPath);
|
|
3779
|
+
if (destination.kind === "gallery-traversed") {
|
|
3780
|
+
return GALLERY_REDIRECT;
|
|
3781
|
+
}
|
|
3782
|
+
if (destination.kind === "richtext") {
|
|
3783
|
+
return {
|
|
3784
|
+
kind: "wrong-tool",
|
|
3785
|
+
suggestedTool: "create_patch",
|
|
3786
|
+
reason: "Destination is a richtext value. duplicate_source and empty_at_path do not handle richtext edits."
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
if (destination.kind === "leaf") {
|
|
3790
|
+
if (isGallery(destination.schema)) {
|
|
3791
|
+
return GALLERY_REDIRECT;
|
|
3792
|
+
}
|
|
3793
|
+
// A richtext value the path lands exactly ON resolves as a leaf, not as
|
|
3794
|
+
// `kind: "richtext"` (which only fires when the walk continues INTO it).
|
|
3795
|
+
if (destination.schema.type === "richtext") {
|
|
3796
|
+
return {
|
|
3797
|
+
kind: "wrong-tool",
|
|
3798
|
+
suggestedTool: "create_patch",
|
|
3799
|
+
reason: "Destination is a richtext value. duplicate_source and empty_at_path do not handle richtext edits."
|
|
3800
|
+
};
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
if (destinationPath.length === 0) {
|
|
3804
|
+
return {
|
|
3805
|
+
kind: "ok",
|
|
3806
|
+
op: "replace",
|
|
3807
|
+
parent: "module"
|
|
3808
|
+
};
|
|
3809
|
+
}
|
|
3810
|
+
var parent = resolveSerializedSchemaAtPath(moduleSchema, destinationPath.slice(0, -1));
|
|
3811
|
+
if (parent.kind === "unresolved") {
|
|
3812
|
+
return {
|
|
3813
|
+
kind: "error",
|
|
3814
|
+
message: "Destination parent path ".concat(JSON.stringify(destinationPath.slice(0, -1)), " does not resolve in this module's schema.")
|
|
3815
|
+
};
|
|
3816
|
+
}
|
|
3817
|
+
if (parent.kind === "richtext") {
|
|
3818
|
+
return {
|
|
3819
|
+
kind: "wrong-tool",
|
|
3820
|
+
suggestedTool: "create_patch",
|
|
3821
|
+
reason: "Destination is inside a richtext value. duplicate_source and empty_at_path do not handle richtext edits."
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
// `gallery-traversed` means the walk stepped INTO a gallery, so the
|
|
3825
|
+
// destination is a gallery entry; `isGallery` catches the case where the
|
|
3826
|
+
// parent IS the gallery and the destination is a new entry key in it.
|
|
3827
|
+
if (parent.kind === "gallery-traversed" || isGallery(parent.schema)) {
|
|
3828
|
+
return GALLERY_REDIRECT;
|
|
3829
|
+
}
|
|
3830
|
+
var schema = parent.schema;
|
|
3831
|
+
if (schema.type === "array" || schema.type === "record") {
|
|
3832
|
+
return {
|
|
3833
|
+
kind: "ok",
|
|
3834
|
+
op: "add",
|
|
3835
|
+
parent: schema.type
|
|
3836
|
+
};
|
|
3837
|
+
}
|
|
3838
|
+
if (schema.type === "object") {
|
|
3839
|
+
return {
|
|
3840
|
+
kind: "ok",
|
|
3841
|
+
op: "replace",
|
|
3842
|
+
parent: "object"
|
|
3843
|
+
};
|
|
3844
|
+
}
|
|
3845
|
+
return {
|
|
3846
|
+
kind: "error",
|
|
3847
|
+
message: "Destination parent has schema type \"".concat(schema.type, "\" \u2014 cannot use duplicate_source/empty_at_path here. Use create_patch instead.")
|
|
3848
|
+
};
|
|
3849
|
+
}
|
|
3850
|
+
function buildDuplicatePatch(args, moduleSchema, moduleSource) {
|
|
3851
|
+
var value = getSourceAt(moduleSource, args.sourcePath);
|
|
3852
|
+
if (value === undefined) {
|
|
3853
|
+
return {
|
|
3854
|
+
kind: "error",
|
|
3855
|
+
message: "Source path ".concat(JSON.stringify(args.sourcePath), " does not exist in the module. Use get_source to inspect the current contents.")
|
|
3856
|
+
};
|
|
3857
|
+
}
|
|
3858
|
+
var decision = decideOp(moduleSchema, args.destinationPath);
|
|
3859
|
+
if (decision.kind === "wrong-tool") {
|
|
3860
|
+
return {
|
|
3861
|
+
kind: "wrong-tool",
|
|
3862
|
+
suggestedTool: decision.suggestedTool,
|
|
3863
|
+
reason: decision.reason
|
|
3864
|
+
};
|
|
3865
|
+
}
|
|
3866
|
+
if (decision.kind === "error") {
|
|
3867
|
+
return {
|
|
3868
|
+
kind: "error",
|
|
3869
|
+
message: decision.message
|
|
3870
|
+
};
|
|
3871
|
+
}
|
|
3872
|
+
var occupied = refuseOccupiedRecordKey(decision.parent, moduleSource, args.destinationPath);
|
|
3873
|
+
if (occupied) {
|
|
3874
|
+
return occupied;
|
|
3875
|
+
}
|
|
3876
|
+
return safeParsePatch([{
|
|
3877
|
+
op: decision.op,
|
|
3878
|
+
path: args.destinationPath,
|
|
3879
|
+
value: value
|
|
3880
|
+
}]);
|
|
3881
|
+
}
|
|
3882
|
+
|
|
3883
|
+
/**
|
|
3884
|
+
* Refuse to write over an existing record entry.
|
|
3885
|
+
*
|
|
3886
|
+
* `add` into a record replaces whatever is at that key, so duplicating or
|
|
3887
|
+
* scaffolding onto an occupied key silently destroys the entry that was there.
|
|
3888
|
+
* A caller guessing at keys — an agent especially — hits this by accident, and
|
|
3889
|
+
* nothing downstream reports it: the patch is valid, the content stays valid,
|
|
3890
|
+
* and an entry is simply gone.
|
|
3891
|
+
*
|
|
3892
|
+
* Only records. An array `add` inserts before the index rather than replacing
|
|
3893
|
+
* it, and an object's fields exist by definition, so `replace` on one is the
|
|
3894
|
+
* whole point rather than a mistake.
|
|
3895
|
+
*/
|
|
3896
|
+
function refuseOccupiedRecordKey(parent, moduleSource, destinationPath) {
|
|
3897
|
+
if (parent !== "record") {
|
|
3898
|
+
return null;
|
|
3899
|
+
}
|
|
3900
|
+
if (getSourceAt(moduleSource, destinationPath) === undefined) {
|
|
3901
|
+
return null;
|
|
3902
|
+
}
|
|
3903
|
+
var key = destinationPath[destinationPath.length - 1];
|
|
3904
|
+
return {
|
|
3905
|
+
kind: "error",
|
|
3906
|
+
message: "Destination key ".concat(JSON.stringify(key), " already exists, and writing to it would replace the entry that is there. Pick a key that is free -- get_record_keys lists the ones in use -- or use create_patch if you meant to change the existing entry.")
|
|
3907
|
+
};
|
|
3908
|
+
}
|
|
3909
|
+
function buildEmptyAtPathPatch(args, moduleSchema,
|
|
3910
|
+
// Required, not optional: the occupied-key check below is the only thing
|
|
3911
|
+
// standing between "scaffold an entry" and "delete the entry that was there",
|
|
3912
|
+
// and an optional argument is one a caller forgets.
|
|
3913
|
+
moduleSource) {
|
|
3914
|
+
var destinationSchema;
|
|
3915
|
+
if (args.destinationPath.length === 0) {
|
|
3916
|
+
destinationSchema = moduleSchema;
|
|
3917
|
+
} else {
|
|
3918
|
+
var result = resolveSerializedSchemaAtPath(moduleSchema, args.destinationPath);
|
|
3919
|
+
if (result.kind === "unresolved") {
|
|
3920
|
+
return {
|
|
3921
|
+
kind: "error",
|
|
3922
|
+
message: "Destination path ".concat(JSON.stringify(args.destinationPath), " does not resolve in this module's schema.")
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
if (result.kind === "richtext") {
|
|
3926
|
+
return {
|
|
3927
|
+
kind: "wrong-tool",
|
|
3928
|
+
suggestedTool: "create_patch",
|
|
3929
|
+
reason: "Destination is a richtext value. Use create_patch to build richtext content."
|
|
3930
|
+
};
|
|
3931
|
+
}
|
|
3932
|
+
if (result.kind === "gallery-traversed") {
|
|
3933
|
+
return {
|
|
3934
|
+
kind: "wrong-tool",
|
|
3935
|
+
suggestedTool: "add_session_image_to_gallery",
|
|
3936
|
+
reason: "Destination is inside an images gallery. Use add_session_image_to_gallery to add entries."
|
|
3937
|
+
};
|
|
3938
|
+
}
|
|
3939
|
+
destinationSchema = result.schema;
|
|
3940
|
+
}
|
|
3941
|
+
var decision = decideOp(moduleSchema, args.destinationPath);
|
|
3942
|
+
if (decision.kind === "wrong-tool") {
|
|
3943
|
+
return {
|
|
3944
|
+
kind: "wrong-tool",
|
|
3945
|
+
suggestedTool: decision.suggestedTool,
|
|
3946
|
+
reason: decision.reason
|
|
3947
|
+
};
|
|
3948
|
+
}
|
|
3949
|
+
if (decision.kind === "error") {
|
|
3950
|
+
return {
|
|
3951
|
+
kind: "error",
|
|
3952
|
+
message: decision.message
|
|
3953
|
+
};
|
|
3954
|
+
}
|
|
3955
|
+
var occupied = refuseOccupiedRecordKey(decision.parent, moduleSource, args.destinationPath);
|
|
3956
|
+
if (occupied) {
|
|
3957
|
+
return occupied;
|
|
3958
|
+
}
|
|
3959
|
+
var value = emptyOf(destinationSchema);
|
|
3960
|
+
return safeParsePatch([{
|
|
3961
|
+
op: decision.op,
|
|
3962
|
+
path: args.destinationPath,
|
|
3963
|
+
value: value
|
|
3964
|
+
}]);
|
|
3965
|
+
}
|
|
3966
|
+
|
|
3967
|
+
/**
|
|
3968
|
+
* What kind of container a path points at.
|
|
3969
|
+
*
|
|
3970
|
+
* `gallery` and `richtext` are called out separately from `record`/`array`
|
|
3971
|
+
* because the two callers disagree about them: `count_entries` can count either,
|
|
3972
|
+
* `get_record_keys` documents that it refuses both.
|
|
3973
|
+
*/
|
|
3974
|
+
|
|
3975
|
+
/**
|
|
3976
|
+
* Classifies the value at `path` using the SCHEMA, not just its runtime shape.
|
|
3977
|
+
*
|
|
3978
|
+
* The runtime shape is not enough: an `s.image()`/`s.file()` source, a richtext
|
|
3979
|
+
* node and a union variant are all plain objects at runtime, so classifying by
|
|
3980
|
+
* `typeof` alone let `get_record_keys` list a file ref's `_ref`/`_type` internals
|
|
3981
|
+
* or a richtext node's `tag`/`children` as if they were record keys.
|
|
3982
|
+
*/
|
|
3983
|
+
function describeContainerAtPath(moduleSchema, moduleSource, path) {
|
|
3984
|
+
var value = getSourceAt(moduleSource, path);
|
|
3985
|
+
if (value === undefined) {
|
|
3986
|
+
return {
|
|
3987
|
+
kind: "error",
|
|
3988
|
+
reason: "missing",
|
|
3989
|
+
message: "Path ".concat(JSON.stringify(path), " does not exist in the module source. Use get_source to inspect the current contents.")
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
var resolved = resolveSerializedSchemaAtPath(moduleSchema, path);
|
|
3993
|
+
if (resolved.kind === "unresolved") {
|
|
3994
|
+
return {
|
|
3995
|
+
kind: "error",
|
|
3996
|
+
reason: "missing",
|
|
3997
|
+
message: "Path ".concat(JSON.stringify(path), " does not resolve in this module's schema.")
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
if (resolved.kind === "richtext") {
|
|
4001
|
+
// Mid-richtext: the path addresses a node inside the richtext value, whose
|
|
4002
|
+
// internals (tag, children, ...) are not entries.
|
|
4003
|
+
return {
|
|
4004
|
+
kind: "error",
|
|
4005
|
+
reason: "not-a-container",
|
|
4006
|
+
message: "Path ".concat(JSON.stringify(path), " points inside a richtext value, which has no entries to count or list.")
|
|
4007
|
+
};
|
|
4008
|
+
}
|
|
4009
|
+
if (resolved.kind === "gallery-traversed") {
|
|
4010
|
+
return {
|
|
4011
|
+
kind: "error",
|
|
4012
|
+
reason: "not-a-container",
|
|
4013
|
+
message: "Path ".concat(JSON.stringify(path), " points inside a gallery entry, which has no entries to count or list.")
|
|
4014
|
+
};
|
|
4015
|
+
}
|
|
4016
|
+
var schema = resolved.schema;
|
|
4017
|
+
if (schema.type === "richtext") {
|
|
4018
|
+
if (!Array.isArray(value)) {
|
|
4019
|
+
return {
|
|
4020
|
+
kind: "error",
|
|
4021
|
+
reason: "not-a-container",
|
|
4022
|
+
message: "Path ".concat(JSON.stringify(path), " is a richtext value but its source is not a block array.")
|
|
4023
|
+
};
|
|
4024
|
+
}
|
|
4025
|
+
return {
|
|
4026
|
+
kind: "ok",
|
|
4027
|
+
container: "richtext",
|
|
4028
|
+
value: value
|
|
4029
|
+
};
|
|
4030
|
+
}
|
|
4031
|
+
if (schema.type === "array") {
|
|
4032
|
+
if (!Array.isArray(value)) {
|
|
4033
|
+
return {
|
|
4034
|
+
kind: "error",
|
|
4035
|
+
reason: "not-a-container",
|
|
4036
|
+
message: "Path ".concat(JSON.stringify(path), " is an array in the schema but its source is not an array.")
|
|
4037
|
+
};
|
|
4038
|
+
}
|
|
4039
|
+
return {
|
|
4040
|
+
kind: "ok",
|
|
4041
|
+
container: "array",
|
|
4042
|
+
value: value
|
|
4043
|
+
};
|
|
4044
|
+
}
|
|
4045
|
+
if (schema.type === "record" || schema.type === "object") {
|
|
4046
|
+
if (value === null || _typeof(value) !== "object" || Array.isArray(value)) {
|
|
4047
|
+
return {
|
|
4048
|
+
kind: "error",
|
|
4049
|
+
reason: "not-a-container",
|
|
4050
|
+
message: "Path ".concat(JSON.stringify(path), " points to a ").concat(value === null ? "null" : Array.isArray(value) ? "array" : _typeof(value), " value, which has no entries to count or list.")
|
|
4051
|
+
};
|
|
4052
|
+
}
|
|
4053
|
+
return {
|
|
4054
|
+
kind: "ok",
|
|
4055
|
+
container: schema.type === "record" ? isGallery(schema) ? "gallery" : "record" : "object",
|
|
4056
|
+
value: value
|
|
4057
|
+
};
|
|
4058
|
+
}
|
|
4059
|
+
// image / file / union / string / number / boolean / date / literal / keyOf /
|
|
4060
|
+
// route: not containers, whatever their runtime shape looks like.
|
|
4061
|
+
return {
|
|
4062
|
+
kind: "error",
|
|
4063
|
+
reason: "not-a-container",
|
|
4064
|
+
message: "Path ".concat(JSON.stringify(path), " points to a \"").concat(schema.type, "\" value, which has no entries to count or list.")
|
|
4065
|
+
};
|
|
4066
|
+
}
|
|
4067
|
+
|
|
4068
|
+
/**
|
|
4069
|
+
* Partition validation errors by whether the UI should surface them.
|
|
4070
|
+
*
|
|
4071
|
+
* `skipped` errors carry only fix codes the user can't (or shouldn't) act on
|
|
4072
|
+
* in the browser:
|
|
4073
|
+
* - image/file metadata checks (need to read bytes from disk)
|
|
4074
|
+
* - remote upload/download/check (need a personal access token + network)
|
|
4075
|
+
* - gallery directory uniqueness + untracked-files checks (need fs traversal)
|
|
4076
|
+
*
|
|
4077
|
+
* The server (ValOps + createFixPatch) resolves all of these automatically on
|
|
4078
|
+
* save, and the CLI's `runValidation` does the same. So the user never needs
|
|
4079
|
+
* to see them in the studio — but we keep them in the `skipped` partition,
|
|
4080
|
+
* not dropped, so we can later surface a "N fixes pending — saving will
|
|
4081
|
+
* repair them" badge or wire up an explicit "fix all" affordance without
|
|
4082
|
+
* having to plumb the data back in.
|
|
4083
|
+
*
|
|
4084
|
+
* `keyof:check-keys` and `router:check-route` are surfaced if they reach
|
|
4085
|
+
* this function — they're meant to be resolved upfront by the shared
|
|
4086
|
+
* `resolveSchemaSourceFixes`. A remnant here means resolution didn't run
|
|
4087
|
+
* for some reason; the user-facing "Invalid key/route" message is more
|
|
4088
|
+
* useful than silent hiding.
|
|
4089
|
+
*/
|
|
4090
|
+
function partitionValidationErrors(validationErrors) {
|
|
4091
|
+
var surfaced = {};
|
|
4092
|
+
var skipped = {};
|
|
4093
|
+
for (var sourcePathS in validationErrors) {
|
|
4094
|
+
var sourcePath = sourcePathS;
|
|
4095
|
+
var _iterator = _createForOfIteratorHelper(validationErrors[sourcePath]),
|
|
4096
|
+
_step;
|
|
4097
|
+
try {
|
|
4098
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
4099
|
+
var error = _step.value;
|
|
4100
|
+
if (isSkippedFix(error)) {
|
|
4101
|
+
var _skipped$sourcePath;
|
|
4102
|
+
((_skipped$sourcePath = skipped[sourcePath]) !== null && _skipped$sourcePath !== void 0 ? _skipped$sourcePath : skipped[sourcePath] = []).push(error);
|
|
4103
|
+
} else {
|
|
4104
|
+
var _surfaced$sourcePath;
|
|
4105
|
+
((_surfaced$sourcePath = surfaced[sourcePath]) !== null && _surfaced$sourcePath !== void 0 ? _surfaced$sourcePath : surfaced[sourcePath] = []).push(error);
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
} catch (err) {
|
|
4109
|
+
_iterator.e(err);
|
|
4110
|
+
} finally {
|
|
4111
|
+
_iterator.f();
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
return {
|
|
4115
|
+
surfaced: surfaced,
|
|
4116
|
+
skipped: skipped
|
|
4117
|
+
};
|
|
4118
|
+
}
|
|
4119
|
+
function isSkippedFix(error) {
|
|
4120
|
+
var _error$fixes;
|
|
4121
|
+
var fixes = (_error$fixes = error.fixes) !== null && _error$fixes !== void 0 ? _error$fixes : [];
|
|
4122
|
+
if (fixes.length === 0) return false;
|
|
4123
|
+
// Skip iff EVERY fix on the error is in the skip set — an error tagged
|
|
4124
|
+
// with both a surfaceable and a skippable fix must still be shown.
|
|
4125
|
+
return fixes.every(isSkippableFixCode);
|
|
4126
|
+
}
|
|
4127
|
+
function isSkippableFixCode(fix) {
|
|
4128
|
+
switch (fix) {
|
|
4129
|
+
case "image:add-metadata":
|
|
4130
|
+
case "image:check-metadata":
|
|
4131
|
+
case "image:upload-remote":
|
|
4132
|
+
case "image:download-remote":
|
|
4133
|
+
case "image:check-remote":
|
|
4134
|
+
case "images:check-remote":
|
|
4135
|
+
case "images:upload-remote":
|
|
4136
|
+
case "file:add-metadata":
|
|
4137
|
+
case "file:check-metadata":
|
|
4138
|
+
case "file:upload-remote":
|
|
4139
|
+
case "file:download-remote":
|
|
4140
|
+
case "file:check-remote":
|
|
4141
|
+
case "files:check-remote":
|
|
4142
|
+
case "files:upload-remote":
|
|
4143
|
+
case "images:check-unique-folder":
|
|
4144
|
+
case "files:check-unique-folder":
|
|
4145
|
+
case "images:check-all-files":
|
|
4146
|
+
case "files:check-all-files":
|
|
4147
|
+
return true;
|
|
4148
|
+
case "keyof:check-keys":
|
|
4149
|
+
case "router:check-route":
|
|
4150
|
+
case "jsonValues:extract-entry":
|
|
4151
|
+
// `jsonValues:extract-entry` is an entry inlined in the `.val.ts`. The
|
|
4152
|
+
// browser cannot fix it (that means writing a new `*.val.json` and
|
|
4153
|
+
// rewriting the module) and saving does not repair it either, so surface
|
|
4154
|
+
// it: the message names the command (`val validate --fix`) that does.
|
|
4155
|
+
return false;
|
|
4156
|
+
default:
|
|
4157
|
+
{
|
|
4158
|
+
return false;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
|
|
4163
|
+
/**
|
|
4164
|
+
* The errors a user must actually act on.
|
|
4165
|
+
*
|
|
4166
|
+
* Two passes stand between a schema's complaint and something worth blocking a
|
|
4167
|
+
* publish for:
|
|
4168
|
+
*
|
|
4169
|
+
* - `resolveSchemaSourceFixes` resolves the CROSS-MODULE fixes —
|
|
4170
|
+
* `keyof:check-keys` and `router:check-route` — against the live schema and
|
|
4171
|
+
* source. Unresolved, those arrive as "This error should typically be
|
|
4172
|
+
* processed by Val internally. Seeing this error most likely means you have a
|
|
4173
|
+
* Val version mismatch", which is not something a user can do anything with.
|
|
4174
|
+
* - `partitionValidationErrors` drops the fixes the SERVER applies on save:
|
|
4175
|
+
* image and file metadata, remote files, gallery directory checks. Blocking on
|
|
4176
|
+
* those would refuse a publish for something the publish itself repairs.
|
|
4177
|
+
*
|
|
4178
|
+
* ## Everything that gates on validation must use this
|
|
4179
|
+
*
|
|
4180
|
+
* That is the whole reason it lives in `validation/` rather than beside one of
|
|
4181
|
+
* its callers. There are three: the errors a field shows, the AI flow's check on
|
|
4182
|
+
* a proposed patch, and — the one that bites — `system.publish`. A publish gate
|
|
4183
|
+
* reading raw errors refuses on `router:check-route` for every route module in
|
|
4184
|
+
* the project, which is a Save button that does nothing and says
|
|
4185
|
+
* "validation-errors" with no error visible anywhere on screen.
|
|
4186
|
+
*/
|
|
4187
|
+
function filterBlockingValidationErrors(validationErrors, schemas, sources) {
|
|
4188
|
+
var resolved = resolveSchemaSourceFixes(validationErrors, {
|
|
4189
|
+
schemas: schemas !== null && schemas !== void 0 ? schemas : {},
|
|
4190
|
+
sources: sources !== null && sources !== void 0 ? sources : {}
|
|
4191
|
+
});
|
|
4192
|
+
return partitionValidationErrors(resolved).surfaced;
|
|
4193
|
+
}
|
|
4194
|
+
|
|
4195
|
+
export { Api, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, FileOptions, ImageEncodeOption, ImageOptions, JSON_ENTRIES_BATCH_MAX, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RichTextOptions, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedStringSchema, SerializedUnionSchema, SharedValConfig, VAL_AI_SESSION_STORAGE_KEY, VAL_CANVAS_MESSAGE, VAL_CANVAS_PARAM, VAL_CONFIG_SESSION_STORAGE_KEY, VAL_ENABLE_COOKIE_NAME, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_THEME_SESSION_STORAGE_KEY, ValCommit, ValDeployment, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, createRegExpFromPattern, createValClient, describeContainerAtPath, emptyOf, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, getErrorMessageFromUnknownJson, getInlineImgInfo, getNextAppRouterSitemapTree, getNextAppRouterSourceFolder, getPatternFromModuleFilePath, getRoutesOf, getRoutesWithModulePaths, getSourceAt, isRemoteSchema, isValCanvasFrame, isValCanvasPageMessage, isValCanvasStudioMessage, levenshtein, parseRoutePattern, partitionValidationErrors, remirrorToRichTextSource, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextToRemirror, safeParsePatch, toolNames, urlOf, validateRoutePatterns, withValCanvasParam };
|