@valbuild/language-server 0.150.0 → 0.150.1
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
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @valbuild/language-server
|
|
2
2
|
|
|
3
|
+
## 0.150.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#894](https://github.com/valbuild/val/pull/894) [`9171baa`](https://github.com/valbuild/val/commit/9171baad7beb1b2a355c70724d2339467b126e02) Thanks [@freekh](https://github.com/freekh)! - `val validate` no longer fails a project just because some of its files are
|
|
8
|
+
local while the project stores files remotely (`files: { remote: true }` or
|
|
9
|
+
`.remote()`). Every project made from a template starts like that, and the
|
|
10
|
+
site serves those files from `public/` until they are uploaded. They are now
|
|
11
|
+
reported as **warnings**, grouped into one block per file with the command
|
|
12
|
+
that uploads them:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
content/images.val.ts ⚠ 7 warnings (12ms)
|
|
16
|
+
│
|
|
17
|
+
│ ⚠ Local files in a project with remote files. Your site serves them from public/ for now; they move to remote storage when uploaded.
|
|
18
|
+
│
|
|
19
|
+
│ content/images.val.ts:7:5 /public/val/images/image-0_00000.png
|
|
20
|
+
│ content/images.val.ts:8:5 /public/val/images/image-1_00001.png
|
|
21
|
+
│ content/images.val.ts:9:5 /public/val/images/image-2_00002.png
|
|
22
|
+
│ content/images.val.ts:10:5 /public/val/images/image-3_00003.png
|
|
23
|
+
│ content/images.val.ts:11:5 /public/val/images/image-4_00004.png
|
|
24
|
+
│ … 2 more
|
|
25
|
+
│
|
|
26
|
+
│ → val validate --fix uploads them (needs val login)
|
|
27
|
+
│
|
|
28
|
+
|
|
29
|
+
✔ No validation errors · 7 warnings in 1 file
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- `--strict` on `val validate` and `val publish` makes warnings fail too.
|
|
33
|
+
- `val validate --fix` still fails when it cannot upload them, for example
|
|
34
|
+
when you are not logged in.
|
|
35
|
+
- A local file that does not exist is still an error.
|
|
36
|
+
- The language server shows these as warnings.
|
|
37
|
+
- In the Studio, **Check everything** on the Validate page lists them with a
|
|
38
|
+
**Fix** button that uploads them, so a hosted project, which
|
|
39
|
+
has no command line, can move its template's images and files to remote
|
|
40
|
+
storage. That covers images, files and videos (a video's poster, captions
|
|
41
|
+
and HLS stream go up with it), images inside rich text included, and the
|
|
42
|
+
fields that picked a gallery image or a video from a set are updated with
|
|
43
|
+
it.
|
|
44
|
+
- On a hosted project, **Check everything** no longer reports the template's
|
|
45
|
+
images and videos as "The file is gone", and no longer offers a Fix that
|
|
46
|
+
would remove them from their gallery or video set.
|
|
47
|
+
|
|
48
|
+
Fixable errors are now printed with `✘`, like every other error, instead of
|
|
49
|
+
the `⚠` warnings use. They were always errors and still make `val validate`
|
|
50
|
+
fail.
|
|
51
|
+
|
|
52
|
+
- Updated dependencies [[`9171baa`](https://github.com/valbuild/val/commit/9171baad7beb1b2a355c70724d2339467b126e02)]:
|
|
53
|
+
- @valbuild/core@0.150.1
|
|
54
|
+
- @valbuild/server@0.150.1
|
|
55
|
+
- @valbuild/shared@0.150.1
|
|
56
|
+
|
|
3
57
|
## 0.150.0
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
|
@@ -60,15 +60,18 @@ export type ValDiagnosticData = {
|
|
|
60
60
|
/**
|
|
61
61
|
* Severity policy, in one place.
|
|
62
62
|
*
|
|
63
|
-
* - **Warning** —
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
63
|
+
* - **Warning** — two kinds:
|
|
64
|
+
* - A local file in a project with remote files (`isValidationWarning`).
|
|
65
|
+
* The CLI calls this a warning too: `val validate` reports it and passes
|
|
66
|
+
* unless `--strict`. Every project made from a template starts this way.
|
|
67
|
+
* - Anything Val can fix automatically. In an editor a one-click-fixable
|
|
68
|
+
* metadata mismatch should not shout as loudly as a type error. The CLI
|
|
69
|
+
* still counts these as errors (`✘`, "run --fix") and exits non-zero, so
|
|
70
|
+
* Warning here is about presentation, not about the problem being
|
|
71
|
+
* optional.
|
|
67
72
|
* - **Error** — everything else: the content is wrong, the schema is wrong, or
|
|
68
|
-
* the module does not work at all.
|
|
69
|
-
*
|
|
70
|
-
* Note that `val validate` still exits non-zero for fixable errors, so Warning
|
|
71
|
-
* here is about presentation, not about the problem being optional.
|
|
73
|
+
* the module does not work at all. A local file that does not exist is
|
|
74
|
+
* `val/file-not-found`, an Error, whatever fix it was reported with.
|
|
72
75
|
*/
|
|
73
76
|
export declare function severityFor({ code, fixes, }: {
|
|
74
77
|
code: ValDiagnosticCode;
|
|
@@ -183,7 +183,7 @@ var packageJson = {
|
|
|
183
183
|
"lsp",
|
|
184
184
|
"language-server"
|
|
185
185
|
],
|
|
186
|
-
version: "0.150.
|
|
186
|
+
version: "0.150.1",
|
|
187
187
|
bin: {
|
|
188
188
|
"val-language-server": "./bin.js"
|
|
189
189
|
},
|
|
@@ -1371,20 +1371,29 @@ const VAL_DIAGNOSTIC_CODES = [/** Content does not satisfy the schema. */
|
|
|
1371
1371
|
/**
|
|
1372
1372
|
* Severity policy, in one place.
|
|
1373
1373
|
*
|
|
1374
|
-
* - **Warning** —
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1374
|
+
* - **Warning** — two kinds:
|
|
1375
|
+
* - A local file in a project with remote files (`isValidationWarning`).
|
|
1376
|
+
* The CLI calls this a warning too: `val validate` reports it and passes
|
|
1377
|
+
* unless `--strict`. Every project made from a template starts this way.
|
|
1378
|
+
* - Anything Val can fix automatically. In an editor a one-click-fixable
|
|
1379
|
+
* metadata mismatch should not shout as loudly as a type error. The CLI
|
|
1380
|
+
* still counts these as errors (`✘`, "run --fix") and exits non-zero, so
|
|
1381
|
+
* Warning here is about presentation, not about the problem being
|
|
1382
|
+
* optional.
|
|
1378
1383
|
* - **Error** — everything else: the content is wrong, the schema is wrong, or
|
|
1379
|
-
* the module does not work at all.
|
|
1380
|
-
*
|
|
1381
|
-
* Note that `val validate` still exits non-zero for fixable errors, so Warning
|
|
1382
|
-
* here is about presentation, not about the problem being optional.
|
|
1384
|
+
* the module does not work at all. A local file that does not exist is
|
|
1385
|
+
* `val/file-not-found`, an Error, whatever fix it was reported with.
|
|
1383
1386
|
*/
|
|
1384
1387
|
function severityFor({
|
|
1385
1388
|
code,
|
|
1386
1389
|
fixes
|
|
1387
1390
|
}) {
|
|
1391
|
+
// Its own branch, so it stays a warning if the one below ever changes.
|
|
1392
|
+
if (code === "val/validation" && internal.isValidationWarning({
|
|
1393
|
+
fixes
|
|
1394
|
+
})) {
|
|
1395
|
+
return vscodeLanguageserver.DiagnosticSeverity.Warning;
|
|
1396
|
+
}
|
|
1388
1397
|
if (code === "val/validation" && fixes && fixes.length > 0) {
|
|
1389
1398
|
return vscodeLanguageserver.DiagnosticSeverity.Warning;
|
|
1390
1399
|
}
|
|
@@ -1418,7 +1427,16 @@ const FILE_FIXES = ["image:add-metadata", "image:check-metadata", "image:upload-
|
|
|
1418
1427
|
// Local only: core never asks a remote video for its metadata.
|
|
1419
1428
|
"video:add-metadata",
|
|
1420
1429
|
// The same, for a video set's entry, whose file is its KEY.
|
|
1421
|
-
"videos:add-metadata"
|
|
1430
|
+
"videos:add-metadata",
|
|
1431
|
+
// A collection entry still to upload: its file is its key too, and a
|
|
1432
|
+
// missing one has to stay an error rather than read as the warning
|
|
1433
|
+
// `isValidationWarning` makes of the upload.
|
|
1434
|
+
"images:upload-remote", "files:upload-remote", "videos:upload-remote",
|
|
1435
|
+
// A video still to upload: `path` is the video's file.
|
|
1436
|
+
"video:upload-remote"];
|
|
1437
|
+
|
|
1438
|
+
/** Fixes reported on a collection entry, whose file is its key, not a `path`. */
|
|
1439
|
+
const KEYED_BY_FILE = ["videos:add-metadata", "images:upload-remote", "files:upload-remote", "videos:upload-remote"];
|
|
1422
1440
|
function build(range, message, data) {
|
|
1423
1441
|
return {
|
|
1424
1442
|
range,
|
|
@@ -1592,18 +1610,38 @@ function missingFileRef({
|
|
|
1592
1610
|
try {
|
|
1593
1611
|
const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
1594
1612
|
const resolved = core.Internal.resolvePath(modulePath, content.source, content.schema);
|
|
1595
|
-
const
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1613
|
+
const value = resolved.source;
|
|
1614
|
+
const source = isRecord(value) ? value : undefined;
|
|
1615
|
+
const refs = fixes.some(fix => KEYED_BY_FILE.includes(fix)) ?
|
|
1616
|
+
// A collection entry is keyed by its file; the value has no `path`.
|
|
1617
|
+
[core.Internal.splitModulePath(modulePath).pop()] : [source?.path];
|
|
1618
|
+
if (fixes.includes("video:upload-remote") || fixes.includes("videos:upload-remote")) {
|
|
1619
|
+
// Every file the upload moves, as the CLI checks before it moves any:
|
|
1620
|
+
// the poster and captions too. A field picked from a set moves only
|
|
1621
|
+
// those -- the video is the set's (`movablePathsOf`).
|
|
1622
|
+
if (fixes.includes("video:upload-remote") && resolved.schema.type === "video" && resolved.schema.referencedModule !== undefined) {
|
|
1623
|
+
refs.length = 0;
|
|
1624
|
+
}
|
|
1625
|
+
if (isRecord(source?.poster)) {
|
|
1626
|
+
refs.push(source.poster.path);
|
|
1627
|
+
}
|
|
1628
|
+
if (Array.isArray(source?.captions)) {
|
|
1629
|
+
for (const track of source.captions) {
|
|
1630
|
+
if (isRecord(track)) refs.push(track.path);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1600
1633
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1634
|
+
for (const ref of refs) {
|
|
1635
|
+
// Remote references are URLs and are not expected on disk.
|
|
1636
|
+
if (typeof ref !== "string" || core.Internal.remote.splitRemoteRef(ref).status === "success") {
|
|
1637
|
+
continue;
|
|
1638
|
+
}
|
|
1639
|
+
const filePath = path__default["default"].join(valRoot, ref);
|
|
1640
|
+
if (!fs__default["default"].existsSync(filePath)) {
|
|
1641
|
+
return filePath;
|
|
1642
|
+
}
|
|
1604
1643
|
}
|
|
1605
|
-
|
|
1606
|
-
return fs__default["default"].existsSync(filePath) ? undefined : filePath;
|
|
1644
|
+
return undefined;
|
|
1607
1645
|
} catch {
|
|
1608
1646
|
// Resolution can fail when the schema failed to serialize; skip the check
|
|
1609
1647
|
// rather than dropping the underlying validation error.
|
|
@@ -1901,6 +1939,9 @@ function galleryMembershipAt({
|
|
|
1901
1939
|
mediaType: schema.type
|
|
1902
1940
|
};
|
|
1903
1941
|
}
|
|
1942
|
+
function isRecord(value) {
|
|
1943
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1944
|
+
}
|
|
1904
1945
|
|
|
1905
1946
|
/**
|
|
1906
1947
|
* Narrow an edit down to the region that actually changed.
|
|
@@ -183,7 +183,7 @@ var packageJson = {
|
|
|
183
183
|
"lsp",
|
|
184
184
|
"language-server"
|
|
185
185
|
],
|
|
186
|
-
version: "0.150.
|
|
186
|
+
version: "0.150.1",
|
|
187
187
|
bin: {
|
|
188
188
|
"val-language-server": "./bin.js"
|
|
189
189
|
},
|
|
@@ -1371,20 +1371,29 @@ const VAL_DIAGNOSTIC_CODES = [/** Content does not satisfy the schema. */
|
|
|
1371
1371
|
/**
|
|
1372
1372
|
* Severity policy, in one place.
|
|
1373
1373
|
*
|
|
1374
|
-
* - **Warning** —
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1374
|
+
* - **Warning** — two kinds:
|
|
1375
|
+
* - A local file in a project with remote files (`isValidationWarning`).
|
|
1376
|
+
* The CLI calls this a warning too: `val validate` reports it and passes
|
|
1377
|
+
* unless `--strict`. Every project made from a template starts this way.
|
|
1378
|
+
* - Anything Val can fix automatically. In an editor a one-click-fixable
|
|
1379
|
+
* metadata mismatch should not shout as loudly as a type error. The CLI
|
|
1380
|
+
* still counts these as errors (`✘`, "run --fix") and exits non-zero, so
|
|
1381
|
+
* Warning here is about presentation, not about the problem being
|
|
1382
|
+
* optional.
|
|
1378
1383
|
* - **Error** — everything else: the content is wrong, the schema is wrong, or
|
|
1379
|
-
* the module does not work at all.
|
|
1380
|
-
*
|
|
1381
|
-
* Note that `val validate` still exits non-zero for fixable errors, so Warning
|
|
1382
|
-
* here is about presentation, not about the problem being optional.
|
|
1384
|
+
* the module does not work at all. A local file that does not exist is
|
|
1385
|
+
* `val/file-not-found`, an Error, whatever fix it was reported with.
|
|
1383
1386
|
*/
|
|
1384
1387
|
function severityFor({
|
|
1385
1388
|
code,
|
|
1386
1389
|
fixes
|
|
1387
1390
|
}) {
|
|
1391
|
+
// Its own branch, so it stays a warning if the one below ever changes.
|
|
1392
|
+
if (code === "val/validation" && internal.isValidationWarning({
|
|
1393
|
+
fixes
|
|
1394
|
+
})) {
|
|
1395
|
+
return vscodeLanguageserver.DiagnosticSeverity.Warning;
|
|
1396
|
+
}
|
|
1388
1397
|
if (code === "val/validation" && fixes && fixes.length > 0) {
|
|
1389
1398
|
return vscodeLanguageserver.DiagnosticSeverity.Warning;
|
|
1390
1399
|
}
|
|
@@ -1418,7 +1427,16 @@ const FILE_FIXES = ["image:add-metadata", "image:check-metadata", "image:upload-
|
|
|
1418
1427
|
// Local only: core never asks a remote video for its metadata.
|
|
1419
1428
|
"video:add-metadata",
|
|
1420
1429
|
// The same, for a video set's entry, whose file is its KEY.
|
|
1421
|
-
"videos:add-metadata"
|
|
1430
|
+
"videos:add-metadata",
|
|
1431
|
+
// A collection entry still to upload: its file is its key too, and a
|
|
1432
|
+
// missing one has to stay an error rather than read as the warning
|
|
1433
|
+
// `isValidationWarning` makes of the upload.
|
|
1434
|
+
"images:upload-remote", "files:upload-remote", "videos:upload-remote",
|
|
1435
|
+
// A video still to upload: `path` is the video's file.
|
|
1436
|
+
"video:upload-remote"];
|
|
1437
|
+
|
|
1438
|
+
/** Fixes reported on a collection entry, whose file is its key, not a `path`. */
|
|
1439
|
+
const KEYED_BY_FILE = ["videos:add-metadata", "images:upload-remote", "files:upload-remote", "videos:upload-remote"];
|
|
1422
1440
|
function build(range, message, data) {
|
|
1423
1441
|
return {
|
|
1424
1442
|
range,
|
|
@@ -1592,18 +1610,38 @@ function missingFileRef({
|
|
|
1592
1610
|
try {
|
|
1593
1611
|
const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
1594
1612
|
const resolved = core.Internal.resolvePath(modulePath, content.source, content.schema);
|
|
1595
|
-
const
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1613
|
+
const value = resolved.source;
|
|
1614
|
+
const source = isRecord(value) ? value : undefined;
|
|
1615
|
+
const refs = fixes.some(fix => KEYED_BY_FILE.includes(fix)) ?
|
|
1616
|
+
// A collection entry is keyed by its file; the value has no `path`.
|
|
1617
|
+
[core.Internal.splitModulePath(modulePath).pop()] : [source?.path];
|
|
1618
|
+
if (fixes.includes("video:upload-remote") || fixes.includes("videos:upload-remote")) {
|
|
1619
|
+
// Every file the upload moves, as the CLI checks before it moves any:
|
|
1620
|
+
// the poster and captions too. A field picked from a set moves only
|
|
1621
|
+
// those -- the video is the set's (`movablePathsOf`).
|
|
1622
|
+
if (fixes.includes("video:upload-remote") && resolved.schema.type === "video" && resolved.schema.referencedModule !== undefined) {
|
|
1623
|
+
refs.length = 0;
|
|
1624
|
+
}
|
|
1625
|
+
if (isRecord(source?.poster)) {
|
|
1626
|
+
refs.push(source.poster.path);
|
|
1627
|
+
}
|
|
1628
|
+
if (Array.isArray(source?.captions)) {
|
|
1629
|
+
for (const track of source.captions) {
|
|
1630
|
+
if (isRecord(track)) refs.push(track.path);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1600
1633
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1634
|
+
for (const ref of refs) {
|
|
1635
|
+
// Remote references are URLs and are not expected on disk.
|
|
1636
|
+
if (typeof ref !== "string" || core.Internal.remote.splitRemoteRef(ref).status === "success") {
|
|
1637
|
+
continue;
|
|
1638
|
+
}
|
|
1639
|
+
const filePath = path__default["default"].join(valRoot, ref);
|
|
1640
|
+
if (!fs__default["default"].existsSync(filePath)) {
|
|
1641
|
+
return filePath;
|
|
1642
|
+
}
|
|
1604
1643
|
}
|
|
1605
|
-
|
|
1606
|
-
return fs__default["default"].existsSync(filePath) ? undefined : filePath;
|
|
1644
|
+
return undefined;
|
|
1607
1645
|
} catch {
|
|
1608
1646
|
// Resolution can fail when the schema failed to serialize; skip the check
|
|
1609
1647
|
// rather than dropping the underlying validation error.
|
|
@@ -1901,6 +1939,9 @@ function galleryMembershipAt({
|
|
|
1901
1939
|
mediaType: schema.type
|
|
1902
1940
|
};
|
|
1903
1941
|
}
|
|
1942
|
+
function isRecord(value) {
|
|
1943
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1944
|
+
}
|
|
1904
1945
|
|
|
1905
1946
|
/**
|
|
1906
1947
|
* Narrow an edit down to the region that actually changed.
|
|
@@ -8,7 +8,7 @@ import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
|
8
8
|
import crypto from 'crypto';
|
|
9
9
|
import { createRequire } from 'node:module';
|
|
10
10
|
import { fixHandlers, createService, analyzeValModule, createFixPatch, findJsonEntryFilePath, rebaseContentOp, classifyJsonValuesOp, parsePersonalAccessTokenFile, getPersonalAccessTokenPath, startValLogin, awaitValLoginConfirmation, persistPersonalAccessToken, ValLoginError, findAndEvalValConfigFile, patchSourceFile, getSettings, uploadRemoteFile, planJsonValuesEntryExtraction, extractVideoMetadataFromFile, extractImageMetadata, extractFileMetadata, findDefaultExport } from '@valbuild/server';
|
|
11
|
-
import { resolveSchemaSourceFixes, SCHEMA_SOURCE_FIXES, getRoutesWithModulePaths } from '@valbuild/shared/internal';
|
|
11
|
+
import { isValidationWarning, resolveSchemaSourceFixes, SCHEMA_SOURCE_FIXES, getRoutesWithModulePaths } from '@valbuild/shared/internal';
|
|
12
12
|
import { result } from '@valbuild/core/fp';
|
|
13
13
|
import { JSONOps, applyPatch, deepClone } from '@valbuild/core/patch';
|
|
14
14
|
|
|
@@ -172,7 +172,7 @@ var packageJson = {
|
|
|
172
172
|
"lsp",
|
|
173
173
|
"language-server"
|
|
174
174
|
],
|
|
175
|
-
version: "0.150.
|
|
175
|
+
version: "0.150.1",
|
|
176
176
|
bin: {
|
|
177
177
|
"val-language-server": "./bin.js"
|
|
178
178
|
},
|
|
@@ -1360,20 +1360,29 @@ const VAL_DIAGNOSTIC_CODES = [/** Content does not satisfy the schema. */
|
|
|
1360
1360
|
/**
|
|
1361
1361
|
* Severity policy, in one place.
|
|
1362
1362
|
*
|
|
1363
|
-
* - **Warning** —
|
|
1364
|
-
*
|
|
1365
|
-
*
|
|
1366
|
-
*
|
|
1363
|
+
* - **Warning** — two kinds:
|
|
1364
|
+
* - A local file in a project with remote files (`isValidationWarning`).
|
|
1365
|
+
* The CLI calls this a warning too: `val validate` reports it and passes
|
|
1366
|
+
* unless `--strict`. Every project made from a template starts this way.
|
|
1367
|
+
* - Anything Val can fix automatically. In an editor a one-click-fixable
|
|
1368
|
+
* metadata mismatch should not shout as loudly as a type error. The CLI
|
|
1369
|
+
* still counts these as errors (`✘`, "run --fix") and exits non-zero, so
|
|
1370
|
+
* Warning here is about presentation, not about the problem being
|
|
1371
|
+
* optional.
|
|
1367
1372
|
* - **Error** — everything else: the content is wrong, the schema is wrong, or
|
|
1368
|
-
* the module does not work at all.
|
|
1369
|
-
*
|
|
1370
|
-
* Note that `val validate` still exits non-zero for fixable errors, so Warning
|
|
1371
|
-
* here is about presentation, not about the problem being optional.
|
|
1373
|
+
* the module does not work at all. A local file that does not exist is
|
|
1374
|
+
* `val/file-not-found`, an Error, whatever fix it was reported with.
|
|
1372
1375
|
*/
|
|
1373
1376
|
function severityFor({
|
|
1374
1377
|
code,
|
|
1375
1378
|
fixes
|
|
1376
1379
|
}) {
|
|
1380
|
+
// Its own branch, so it stays a warning if the one below ever changes.
|
|
1381
|
+
if (code === "val/validation" && isValidationWarning({
|
|
1382
|
+
fixes
|
|
1383
|
+
})) {
|
|
1384
|
+
return DiagnosticSeverity.Warning;
|
|
1385
|
+
}
|
|
1377
1386
|
if (code === "val/validation" && fixes && fixes.length > 0) {
|
|
1378
1387
|
return DiagnosticSeverity.Warning;
|
|
1379
1388
|
}
|
|
@@ -1407,7 +1416,16 @@ const FILE_FIXES = ["image:add-metadata", "image:check-metadata", "image:upload-
|
|
|
1407
1416
|
// Local only: core never asks a remote video for its metadata.
|
|
1408
1417
|
"video:add-metadata",
|
|
1409
1418
|
// The same, for a video set's entry, whose file is its KEY.
|
|
1410
|
-
"videos:add-metadata"
|
|
1419
|
+
"videos:add-metadata",
|
|
1420
|
+
// A collection entry still to upload: its file is its key too, and a
|
|
1421
|
+
// missing one has to stay an error rather than read as the warning
|
|
1422
|
+
// `isValidationWarning` makes of the upload.
|
|
1423
|
+
"images:upload-remote", "files:upload-remote", "videos:upload-remote",
|
|
1424
|
+
// A video still to upload: `path` is the video's file.
|
|
1425
|
+
"video:upload-remote"];
|
|
1426
|
+
|
|
1427
|
+
/** Fixes reported on a collection entry, whose file is its key, not a `path`. */
|
|
1428
|
+
const KEYED_BY_FILE = ["videos:add-metadata", "images:upload-remote", "files:upload-remote", "videos:upload-remote"];
|
|
1411
1429
|
function build(range, message, data) {
|
|
1412
1430
|
return {
|
|
1413
1431
|
range,
|
|
@@ -1581,18 +1599,38 @@ function missingFileRef({
|
|
|
1581
1599
|
try {
|
|
1582
1600
|
const [, modulePath] = Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
1583
1601
|
const resolved = Internal.resolvePath(modulePath, content.source, content.schema);
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1602
|
+
const value = resolved.source;
|
|
1603
|
+
const source = isRecord(value) ? value : undefined;
|
|
1604
|
+
const refs = fixes.some(fix => KEYED_BY_FILE.includes(fix)) ?
|
|
1605
|
+
// A collection entry is keyed by its file; the value has no `path`.
|
|
1606
|
+
[Internal.splitModulePath(modulePath).pop()] : [source?.path];
|
|
1607
|
+
if (fixes.includes("video:upload-remote") || fixes.includes("videos:upload-remote")) {
|
|
1608
|
+
// Every file the upload moves, as the CLI checks before it moves any:
|
|
1609
|
+
// the poster and captions too. A field picked from a set moves only
|
|
1610
|
+
// those -- the video is the set's (`movablePathsOf`).
|
|
1611
|
+
if (fixes.includes("video:upload-remote") && resolved.schema.type === "video" && resolved.schema.referencedModule !== undefined) {
|
|
1612
|
+
refs.length = 0;
|
|
1613
|
+
}
|
|
1614
|
+
if (isRecord(source?.poster)) {
|
|
1615
|
+
refs.push(source.poster.path);
|
|
1616
|
+
}
|
|
1617
|
+
if (Array.isArray(source?.captions)) {
|
|
1618
|
+
for (const track of source.captions) {
|
|
1619
|
+
if (isRecord(track)) refs.push(track.path);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1589
1622
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1623
|
+
for (const ref of refs) {
|
|
1624
|
+
// Remote references are URLs and are not expected on disk.
|
|
1625
|
+
if (typeof ref !== "string" || Internal.remote.splitRemoteRef(ref).status === "success") {
|
|
1626
|
+
continue;
|
|
1627
|
+
}
|
|
1628
|
+
const filePath = path.join(valRoot, ref);
|
|
1629
|
+
if (!fs.existsSync(filePath)) {
|
|
1630
|
+
return filePath;
|
|
1631
|
+
}
|
|
1593
1632
|
}
|
|
1594
|
-
|
|
1595
|
-
return fs.existsSync(filePath) ? undefined : filePath;
|
|
1633
|
+
return undefined;
|
|
1596
1634
|
} catch {
|
|
1597
1635
|
// Resolution can fail when the schema failed to serialize; skip the check
|
|
1598
1636
|
// rather than dropping the underlying validation error.
|
|
@@ -1890,6 +1928,9 @@ function galleryMembershipAt({
|
|
|
1890
1928
|
mediaType: schema.type
|
|
1891
1929
|
};
|
|
1892
1930
|
}
|
|
1931
|
+
function isRecord(value) {
|
|
1932
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1933
|
+
}
|
|
1893
1934
|
|
|
1894
1935
|
/**
|
|
1895
1936
|
* Narrow an edit down to the region that actually changed.
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"lsp",
|
|
12
12
|
"language-server"
|
|
13
13
|
],
|
|
14
|
-
"version": "0.150.
|
|
14
|
+
"version": "0.150.1",
|
|
15
15
|
"bin": {
|
|
16
16
|
"val-language-server": "./bin.js"
|
|
17
17
|
},
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"typescript": "^6.0.3",
|
|
30
30
|
"vscode-languageserver": "^10.1.0",
|
|
31
31
|
"vscode-languageserver-textdocument": "^1.0.14",
|
|
32
|
-
"@valbuild/core": "0.
|
|
33
|
-
"@valbuild/server": "0.150.
|
|
34
|
-
"@valbuild/shared": "0.
|
|
32
|
+
"@valbuild/core": "0.150.1",
|
|
33
|
+
"@valbuild/server": "0.150.1",
|
|
34
|
+
"@valbuild/shared": "0.150.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/jest": "^30.0.0",
|