@valbuild/server 0.143.1 → 0.144.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 +17 -0
- package/dist/declarations/src/fixHandlers.d.ts +28 -0
- package/dist/declarations/src/videosetFixes.d.ts +5 -4
- package/dist/valbuild-server.cjs.dev.js +259 -42
- package/dist/valbuild-server.cjs.prod.js +259 -42
- package/dist/valbuild-server.esm.js +260 -43
- package/package.json +4 -4
|
@@ -8,7 +8,7 @@ import path__default from 'path';
|
|
|
8
8
|
import fs from 'fs';
|
|
9
9
|
import vm from 'node:vm';
|
|
10
10
|
import { Module } from 'node:module';
|
|
11
|
-
import { isSchemaSourceFixError, resolveSchemaSourceFixForError, Patch, getErrorMessageFromUnknownJson, PatchId as PatchId$1, JSONValue, PatchGroup, newestCommitSha, SerializedSchema, VAL_ENABLE_COOKIE_NAME, VAL_STATE_COOKIE, VAL_SESSION_COOKIE, parseJob, VAL_STUDIO_HEADER, Api, traverseSchemaSource } from '@valbuild/shared/internal';
|
|
11
|
+
import { isSchemaSourceFixError, resolveSchemaSourceFixForError, Patch, getErrorMessageFromUnknownJson, PatchId as PatchId$1, JSONValue, PatchGroup, newestCommitSha, SerializedSchema, VAL_ENABLE_COOKIE_NAME, VAL_STATE_COOKIE, VAL_SESSION_COOKIE, parseJob, VAL_STUDIO_HEADER, Api, traverseSchemaSource, richTextImageSchema, forEachRichTextImage } from '@valbuild/shared/internal';
|
|
12
12
|
import { createUIRequestHandler } from '@valbuild/ui/server';
|
|
13
13
|
import crypto$1 from 'crypto';
|
|
14
14
|
import z$1, { z } from 'zod';
|
|
@@ -20236,7 +20236,7 @@ function readFileOrUndefined$1(absolutePath) {
|
|
|
20236
20236
|
* be uploaded first). On the way DOWN the same playlists are rewritten back to
|
|
20237
20237
|
* relative names, which is what lets a published stream be plain static files.
|
|
20238
20238
|
*/
|
|
20239
|
-
function isRecord$
|
|
20239
|
+
function isRecord$3(value) {
|
|
20240
20240
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20241
20241
|
}
|
|
20242
20242
|
function isPlaylist$1(ref) {
|
|
@@ -20245,14 +20245,14 @@ function isPlaylist$1(ref) {
|
|
|
20245
20245
|
|
|
20246
20246
|
/** The paths a video value holds, each with where in the value it sits. */
|
|
20247
20247
|
function videoPathsOf(video) {
|
|
20248
|
-
if (!isRecord$
|
|
20248
|
+
if (!isRecord$3(video) || typeof video.path !== "string") {
|
|
20249
20249
|
return [];
|
|
20250
20250
|
}
|
|
20251
20251
|
const found = [{
|
|
20252
20252
|
at: ["path"],
|
|
20253
20253
|
path: video.path
|
|
20254
20254
|
}];
|
|
20255
|
-
if (isRecord$
|
|
20255
|
+
if (isRecord$3(video.poster) && typeof video.poster.path === "string") {
|
|
20256
20256
|
found.push({
|
|
20257
20257
|
at: ["poster", "path"],
|
|
20258
20258
|
path: video.poster.path
|
|
@@ -20260,7 +20260,7 @@ function videoPathsOf(video) {
|
|
|
20260
20260
|
}
|
|
20261
20261
|
if (Array.isArray(video.captions)) {
|
|
20262
20262
|
video.captions.forEach((track, index) => {
|
|
20263
|
-
if (isRecord$
|
|
20263
|
+
if (isRecord$3(track) && typeof track.path === "string") {
|
|
20264
20264
|
found.push({
|
|
20265
20265
|
at: ["captions", String(index), "path"],
|
|
20266
20266
|
path: track.path
|
|
@@ -20331,7 +20331,7 @@ function metadataOf(localRef, role, video) {
|
|
|
20331
20331
|
height: video.height
|
|
20332
20332
|
};
|
|
20333
20333
|
}
|
|
20334
|
-
if (role === "poster" && isRecord$
|
|
20334
|
+
if (role === "poster" && isRecord$3(video.poster)) {
|
|
20335
20335
|
return {
|
|
20336
20336
|
mimeType: video.poster.mimeType ?? mimeType,
|
|
20337
20337
|
width: video.poster.width,
|
|
@@ -20347,7 +20347,7 @@ function metadataOf(localRef, role, video) {
|
|
|
20347
20347
|
* Places a video's local files on Val Remote, each once, and remembers where.
|
|
20348
20348
|
*
|
|
20349
20349
|
* The one implementation of "upload a video" for every fix that does it: a
|
|
20350
|
-
* video field (`video:upload-remote`), and an entry of an `s.
|
|
20350
|
+
* video field (`video:upload-remote`), and an entry of an `s.videodir()`
|
|
20351
20351
|
* (`videos:upload-remote`). What differs between the two is which files go up
|
|
20352
20352
|
* and what their refs are hashed against, so those are the arguments.
|
|
20353
20353
|
*
|
|
@@ -20440,7 +20440,7 @@ function resolveVideo(ctx) {
|
|
|
20440
20440
|
}
|
|
20441
20441
|
const resolved = Internal.resolvePath(modulePath, ctx.valModule.source, ctx.valModule.schema);
|
|
20442
20442
|
const video = resolved.source;
|
|
20443
|
-
if (((_resolved$schema = resolved.schema) === null || _resolved$schema === void 0 ? void 0 : _resolved$schema.type) !== "video" || !isRecord$
|
|
20443
|
+
if (((_resolved$schema = resolved.schema) === null || _resolved$schema === void 0 ? void 0 : _resolved$schema.type) !== "video" || !isRecord$3(video) || typeof video.path !== "string") {
|
|
20444
20444
|
return {
|
|
20445
20445
|
success: false,
|
|
20446
20446
|
result: {
|
|
@@ -20460,7 +20460,7 @@ function resolveVideo(ctx) {
|
|
|
20460
20460
|
* The paths of a video FIELD that its fix moves.
|
|
20461
20461
|
*
|
|
20462
20462
|
* All of them for a video of its own. For a field picked from an
|
|
20463
|
-
* `s.
|
|
20463
|
+
* `s.videodir()` (`referencedModule`), only the poster and the captions: the
|
|
20464
20464
|
* video file is the set's — its key there — and moving it from here would
|
|
20465
20465
|
* leave the field naming a file the set does not have. The set's own fix
|
|
20466
20466
|
* (`videos:upload-remote`) moves it, and rewrites the fields that name it.
|
|
@@ -20633,6 +20633,192 @@ async function handleVideoDownloadRemote(ctx) {
|
|
|
20633
20633
|
};
|
|
20634
20634
|
}
|
|
20635
20635
|
|
|
20636
|
+
/**
|
|
20637
|
+
* The fields that name an entry of a media collection by its key, and the
|
|
20638
|
+
* patches that point them at a new key.
|
|
20639
|
+
*
|
|
20640
|
+
* A collection — `s.imagedir()`, `s.filedir()`, `s.videodir()` — is a record
|
|
20641
|
+
* keyed by each entry's file path, and a field picked from it
|
|
20642
|
+
* (`s.image(imagesVal)`, `s.file(filesVal)`, `s.video(videosVal)`) stores that
|
|
20643
|
+
* key as its `path`. So when `--fix` renames a key — moving an entry of a
|
|
20644
|
+
* `.remote()` collection to Val Remote renames it from the local path to the
|
|
20645
|
+
* ref — every field holding the old key would name an entry the collection no
|
|
20646
|
+
* longer has, and nothing could repair it afterwards.
|
|
20647
|
+
*
|
|
20648
|
+
* Two kinds of value name a key:
|
|
20649
|
+
*
|
|
20650
|
+
* - **A field whose schema is backed by the collection** (`referencedModule`).
|
|
20651
|
+
* - **An inline image in rich text** whose `img` schema is backed by it
|
|
20652
|
+
* (`s.richtext({ img: s.image(imagesVal) })`). The field's own schema is
|
|
20653
|
+
* `richtext`, so a walk looking only for image leaves goes straight past
|
|
20654
|
+
* them — the Studio's reference scan learned that once already
|
|
20655
|
+
* (`getReferencedFiles`), and uses the same `forEachRichTextImage`.
|
|
20656
|
+
*
|
|
20657
|
+
* **A field is renamed when the key it names is the old key**, and "names" is
|
|
20658
|
+
* `galleryKeyOf` in core: the field's `path` when that is a key, and otherwise
|
|
20659
|
+
* the local path inside it when it is a ref. That is how a field is read
|
|
20660
|
+
* (`fillFromGallery`) and how it is validated, so it is exactly the set of
|
|
20661
|
+
* fields the rename would break. The second shape is real: an image uploaded
|
|
20662
|
+
* THROUGH an `s.image(remoteGallery)` field in the Studio stores the ref in
|
|
20663
|
+
* the field and keys the entry by the local path inside it, so uploading that
|
|
20664
|
+
* entry here has to move the field to the entry's new key as well. A ref that
|
|
20665
|
+
* is itself a key names its own entry, and is left alone.
|
|
20666
|
+
*
|
|
20667
|
+
* Nothing here imports `fixHandlers.ts` at runtime: that module calls this one.
|
|
20668
|
+
*/
|
|
20669
|
+
|
|
20670
|
+
/** What of a `Service` the project-wide walk needs. */
|
|
20671
|
+
|
|
20672
|
+
/** A value that names an entry of a collection by its key. */
|
|
20673
|
+
|
|
20674
|
+
function isRecord$2(value) {
|
|
20675
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20676
|
+
}
|
|
20677
|
+
|
|
20678
|
+
/** Whether a serialized schema is backed by `collection` anywhere in it. */
|
|
20679
|
+
function isBackedBy(schema, collection) {
|
|
20680
|
+
if (Array.isArray(schema)) {
|
|
20681
|
+
return schema.some(item => isBackedBy(item, collection));
|
|
20682
|
+
}
|
|
20683
|
+
if (!isRecord$2(schema)) {
|
|
20684
|
+
return false;
|
|
20685
|
+
}
|
|
20686
|
+
if (schema.referencedModule === collection) {
|
|
20687
|
+
return true;
|
|
20688
|
+
}
|
|
20689
|
+
return Object.values(schema).some(value => isBackedBy(value, collection));
|
|
20690
|
+
}
|
|
20691
|
+
|
|
20692
|
+
/**
|
|
20693
|
+
* The references already found, per service and collection.
|
|
20694
|
+
*
|
|
20695
|
+
* `val validate --fix` renames a key once per local entry, so a gallery of N
|
|
20696
|
+
* local entries would otherwise walk the project N times — validating every
|
|
20697
|
+
* module that uses the gallery each time. Caching per `Service` is exact, not
|
|
20698
|
+
* an approximation: a `Service` answers `get` from the snapshot it was created
|
|
20699
|
+
* with (`patch` writes to disk and changes nothing it returns), so the walk
|
|
20700
|
+
* would find the same references every time. A new `Service` — the language
|
|
20701
|
+
* server makes one after every edit — starts with nothing cached.
|
|
20702
|
+
*/
|
|
20703
|
+
const referencesByService = new WeakMap();
|
|
20704
|
+
|
|
20705
|
+
/**
|
|
20706
|
+
* Every value in the project that names an entry of `collection`, as the
|
|
20707
|
+
* service's snapshot has it. Found once per service; see
|
|
20708
|
+
* {@link referencesByService}.
|
|
20709
|
+
*/
|
|
20710
|
+
function collectionReferencesOf(service, collection) {
|
|
20711
|
+
let byCollection = referencesByService.get(service);
|
|
20712
|
+
if (!byCollection) {
|
|
20713
|
+
byCollection = new Map();
|
|
20714
|
+
referencesByService.set(service, byCollection);
|
|
20715
|
+
}
|
|
20716
|
+
let references = byCollection.get(collection);
|
|
20717
|
+
if (!references) {
|
|
20718
|
+
references = findCollectionReferences(service, collection);
|
|
20719
|
+
// A walk that failed is not an answer; the next caller tries again.
|
|
20720
|
+
references.catch(() => byCollection.delete(collection));
|
|
20721
|
+
byCollection.set(collection, references);
|
|
20722
|
+
}
|
|
20723
|
+
return references;
|
|
20724
|
+
}
|
|
20725
|
+
|
|
20726
|
+
/**
|
|
20727
|
+
* The walk itself.
|
|
20728
|
+
*
|
|
20729
|
+
* Validated reads for the modules backed by the collection, because only
|
|
20730
|
+
* those come back with their `.jsonValues()` entries loaded — an unvalidated
|
|
20731
|
+
* read hands back each entry as a marker, and a field inside one would be
|
|
20732
|
+
* invisible. Every other module is read once, unvalidated, to find out it is
|
|
20733
|
+
* not one of them.
|
|
20734
|
+
*/
|
|
20735
|
+
async function findCollectionReferences(service, collection) {
|
|
20736
|
+
const found = [];
|
|
20737
|
+
for (const moduleFilePath of service.getModuleFilePaths()) {
|
|
20738
|
+
const shallow = await service.get(moduleFilePath, "", {
|
|
20739
|
+
validate: false
|
|
20740
|
+
});
|
|
20741
|
+
if (!isBackedBy(shallow.schema, collection)) {
|
|
20742
|
+
continue;
|
|
20743
|
+
}
|
|
20744
|
+
const loaded = await service.get(moduleFilePath, "", {
|
|
20745
|
+
validate: true
|
|
20746
|
+
});
|
|
20747
|
+
if (loaded.source === undefined || !loaded.schema) {
|
|
20748
|
+
continue;
|
|
20749
|
+
}
|
|
20750
|
+
const add = (sourcePath, value) => {
|
|
20751
|
+
if (isRecord$2(value) && typeof value.path === "string") {
|
|
20752
|
+
found.push({
|
|
20753
|
+
moduleFilePath,
|
|
20754
|
+
sourcePath,
|
|
20755
|
+
path: value.path
|
|
20756
|
+
});
|
|
20757
|
+
}
|
|
20758
|
+
};
|
|
20759
|
+
traverseSchemaSource(loaded.source, loaded.schema, moduleFilePath, ({
|
|
20760
|
+
source,
|
|
20761
|
+
schema,
|
|
20762
|
+
path: sourcePath
|
|
20763
|
+
}) => {
|
|
20764
|
+
if (schema.type === "image" || schema.type === "file" || schema.type === "video") {
|
|
20765
|
+
if (schema.referencedModule === collection) {
|
|
20766
|
+
add(sourcePath, source);
|
|
20767
|
+
}
|
|
20768
|
+
} else if (schema.type === "richtext") {
|
|
20769
|
+
var _richTextImageSchema;
|
|
20770
|
+
if (((_richTextImageSchema = richTextImageSchema(schema)) === null || _richTextImageSchema === void 0 ? void 0 : _richTextImageSchema.referencedModule) === collection) {
|
|
20771
|
+
forEachRichTextImage(sourcePath, source, add);
|
|
20772
|
+
}
|
|
20773
|
+
}
|
|
20774
|
+
});
|
|
20775
|
+
}
|
|
20776
|
+
return found;
|
|
20777
|
+
}
|
|
20778
|
+
|
|
20779
|
+
/**
|
|
20780
|
+
* The patch path of `sourcePath`. Not `sourceToPatchPath`: a collection's keys
|
|
20781
|
+
* are file paths, and their dots do not survive its `split(".")`.
|
|
20782
|
+
*/
|
|
20783
|
+
function patchPathOf$1(sourcePath) {
|
|
20784
|
+
const [, modulePath] = Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
20785
|
+
return Internal.splitModulePath(modulePath);
|
|
20786
|
+
}
|
|
20787
|
+
|
|
20788
|
+
/**
|
|
20789
|
+
* The patches that point every value naming a key in `renamed` at its new key.
|
|
20790
|
+
*
|
|
20791
|
+
* `renamed` is keyed by the collection's keys BEFORE the rename, and the
|
|
20792
|
+
* collection is read as it is now — so call this before its own patch lands.
|
|
20793
|
+
*
|
|
20794
|
+
* One `add` on each value's `path`, so the alt text, hotspot, poster and
|
|
20795
|
+
* captions beside it are never rewritten.
|
|
20796
|
+
*/
|
|
20797
|
+
async function collectionReferencePatches(service, collection, renamed) {
|
|
20798
|
+
const collectionSource = (await service.get(collection, "", {
|
|
20799
|
+
validate: false
|
|
20800
|
+
})).source;
|
|
20801
|
+
const keys = new Set(isRecord$2(collectionSource) ? Object.keys(collectionSource) : []);
|
|
20802
|
+
const byModule = new Map();
|
|
20803
|
+
for (const reference of await collectionReferencesOf(service, collection)) {
|
|
20804
|
+
const key = Internal.media.galleryKeyOf(reference.path, candidate => keys.has(candidate));
|
|
20805
|
+
if (key === null || !Object.prototype.hasOwnProperty.call(renamed, key)) {
|
|
20806
|
+
continue;
|
|
20807
|
+
}
|
|
20808
|
+
const patch = byModule.get(reference.moduleFilePath) ?? [];
|
|
20809
|
+
patch.push({
|
|
20810
|
+
op: "add",
|
|
20811
|
+
path: patchPathOf$1(reference.sourcePath).concat("path"),
|
|
20812
|
+
value: renamed[key]
|
|
20813
|
+
});
|
|
20814
|
+
byModule.set(reference.moduleFilePath, patch);
|
|
20815
|
+
}
|
|
20816
|
+
return [...byModule].map(([moduleFilePath, patch]) => ({
|
|
20817
|
+
moduleFilePath,
|
|
20818
|
+
patch
|
|
20819
|
+
}));
|
|
20820
|
+
}
|
|
20821
|
+
|
|
20636
20822
|
/**
|
|
20637
20823
|
* What is out of step between a gallery's entries and its directory.
|
|
20638
20824
|
*
|
|
@@ -20741,7 +20927,7 @@ function filesInDirectory({
|
|
|
20741
20927
|
}
|
|
20742
20928
|
|
|
20743
20929
|
/**
|
|
20744
|
-
* The fixes of an `s.
|
|
20930
|
+
* The fixes of an `s.videodir()` — the video twin of an image gallery.
|
|
20745
20931
|
*
|
|
20746
20932
|
* A set is a record keyed by each video's file path (an HLS stream by its
|
|
20747
20933
|
* master playlist), so most of this is the gallery fixes again with the key as
|
|
@@ -21004,34 +21190,14 @@ async function filesNamedByVideoFields(service, options) {
|
|
|
21004
21190
|
/**
|
|
21005
21191
|
* The patches that point every `s.video(set)` field at a set entry's new key.
|
|
21006
21192
|
*
|
|
21007
|
-
*
|
|
21008
|
-
*
|
|
21009
|
-
*
|
|
21010
|
-
*
|
|
21193
|
+
* The same walk an image or file collection's rename uses
|
|
21194
|
+
* (`collectionReferencePatches`): one `add` on each field's `path`, so the
|
|
21195
|
+
* description, poster, times and captions beside it are never rewritten, and
|
|
21196
|
+
* a field of another set, or of no set, is left alone even when its path is
|
|
21197
|
+
* the same string — it names its own file.
|
|
21011
21198
|
*/
|
|
21012
21199
|
async function videosetReferencePatches(service, setModuleFilePath, renamed) {
|
|
21013
|
-
|
|
21014
|
-
for (const field of await videoFieldsOf(service)) {
|
|
21015
|
-
if (field.schema.referencedModule !== setModuleFilePath) {
|
|
21016
|
-
continue;
|
|
21017
|
-
}
|
|
21018
|
-
const value = field.source;
|
|
21019
|
-
const current = isRecord$1(value) ? value.path : undefined;
|
|
21020
|
-
if (typeof current !== "string" || !(current in renamed)) {
|
|
21021
|
-
continue;
|
|
21022
|
-
}
|
|
21023
|
-
const patch = byModule.get(field.moduleFilePath) ?? [];
|
|
21024
|
-
patch.push({
|
|
21025
|
-
op: "add",
|
|
21026
|
-
path: patchPathOf(field.sourcePath).concat("path"),
|
|
21027
|
-
value: renamed[current]
|
|
21028
|
-
});
|
|
21029
|
-
byModule.set(field.moduleFilePath, patch);
|
|
21030
|
-
}
|
|
21031
|
-
return [...byModule].map(([moduleFilePath, patch]) => ({
|
|
21032
|
-
moduleFilePath,
|
|
21033
|
-
patch
|
|
21034
|
-
}));
|
|
21200
|
+
return collectionReferencePatches(service, setModuleFilePath, renamed);
|
|
21035
21201
|
}
|
|
21036
21202
|
|
|
21037
21203
|
/** The record at `sourcePath` and its entries, or why it could not be read. */
|
|
@@ -22615,13 +22781,13 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
22615
22781
|
return uploadRemoteFileCore(ctx, fileRefProp, fileSourceMetadata, resolveRemoteFileSchema);
|
|
22616
22782
|
}
|
|
22617
22783
|
|
|
22618
|
-
// Gallery (s.
|
|
22784
|
+
// Gallery (s.imagedir(dir, { ... }).remote() / s.filedir(dir, { ... }).remote()) upload.
|
|
22619
22785
|
// Unlike a single image/file field, a gallery entry is keyed by its local file
|
|
22620
22786
|
// path and the value is bare metadata (no FileSource), so we derive the file
|
|
22621
22787
|
// ref from the key and synthesize the image/file schema from the record's
|
|
22622
22788
|
// media options.
|
|
22623
22789
|
async function handleRemoteGalleryFileUpload(ctx) {
|
|
22624
|
-
var _ctx$validationError$;
|
|
22790
|
+
var _ctx$validationError$, _ctx$remoteFiles$ctx$;
|
|
22625
22791
|
if (!ctx.fix) {
|
|
22626
22792
|
return {
|
|
22627
22793
|
success: false,
|
|
@@ -22659,7 +22825,7 @@ async function handleRemoteGalleryFileUpload(ctx) {
|
|
|
22659
22825
|
// `accept`/`dir` come from the RECORD that holds the entry, resolved
|
|
22660
22826
|
// from the entry's PARENT path - not from the module root, which is only the
|
|
22661
22827
|
// record when the gallery is the whole module. A nested gallery
|
|
22662
|
-
// (s.object({ gallery: s.
|
|
22828
|
+
// (s.object({ gallery: s.imagedir(...) })) would otherwise synthesize a schema
|
|
22663
22829
|
// with no options and bake a validation hash into the remote ref that can
|
|
22664
22830
|
// never validate, so a mismatch fails fast instead of uploading.
|
|
22665
22831
|
const [, parentModulePath] = Internal.splitModuleFilePathAndModulePath(Internal.parentOfSourcePath(ctx.sourcePath));
|
|
@@ -22694,7 +22860,24 @@ async function handleRemoteGalleryFileUpload(ctx) {
|
|
|
22694
22860
|
} : {})
|
|
22695
22861
|
}
|
|
22696
22862
|
};
|
|
22697
|
-
|
|
22863
|
+
const uploaded = await uploadRemoteFileCore(ctx, fileRef, metadata, schema);
|
|
22864
|
+
const ref = (_ctx$remoteFiles$ctx$ = ctx.remoteFiles[ctx.sourcePath]) === null || _ctx$remoteFiles$ctx$ === void 0 ? void 0 : _ctx$remoteFiles$ctx$.ref;
|
|
22865
|
+
if (!uploaded.success || !uploaded.shouldApplyPatch || ref === undefined) {
|
|
22866
|
+
return uploaded;
|
|
22867
|
+
}
|
|
22868
|
+
// `createFixPatch` renames the entry's key to the ref. Every field picked
|
|
22869
|
+
// from the gallery that holds the old key — and every rich text image from
|
|
22870
|
+
// it — would then name an image the gallery no longer has, so they are
|
|
22871
|
+
// pointed at the ref in the same run, as `videos:upload-remote` does.
|
|
22872
|
+
const otherModulePatches = await collectionReferencePatches(ctx.service, ctx.moduleFilePath, {
|
|
22873
|
+
[fileRef]: ref
|
|
22874
|
+
});
|
|
22875
|
+
return {
|
|
22876
|
+
...uploaded,
|
|
22877
|
+
...(otherModulePatches.length > 0 ? {
|
|
22878
|
+
otherModulePatches
|
|
22879
|
+
} : {})
|
|
22880
|
+
};
|
|
22698
22881
|
}
|
|
22699
22882
|
async function handleRemoteFileDownload(ctx) {
|
|
22700
22883
|
if (ctx.fix) {
|
|
@@ -22713,13 +22896,47 @@ async function handleRemoteFileDownload(ctx) {
|
|
|
22713
22896
|
};
|
|
22714
22897
|
}
|
|
22715
22898
|
}
|
|
22899
|
+
|
|
22900
|
+
/**
|
|
22901
|
+
* `image:check-remote` / `file:check-remote`: core's "Remote image was not
|
|
22902
|
+
* checked." — emitted for EVERY remote value of an `s.image().remote()` /
|
|
22903
|
+
* `s.file().remote()`, wrong or not, because core cannot read the bytes or the
|
|
22904
|
+
* ref's validation hash. It is a request to look, not a finding, so there is
|
|
22905
|
+
* nothing to report here: `createFixPatch` does the looking (`checkRemoteRef`)
|
|
22906
|
+
* and returns an error only for a ref that is actually wrong, with a fix where
|
|
22907
|
+
* the ref only needs rewriting.
|
|
22908
|
+
*
|
|
22909
|
+
* So these stay a hand-off. Reporting core's message here instead would put an
|
|
22910
|
+
* error on every remote image in a project, which is what the language server
|
|
22911
|
+
* learned to stop doing (`mediaChecks.ts`).
|
|
22912
|
+
*/
|
|
22716
22913
|
async function handleRemoteFileCheck() {
|
|
22717
|
-
// Skip - no action needed
|
|
22718
22914
|
return {
|
|
22719
22915
|
success: true,
|
|
22720
22916
|
shouldApplyPatch: true
|
|
22721
22917
|
};
|
|
22722
22918
|
}
|
|
22919
|
+
|
|
22920
|
+
/**
|
|
22921
|
+
* `images:check-remote` / `files:check-remote`: a gallery key that is wrong as
|
|
22922
|
+
* a key — a remote URL in a gallery that is not `.remote()`, a ref that does
|
|
22923
|
+
* not parse, one outside the gallery's directory (`validateMediaKey` in core).
|
|
22924
|
+
*
|
|
22925
|
+
* Unlike the singular codes, core emits these only when something IS wrong,
|
|
22926
|
+
* and its message says what. There is nothing to look up and nothing to move,
|
|
22927
|
+
* so it is reported as it is, for a person: only they know whether the key or
|
|
22928
|
+
* the gallery's options are the mistake. It used to share the singular codes'
|
|
22929
|
+
* handler, which hands off to `createFixPatch` — and that has no branch for a
|
|
22930
|
+
* gallery key, so the error vanished and the module was reported valid.
|
|
22931
|
+
*
|
|
22932
|
+
* The same answer as `videos:check-remote`.
|
|
22933
|
+
*/
|
|
22934
|
+
async function handleGalleryCheckRemote(ctx) {
|
|
22935
|
+
return {
|
|
22936
|
+
success: false,
|
|
22937
|
+
errorMessage: ctx.validationError.message
|
|
22938
|
+
};
|
|
22939
|
+
}
|
|
22723
22940
|
async function handleUniqueFolderCheck(ctx) {
|
|
22724
22941
|
const value = ctx.validationError.value;
|
|
22725
22942
|
if (!value || typeof value.dir !== "string") {
|
|
@@ -22914,9 +23131,9 @@ const currentFixHandlers = {
|
|
|
22914
23131
|
"videos:check-unique-folder": handleUniqueFolderCheck,
|
|
22915
23132
|
"videos:check-all-files": handleVideosetCheckAllFiles,
|
|
22916
23133
|
"image:check-remote": handleRemoteFileCheck,
|
|
22917
|
-
"images:check-remote":
|
|
23134
|
+
"images:check-remote": handleGalleryCheckRemote,
|
|
22918
23135
|
"file:check-remote": handleRemoteFileCheck,
|
|
22919
|
-
"files:check-remote":
|
|
23136
|
+
"files:check-remote": handleGalleryCheckRemote,
|
|
22920
23137
|
"images:check-unique-folder": handleUniqueFolderCheck,
|
|
22921
23138
|
"files:check-unique-folder": handleUniqueFolderCheck,
|
|
22922
23139
|
"images:check-all-files": handleCheckAllFiles,
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"./package.json": "./package.json"
|
|
17
17
|
},
|
|
18
18
|
"types": "dist/valbuild-server.cjs.d.ts",
|
|
19
|
-
"version": "0.
|
|
19
|
+
"version": "0.144.0",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@prettier/sync": "^0.6.1",
|
|
22
22
|
"@types/jest": "^30.0.0",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"typescript": "^6.0.3",
|
|
31
31
|
"zod": "^4.4.3",
|
|
32
32
|
"zod-validation-error": "^5.0.0",
|
|
33
|
-
"@valbuild/
|
|
34
|
-
"@valbuild/
|
|
35
|
-
"@valbuild/
|
|
33
|
+
"@valbuild/core": "0.144.0",
|
|
34
|
+
"@valbuild/shared": "0.144.0",
|
|
35
|
+
"@valbuild/ui": "0.144.0"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": "^20.19.0 || >=22"
|