@valbuild/server 0.143.0 → 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 +24 -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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @valbuild/server
|
|
2
2
|
|
|
3
|
+
## 0.144.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#788](https://github.com/valbuild/val/pull/788) [`a84271c`](https://github.com/valbuild/val/commit/a84271c534822071c1e428cf9990602459682d25) Thanks [@freekh](https://github.com/freekh)! - Fixes to `npx val validate` for `s.imagedir()` and `s.filedir()`, and the `s.image(galleryVal)` / `s.file(filesVal)` fields that use them:
|
|
8
|
+
|
|
9
|
+
- **`--fix` now updates every field that uses an uploaded image or file.** When `--fix` moves an entry of an `s.imagedir(dir).remote()` or `s.filedir(dir, options).remote()` to Val Remote, the entry's key changes from the local path to the remote URL. Fields that held the old path were left pointing at it, and reported "The gallery does not have an image at …" with nothing to fix it. Now `s.image(galleryVal)` and `s.file(filesVal)` fields, and images in rich text (`s.richtext({ img: s.image(galleryVal) })`), are updated in the same run. The VS Code extension's "upload to Val Remote" updates them in the same edit, including fields inside `.jsonValues()` entries, which live in their own `*.val.json` files.
|
|
10
|
+
- **A field that uses an image or file from a `.remote()` gallery is no longer reported as "Expected local image, but found remote".** The gallery decides whether its files are on Val Remote; the field only has to name a file the gallery has. Before, `--fix` would download the file and point the field at a path the gallery did not have.
|
|
11
|
+
- **Images uploaded through a field into a `.remote()` gallery.** When you upload an image through an `s.image(galleryVal)` field in Val Studio, the field stores the remote URL and the gallery stores the image under its local path. Validation now accepts this, and `useVal` / `fetchVal` now fill in the image's `width`, `height` and `mimeType` from the gallery for it, as they do for every other gallery image.
|
|
12
|
+
- **Errors in a gallery's keys are reported.** A remote URL in a gallery that is not `.remote()`, a remote URL that is not valid, or one outside the gallery's `dir` was silently ignored by `npx val validate`. It is now reported as an error. `--fix` does not change it: you decide whether the key or the gallery's options are wrong.
|
|
13
|
+
- **A file is no longer reported as valid when it still has an error.** When `--fix` fixed one error in a file and another error was left, the file could be printed as "✔ valid".
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`a84271c`](https://github.com/valbuild/val/commit/a84271c534822071c1e428cf9990602459682d25), [`860ab2b`](https://github.com/valbuild/val/commit/860ab2b87333daf95a48215b0e4a1b44f441c878)]:
|
|
16
|
+
- @valbuild/core@0.144.0
|
|
17
|
+
- @valbuild/shared@0.144.0
|
|
18
|
+
- @valbuild/ui@0.144.0
|
|
19
|
+
|
|
20
|
+
## 0.143.1
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [[`49969c1`](https://github.com/valbuild/val/commit/49969c1e9f7c39f9cea1a97c91d59dbba6fe3f95), [`ee8e2a2`](https://github.com/valbuild/val/commit/ee8e2a23272a512b43a03fb5f61fc0ddecd61dc4), [`d6cc677`](https://github.com/valbuild/val/commit/d6cc6777cf9c2bbef3ba25e43a6227631523758e), [`54aacab`](https://github.com/valbuild/val/commit/54aacab71893a95145183e4e9fefbfac945be24d), [`2577f4e`](https://github.com/valbuild/val/commit/2577f4e8ff19f5ea155040d4d9588b2dbc756ad9)]:
|
|
25
|
+
- @valbuild/ui@0.143.1
|
|
26
|
+
|
|
3
27
|
## 0.143.0
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -194,7 +194,35 @@ export declare function handleVideoMetadata(ctx: FixHandlerContext): Promise<Fix
|
|
|
194
194
|
export declare function handleRemoteFileUpload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
195
195
|
export declare function handleRemoteGalleryFileUpload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
196
196
|
export declare function handleRemoteFileDownload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
197
|
+
/**
|
|
198
|
+
* `image:check-remote` / `file:check-remote`: core's "Remote image was not
|
|
199
|
+
* checked." — emitted for EVERY remote value of an `s.image().remote()` /
|
|
200
|
+
* `s.file().remote()`, wrong or not, because core cannot read the bytes or the
|
|
201
|
+
* ref's validation hash. It is a request to look, not a finding, so there is
|
|
202
|
+
* nothing to report here: `createFixPatch` does the looking (`checkRemoteRef`)
|
|
203
|
+
* and returns an error only for a ref that is actually wrong, with a fix where
|
|
204
|
+
* the ref only needs rewriting.
|
|
205
|
+
*
|
|
206
|
+
* So these stay a hand-off. Reporting core's message here instead would put an
|
|
207
|
+
* error on every remote image in a project, which is what the language server
|
|
208
|
+
* learned to stop doing (`mediaChecks.ts`).
|
|
209
|
+
*/
|
|
197
210
|
export declare function handleRemoteFileCheck(): Promise<FixHandlerResult>;
|
|
211
|
+
/**
|
|
212
|
+
* `images:check-remote` / `files:check-remote`: a gallery key that is wrong as
|
|
213
|
+
* a key — a remote URL in a gallery that is not `.remote()`, a ref that does
|
|
214
|
+
* not parse, one outside the gallery's directory (`validateMediaKey` in core).
|
|
215
|
+
*
|
|
216
|
+
* Unlike the singular codes, core emits these only when something IS wrong,
|
|
217
|
+
* and its message says what. There is nothing to look up and nothing to move,
|
|
218
|
+
* so it is reported as it is, for a person: only they know whether the key or
|
|
219
|
+
* the gallery's options are the mistake. It used to share the singular codes'
|
|
220
|
+
* handler, which hands off to `createFixPatch` — and that has no branch for a
|
|
221
|
+
* gallery key, so the error vanished and the module was reported valid.
|
|
222
|
+
*
|
|
223
|
+
* The same answer as `videos:check-remote`.
|
|
224
|
+
*/
|
|
225
|
+
export declare function handleGalleryCheckRemote(ctx: Pick<FixHandlerContext, "validationError">): Promise<FixHandlerResult>;
|
|
198
226
|
export declare function handleUniqueFolderCheck(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
199
227
|
export declare function handleCheckAllFiles(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
200
228
|
export declare function handleJsonValuesExtractEntry(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
@@ -52,10 +52,11 @@ export declare function filesNamedByVideoFields(service: VideoFieldService, opti
|
|
|
52
52
|
/**
|
|
53
53
|
* The patches that point every `s.video(set)` field at a set entry's new key.
|
|
54
54
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
55
|
+
* The same walk an image or file collection's rename uses
|
|
56
|
+
* (`collectionReferencePatches`): one `add` on each field's `path`, so the
|
|
57
|
+
* description, poster, times and captions beside it are never rewritten, and
|
|
58
|
+
* a field of another set, or of no set, is left alone even when its path is
|
|
59
|
+
* the same string — it names its own file.
|
|
59
60
|
*/
|
|
60
61
|
export declare function videosetReferencePatches(service: VideoFieldService, setModuleFilePath: ModuleFilePath, renamed: Record<string, string>): Promise<ModulePatch[]>;
|
|
61
62
|
/**
|
|
@@ -20273,7 +20273,7 @@ function readFileOrUndefined$1(absolutePath) {
|
|
|
20273
20273
|
* be uploaded first). On the way DOWN the same playlists are rewritten back to
|
|
20274
20274
|
* relative names, which is what lets a published stream be plain static files.
|
|
20275
20275
|
*/
|
|
20276
|
-
function isRecord$
|
|
20276
|
+
function isRecord$3(value) {
|
|
20277
20277
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20278
20278
|
}
|
|
20279
20279
|
function isPlaylist$1(ref) {
|
|
@@ -20282,14 +20282,14 @@ function isPlaylist$1(ref) {
|
|
|
20282
20282
|
|
|
20283
20283
|
/** The paths a video value holds, each with where in the value it sits. */
|
|
20284
20284
|
function videoPathsOf(video) {
|
|
20285
|
-
if (!isRecord$
|
|
20285
|
+
if (!isRecord$3(video) || typeof video.path !== "string") {
|
|
20286
20286
|
return [];
|
|
20287
20287
|
}
|
|
20288
20288
|
const found = [{
|
|
20289
20289
|
at: ["path"],
|
|
20290
20290
|
path: video.path
|
|
20291
20291
|
}];
|
|
20292
|
-
if (isRecord$
|
|
20292
|
+
if (isRecord$3(video.poster) && typeof video.poster.path === "string") {
|
|
20293
20293
|
found.push({
|
|
20294
20294
|
at: ["poster", "path"],
|
|
20295
20295
|
path: video.poster.path
|
|
@@ -20297,7 +20297,7 @@ function videoPathsOf(video) {
|
|
|
20297
20297
|
}
|
|
20298
20298
|
if (Array.isArray(video.captions)) {
|
|
20299
20299
|
video.captions.forEach((track, index) => {
|
|
20300
|
-
if (isRecord$
|
|
20300
|
+
if (isRecord$3(track) && typeof track.path === "string") {
|
|
20301
20301
|
found.push({
|
|
20302
20302
|
at: ["captions", String(index), "path"],
|
|
20303
20303
|
path: track.path
|
|
@@ -20368,7 +20368,7 @@ function metadataOf(localRef, role, video) {
|
|
|
20368
20368
|
height: video.height
|
|
20369
20369
|
};
|
|
20370
20370
|
}
|
|
20371
|
-
if (role === "poster" && isRecord$
|
|
20371
|
+
if (role === "poster" && isRecord$3(video.poster)) {
|
|
20372
20372
|
return {
|
|
20373
20373
|
mimeType: video.poster.mimeType ?? mimeType,
|
|
20374
20374
|
width: video.poster.width,
|
|
@@ -20384,7 +20384,7 @@ function metadataOf(localRef, role, video) {
|
|
|
20384
20384
|
* Places a video's local files on Val Remote, each once, and remembers where.
|
|
20385
20385
|
*
|
|
20386
20386
|
* The one implementation of "upload a video" for every fix that does it: a
|
|
20387
|
-
* video field (`video:upload-remote`), and an entry of an `s.
|
|
20387
|
+
* video field (`video:upload-remote`), and an entry of an `s.videodir()`
|
|
20388
20388
|
* (`videos:upload-remote`). What differs between the two is which files go up
|
|
20389
20389
|
* and what their refs are hashed against, so those are the arguments.
|
|
20390
20390
|
*
|
|
@@ -20477,7 +20477,7 @@ function resolveVideo(ctx) {
|
|
|
20477
20477
|
}
|
|
20478
20478
|
const resolved = core.Internal.resolvePath(modulePath, ctx.valModule.source, ctx.valModule.schema);
|
|
20479
20479
|
const video = resolved.source;
|
|
20480
|
-
if (((_resolved$schema = resolved.schema) === null || _resolved$schema === void 0 ? void 0 : _resolved$schema.type) !== "video" || !isRecord$
|
|
20480
|
+
if (((_resolved$schema = resolved.schema) === null || _resolved$schema === void 0 ? void 0 : _resolved$schema.type) !== "video" || !isRecord$3(video) || typeof video.path !== "string") {
|
|
20481
20481
|
return {
|
|
20482
20482
|
success: false,
|
|
20483
20483
|
result: {
|
|
@@ -20497,7 +20497,7 @@ function resolveVideo(ctx) {
|
|
|
20497
20497
|
* The paths of a video FIELD that its fix moves.
|
|
20498
20498
|
*
|
|
20499
20499
|
* All of them for a video of its own. For a field picked from an
|
|
20500
|
-
* `s.
|
|
20500
|
+
* `s.videodir()` (`referencedModule`), only the poster and the captions: the
|
|
20501
20501
|
* video file is the set's — its key there — and moving it from here would
|
|
20502
20502
|
* leave the field naming a file the set does not have. The set's own fix
|
|
20503
20503
|
* (`videos:upload-remote`) moves it, and rewrites the fields that name it.
|
|
@@ -20670,6 +20670,192 @@ async function handleVideoDownloadRemote(ctx) {
|
|
|
20670
20670
|
};
|
|
20671
20671
|
}
|
|
20672
20672
|
|
|
20673
|
+
/**
|
|
20674
|
+
* The fields that name an entry of a media collection by its key, and the
|
|
20675
|
+
* patches that point them at a new key.
|
|
20676
|
+
*
|
|
20677
|
+
* A collection — `s.imagedir()`, `s.filedir()`, `s.videodir()` — is a record
|
|
20678
|
+
* keyed by each entry's file path, and a field picked from it
|
|
20679
|
+
* (`s.image(imagesVal)`, `s.file(filesVal)`, `s.video(videosVal)`) stores that
|
|
20680
|
+
* key as its `path`. So when `--fix` renames a key — moving an entry of a
|
|
20681
|
+
* `.remote()` collection to Val Remote renames it from the local path to the
|
|
20682
|
+
* ref — every field holding the old key would name an entry the collection no
|
|
20683
|
+
* longer has, and nothing could repair it afterwards.
|
|
20684
|
+
*
|
|
20685
|
+
* Two kinds of value name a key:
|
|
20686
|
+
*
|
|
20687
|
+
* - **A field whose schema is backed by the collection** (`referencedModule`).
|
|
20688
|
+
* - **An inline image in rich text** whose `img` schema is backed by it
|
|
20689
|
+
* (`s.richtext({ img: s.image(imagesVal) })`). The field's own schema is
|
|
20690
|
+
* `richtext`, so a walk looking only for image leaves goes straight past
|
|
20691
|
+
* them — the Studio's reference scan learned that once already
|
|
20692
|
+
* (`getReferencedFiles`), and uses the same `forEachRichTextImage`.
|
|
20693
|
+
*
|
|
20694
|
+
* **A field is renamed when the key it names is the old key**, and "names" is
|
|
20695
|
+
* `galleryKeyOf` in core: the field's `path` when that is a key, and otherwise
|
|
20696
|
+
* the local path inside it when it is a ref. That is how a field is read
|
|
20697
|
+
* (`fillFromGallery`) and how it is validated, so it is exactly the set of
|
|
20698
|
+
* fields the rename would break. The second shape is real: an image uploaded
|
|
20699
|
+
* THROUGH an `s.image(remoteGallery)` field in the Studio stores the ref in
|
|
20700
|
+
* the field and keys the entry by the local path inside it, so uploading that
|
|
20701
|
+
* entry here has to move the field to the entry's new key as well. A ref that
|
|
20702
|
+
* is itself a key names its own entry, and is left alone.
|
|
20703
|
+
*
|
|
20704
|
+
* Nothing here imports `fixHandlers.ts` at runtime: that module calls this one.
|
|
20705
|
+
*/
|
|
20706
|
+
|
|
20707
|
+
/** What of a `Service` the project-wide walk needs. */
|
|
20708
|
+
|
|
20709
|
+
/** A value that names an entry of a collection by its key. */
|
|
20710
|
+
|
|
20711
|
+
function isRecord$2(value) {
|
|
20712
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20713
|
+
}
|
|
20714
|
+
|
|
20715
|
+
/** Whether a serialized schema is backed by `collection` anywhere in it. */
|
|
20716
|
+
function isBackedBy(schema, collection) {
|
|
20717
|
+
if (Array.isArray(schema)) {
|
|
20718
|
+
return schema.some(item => isBackedBy(item, collection));
|
|
20719
|
+
}
|
|
20720
|
+
if (!isRecord$2(schema)) {
|
|
20721
|
+
return false;
|
|
20722
|
+
}
|
|
20723
|
+
if (schema.referencedModule === collection) {
|
|
20724
|
+
return true;
|
|
20725
|
+
}
|
|
20726
|
+
return Object.values(schema).some(value => isBackedBy(value, collection));
|
|
20727
|
+
}
|
|
20728
|
+
|
|
20729
|
+
/**
|
|
20730
|
+
* The references already found, per service and collection.
|
|
20731
|
+
*
|
|
20732
|
+
* `val validate --fix` renames a key once per local entry, so a gallery of N
|
|
20733
|
+
* local entries would otherwise walk the project N times — validating every
|
|
20734
|
+
* module that uses the gallery each time. Caching per `Service` is exact, not
|
|
20735
|
+
* an approximation: a `Service` answers `get` from the snapshot it was created
|
|
20736
|
+
* with (`patch` writes to disk and changes nothing it returns), so the walk
|
|
20737
|
+
* would find the same references every time. A new `Service` — the language
|
|
20738
|
+
* server makes one after every edit — starts with nothing cached.
|
|
20739
|
+
*/
|
|
20740
|
+
const referencesByService = new WeakMap();
|
|
20741
|
+
|
|
20742
|
+
/**
|
|
20743
|
+
* Every value in the project that names an entry of `collection`, as the
|
|
20744
|
+
* service's snapshot has it. Found once per service; see
|
|
20745
|
+
* {@link referencesByService}.
|
|
20746
|
+
*/
|
|
20747
|
+
function collectionReferencesOf(service, collection) {
|
|
20748
|
+
let byCollection = referencesByService.get(service);
|
|
20749
|
+
if (!byCollection) {
|
|
20750
|
+
byCollection = new Map();
|
|
20751
|
+
referencesByService.set(service, byCollection);
|
|
20752
|
+
}
|
|
20753
|
+
let references = byCollection.get(collection);
|
|
20754
|
+
if (!references) {
|
|
20755
|
+
references = findCollectionReferences(service, collection);
|
|
20756
|
+
// A walk that failed is not an answer; the next caller tries again.
|
|
20757
|
+
references.catch(() => byCollection.delete(collection));
|
|
20758
|
+
byCollection.set(collection, references);
|
|
20759
|
+
}
|
|
20760
|
+
return references;
|
|
20761
|
+
}
|
|
20762
|
+
|
|
20763
|
+
/**
|
|
20764
|
+
* The walk itself.
|
|
20765
|
+
*
|
|
20766
|
+
* Validated reads for the modules backed by the collection, because only
|
|
20767
|
+
* those come back with their `.jsonValues()` entries loaded — an unvalidated
|
|
20768
|
+
* read hands back each entry as a marker, and a field inside one would be
|
|
20769
|
+
* invisible. Every other module is read once, unvalidated, to find out it is
|
|
20770
|
+
* not one of them.
|
|
20771
|
+
*/
|
|
20772
|
+
async function findCollectionReferences(service, collection) {
|
|
20773
|
+
const found = [];
|
|
20774
|
+
for (const moduleFilePath of service.getModuleFilePaths()) {
|
|
20775
|
+
const shallow = await service.get(moduleFilePath, "", {
|
|
20776
|
+
validate: false
|
|
20777
|
+
});
|
|
20778
|
+
if (!isBackedBy(shallow.schema, collection)) {
|
|
20779
|
+
continue;
|
|
20780
|
+
}
|
|
20781
|
+
const loaded = await service.get(moduleFilePath, "", {
|
|
20782
|
+
validate: true
|
|
20783
|
+
});
|
|
20784
|
+
if (loaded.source === undefined || !loaded.schema) {
|
|
20785
|
+
continue;
|
|
20786
|
+
}
|
|
20787
|
+
const add = (sourcePath, value) => {
|
|
20788
|
+
if (isRecord$2(value) && typeof value.path === "string") {
|
|
20789
|
+
found.push({
|
|
20790
|
+
moduleFilePath,
|
|
20791
|
+
sourcePath,
|
|
20792
|
+
path: value.path
|
|
20793
|
+
});
|
|
20794
|
+
}
|
|
20795
|
+
};
|
|
20796
|
+
internal.traverseSchemaSource(loaded.source, loaded.schema, moduleFilePath, ({
|
|
20797
|
+
source,
|
|
20798
|
+
schema,
|
|
20799
|
+
path: sourcePath
|
|
20800
|
+
}) => {
|
|
20801
|
+
if (schema.type === "image" || schema.type === "file" || schema.type === "video") {
|
|
20802
|
+
if (schema.referencedModule === collection) {
|
|
20803
|
+
add(sourcePath, source);
|
|
20804
|
+
}
|
|
20805
|
+
} else if (schema.type === "richtext") {
|
|
20806
|
+
var _richTextImageSchema;
|
|
20807
|
+
if (((_richTextImageSchema = internal.richTextImageSchema(schema)) === null || _richTextImageSchema === void 0 ? void 0 : _richTextImageSchema.referencedModule) === collection) {
|
|
20808
|
+
internal.forEachRichTextImage(sourcePath, source, add);
|
|
20809
|
+
}
|
|
20810
|
+
}
|
|
20811
|
+
});
|
|
20812
|
+
}
|
|
20813
|
+
return found;
|
|
20814
|
+
}
|
|
20815
|
+
|
|
20816
|
+
/**
|
|
20817
|
+
* The patch path of `sourcePath`. Not `sourceToPatchPath`: a collection's keys
|
|
20818
|
+
* are file paths, and their dots do not survive its `split(".")`.
|
|
20819
|
+
*/
|
|
20820
|
+
function patchPathOf$1(sourcePath) {
|
|
20821
|
+
const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
20822
|
+
return core.Internal.splitModulePath(modulePath);
|
|
20823
|
+
}
|
|
20824
|
+
|
|
20825
|
+
/**
|
|
20826
|
+
* The patches that point every value naming a key in `renamed` at its new key.
|
|
20827
|
+
*
|
|
20828
|
+
* `renamed` is keyed by the collection's keys BEFORE the rename, and the
|
|
20829
|
+
* collection is read as it is now — so call this before its own patch lands.
|
|
20830
|
+
*
|
|
20831
|
+
* One `add` on each value's `path`, so the alt text, hotspot, poster and
|
|
20832
|
+
* captions beside it are never rewritten.
|
|
20833
|
+
*/
|
|
20834
|
+
async function collectionReferencePatches(service, collection, renamed) {
|
|
20835
|
+
const collectionSource = (await service.get(collection, "", {
|
|
20836
|
+
validate: false
|
|
20837
|
+
})).source;
|
|
20838
|
+
const keys = new Set(isRecord$2(collectionSource) ? Object.keys(collectionSource) : []);
|
|
20839
|
+
const byModule = new Map();
|
|
20840
|
+
for (const reference of await collectionReferencesOf(service, collection)) {
|
|
20841
|
+
const key = core.Internal.media.galleryKeyOf(reference.path, candidate => keys.has(candidate));
|
|
20842
|
+
if (key === null || !Object.prototype.hasOwnProperty.call(renamed, key)) {
|
|
20843
|
+
continue;
|
|
20844
|
+
}
|
|
20845
|
+
const patch = byModule.get(reference.moduleFilePath) ?? [];
|
|
20846
|
+
patch.push({
|
|
20847
|
+
op: "add",
|
|
20848
|
+
path: patchPathOf$1(reference.sourcePath).concat("path"),
|
|
20849
|
+
value: renamed[key]
|
|
20850
|
+
});
|
|
20851
|
+
byModule.set(reference.moduleFilePath, patch);
|
|
20852
|
+
}
|
|
20853
|
+
return [...byModule].map(([moduleFilePath, patch]) => ({
|
|
20854
|
+
moduleFilePath,
|
|
20855
|
+
patch
|
|
20856
|
+
}));
|
|
20857
|
+
}
|
|
20858
|
+
|
|
20673
20859
|
/**
|
|
20674
20860
|
* What is out of step between a gallery's entries and its directory.
|
|
20675
20861
|
*
|
|
@@ -20778,7 +20964,7 @@ function filesInDirectory({
|
|
|
20778
20964
|
}
|
|
20779
20965
|
|
|
20780
20966
|
/**
|
|
20781
|
-
* The fixes of an `s.
|
|
20967
|
+
* The fixes of an `s.videodir()` — the video twin of an image gallery.
|
|
20782
20968
|
*
|
|
20783
20969
|
* A set is a record keyed by each video's file path (an HLS stream by its
|
|
20784
20970
|
* master playlist), so most of this is the gallery fixes again with the key as
|
|
@@ -21041,34 +21227,14 @@ async function filesNamedByVideoFields(service, options) {
|
|
|
21041
21227
|
/**
|
|
21042
21228
|
* The patches that point every `s.video(set)` field at a set entry's new key.
|
|
21043
21229
|
*
|
|
21044
|
-
*
|
|
21045
|
-
*
|
|
21046
|
-
*
|
|
21047
|
-
*
|
|
21230
|
+
* The same walk an image or file collection's rename uses
|
|
21231
|
+
* (`collectionReferencePatches`): one `add` on each field's `path`, so the
|
|
21232
|
+
* description, poster, times and captions beside it are never rewritten, and
|
|
21233
|
+
* a field of another set, or of no set, is left alone even when its path is
|
|
21234
|
+
* the same string — it names its own file.
|
|
21048
21235
|
*/
|
|
21049
21236
|
async function videosetReferencePatches(service, setModuleFilePath, renamed) {
|
|
21050
|
-
|
|
21051
|
-
for (const field of await videoFieldsOf(service)) {
|
|
21052
|
-
if (field.schema.referencedModule !== setModuleFilePath) {
|
|
21053
|
-
continue;
|
|
21054
|
-
}
|
|
21055
|
-
const value = field.source;
|
|
21056
|
-
const current = isRecord$1(value) ? value.path : undefined;
|
|
21057
|
-
if (typeof current !== "string" || !(current in renamed)) {
|
|
21058
|
-
continue;
|
|
21059
|
-
}
|
|
21060
|
-
const patch = byModule.get(field.moduleFilePath) ?? [];
|
|
21061
|
-
patch.push({
|
|
21062
|
-
op: "add",
|
|
21063
|
-
path: patchPathOf(field.sourcePath).concat("path"),
|
|
21064
|
-
value: renamed[current]
|
|
21065
|
-
});
|
|
21066
|
-
byModule.set(field.moduleFilePath, patch);
|
|
21067
|
-
}
|
|
21068
|
-
return [...byModule].map(([moduleFilePath, patch]) => ({
|
|
21069
|
-
moduleFilePath,
|
|
21070
|
-
patch
|
|
21071
|
-
}));
|
|
21237
|
+
return collectionReferencePatches(service, setModuleFilePath, renamed);
|
|
21072
21238
|
}
|
|
21073
21239
|
|
|
21074
21240
|
/** The record at `sourcePath` and its entries, or why it could not be read. */
|
|
@@ -22652,13 +22818,13 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
22652
22818
|
return uploadRemoteFileCore(ctx, fileRefProp, fileSourceMetadata, resolveRemoteFileSchema);
|
|
22653
22819
|
}
|
|
22654
22820
|
|
|
22655
|
-
// Gallery (s.
|
|
22821
|
+
// Gallery (s.imagedir(dir, { ... }).remote() / s.filedir(dir, { ... }).remote()) upload.
|
|
22656
22822
|
// Unlike a single image/file field, a gallery entry is keyed by its local file
|
|
22657
22823
|
// path and the value is bare metadata (no FileSource), so we derive the file
|
|
22658
22824
|
// ref from the key and synthesize the image/file schema from the record's
|
|
22659
22825
|
// media options.
|
|
22660
22826
|
async function handleRemoteGalleryFileUpload(ctx) {
|
|
22661
|
-
var _ctx$validationError$;
|
|
22827
|
+
var _ctx$validationError$, _ctx$remoteFiles$ctx$;
|
|
22662
22828
|
if (!ctx.fix) {
|
|
22663
22829
|
return {
|
|
22664
22830
|
success: false,
|
|
@@ -22696,7 +22862,7 @@ async function handleRemoteGalleryFileUpload(ctx) {
|
|
|
22696
22862
|
// `accept`/`dir` come from the RECORD that holds the entry, resolved
|
|
22697
22863
|
// from the entry's PARENT path - not from the module root, which is only the
|
|
22698
22864
|
// record when the gallery is the whole module. A nested gallery
|
|
22699
|
-
// (s.object({ gallery: s.
|
|
22865
|
+
// (s.object({ gallery: s.imagedir(...) })) would otherwise synthesize a schema
|
|
22700
22866
|
// with no options and bake a validation hash into the remote ref that can
|
|
22701
22867
|
// never validate, so a mismatch fails fast instead of uploading.
|
|
22702
22868
|
const [, parentModulePath] = core.Internal.splitModuleFilePathAndModulePath(core.Internal.parentOfSourcePath(ctx.sourcePath));
|
|
@@ -22731,7 +22897,24 @@ async function handleRemoteGalleryFileUpload(ctx) {
|
|
|
22731
22897
|
} : {})
|
|
22732
22898
|
}
|
|
22733
22899
|
};
|
|
22734
|
-
|
|
22900
|
+
const uploaded = await uploadRemoteFileCore(ctx, fileRef, metadata, schema);
|
|
22901
|
+
const ref = (_ctx$remoteFiles$ctx$ = ctx.remoteFiles[ctx.sourcePath]) === null || _ctx$remoteFiles$ctx$ === void 0 ? void 0 : _ctx$remoteFiles$ctx$.ref;
|
|
22902
|
+
if (!uploaded.success || !uploaded.shouldApplyPatch || ref === undefined) {
|
|
22903
|
+
return uploaded;
|
|
22904
|
+
}
|
|
22905
|
+
// `createFixPatch` renames the entry's key to the ref. Every field picked
|
|
22906
|
+
// from the gallery that holds the old key — and every rich text image from
|
|
22907
|
+
// it — would then name an image the gallery no longer has, so they are
|
|
22908
|
+
// pointed at the ref in the same run, as `videos:upload-remote` does.
|
|
22909
|
+
const otherModulePatches = await collectionReferencePatches(ctx.service, ctx.moduleFilePath, {
|
|
22910
|
+
[fileRef]: ref
|
|
22911
|
+
});
|
|
22912
|
+
return {
|
|
22913
|
+
...uploaded,
|
|
22914
|
+
...(otherModulePatches.length > 0 ? {
|
|
22915
|
+
otherModulePatches
|
|
22916
|
+
} : {})
|
|
22917
|
+
};
|
|
22735
22918
|
}
|
|
22736
22919
|
async function handleRemoteFileDownload(ctx) {
|
|
22737
22920
|
if (ctx.fix) {
|
|
@@ -22750,13 +22933,47 @@ async function handleRemoteFileDownload(ctx) {
|
|
|
22750
22933
|
};
|
|
22751
22934
|
}
|
|
22752
22935
|
}
|
|
22936
|
+
|
|
22937
|
+
/**
|
|
22938
|
+
* `image:check-remote` / `file:check-remote`: core's "Remote image was not
|
|
22939
|
+
* checked." — emitted for EVERY remote value of an `s.image().remote()` /
|
|
22940
|
+
* `s.file().remote()`, wrong or not, because core cannot read the bytes or the
|
|
22941
|
+
* ref's validation hash. It is a request to look, not a finding, so there is
|
|
22942
|
+
* nothing to report here: `createFixPatch` does the looking (`checkRemoteRef`)
|
|
22943
|
+
* and returns an error only for a ref that is actually wrong, with a fix where
|
|
22944
|
+
* the ref only needs rewriting.
|
|
22945
|
+
*
|
|
22946
|
+
* So these stay a hand-off. Reporting core's message here instead would put an
|
|
22947
|
+
* error on every remote image in a project, which is what the language server
|
|
22948
|
+
* learned to stop doing (`mediaChecks.ts`).
|
|
22949
|
+
*/
|
|
22753
22950
|
async function handleRemoteFileCheck() {
|
|
22754
|
-
// Skip - no action needed
|
|
22755
22951
|
return {
|
|
22756
22952
|
success: true,
|
|
22757
22953
|
shouldApplyPatch: true
|
|
22758
22954
|
};
|
|
22759
22955
|
}
|
|
22956
|
+
|
|
22957
|
+
/**
|
|
22958
|
+
* `images:check-remote` / `files:check-remote`: a gallery key that is wrong as
|
|
22959
|
+
* a key — a remote URL in a gallery that is not `.remote()`, a ref that does
|
|
22960
|
+
* not parse, one outside the gallery's directory (`validateMediaKey` in core).
|
|
22961
|
+
*
|
|
22962
|
+
* Unlike the singular codes, core emits these only when something IS wrong,
|
|
22963
|
+
* and its message says what. There is nothing to look up and nothing to move,
|
|
22964
|
+
* so it is reported as it is, for a person: only they know whether the key or
|
|
22965
|
+
* the gallery's options are the mistake. It used to share the singular codes'
|
|
22966
|
+
* handler, which hands off to `createFixPatch` — and that has no branch for a
|
|
22967
|
+
* gallery key, so the error vanished and the module was reported valid.
|
|
22968
|
+
*
|
|
22969
|
+
* The same answer as `videos:check-remote`.
|
|
22970
|
+
*/
|
|
22971
|
+
async function handleGalleryCheckRemote(ctx) {
|
|
22972
|
+
return {
|
|
22973
|
+
success: false,
|
|
22974
|
+
errorMessage: ctx.validationError.message
|
|
22975
|
+
};
|
|
22976
|
+
}
|
|
22760
22977
|
async function handleUniqueFolderCheck(ctx) {
|
|
22761
22978
|
const value = ctx.validationError.value;
|
|
22762
22979
|
if (!value || typeof value.dir !== "string") {
|
|
@@ -22951,9 +23168,9 @@ const currentFixHandlers = {
|
|
|
22951
23168
|
"videos:check-unique-folder": handleUniqueFolderCheck,
|
|
22952
23169
|
"videos:check-all-files": handleVideosetCheckAllFiles,
|
|
22953
23170
|
"image:check-remote": handleRemoteFileCheck,
|
|
22954
|
-
"images:check-remote":
|
|
23171
|
+
"images:check-remote": handleGalleryCheckRemote,
|
|
22955
23172
|
"file:check-remote": handleRemoteFileCheck,
|
|
22956
|
-
"files:check-remote":
|
|
23173
|
+
"files:check-remote": handleGalleryCheckRemote,
|
|
22957
23174
|
"images:check-unique-folder": handleUniqueFolderCheck,
|
|
22958
23175
|
"files:check-unique-folder": handleUniqueFolderCheck,
|
|
22959
23176
|
"images:check-all-files": handleCheckAllFiles,
|