@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** — Val can fix it automatically. Mirrors the CLI, which prints
64
- * these with `⚠` (its `validation-fixable-error` event) rather than `✘`. In an
65
- * editor a one-click-fixable metadata mismatch should not shout as loudly as a
66
- * type error.
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.0",
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** — Val can fix it automatically. Mirrors the CLI, which prints
1375
- * these with `⚠` (its `validation-fixable-error` event) rather than `✘`. In an
1376
- * editor a one-click-fixable metadata mismatch should not shout as loudly as a
1377
- * type error.
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 ref = fixes.includes("videos:add-metadata") ?
1596
- // A video set entry is keyed by its file; the value has no `path`.
1597
- core.Internal.splitModulePath(modulePath).pop() : resolved.source?.path;
1598
- if (typeof ref !== "string") {
1599
- return undefined;
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
- // Remote references are URLs and are not expected on disk.
1602
- if (core.Internal.remote.splitRemoteRef(ref).status === "success") {
1603
- return undefined;
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
- const filePath = path__default["default"].join(valRoot, ref);
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.0",
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** — Val can fix it automatically. Mirrors the CLI, which prints
1375
- * these with `⚠` (its `validation-fixable-error` event) rather than `✘`. In an
1376
- * editor a one-click-fixable metadata mismatch should not shout as loudly as a
1377
- * type error.
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 ref = fixes.includes("videos:add-metadata") ?
1596
- // A video set entry is keyed by its file; the value has no `path`.
1597
- core.Internal.splitModulePath(modulePath).pop() : resolved.source?.path;
1598
- if (typeof ref !== "string") {
1599
- return undefined;
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
- // Remote references are URLs and are not expected on disk.
1602
- if (core.Internal.remote.splitRemoteRef(ref).status === "success") {
1603
- return undefined;
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
- const filePath = path__default["default"].join(valRoot, ref);
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.0",
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** — Val can fix it automatically. Mirrors the CLI, which prints
1364
- * these with `⚠` (its `validation-fixable-error` event) rather than `✘`. In an
1365
- * editor a one-click-fixable metadata mismatch should not shout as loudly as a
1366
- * type error.
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 ref = fixes.includes("videos:add-metadata") ?
1585
- // A video set entry is keyed by its file; the value has no `path`.
1586
- Internal.splitModulePath(modulePath).pop() : resolved.source?.path;
1587
- if (typeof ref !== "string") {
1588
- return undefined;
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
- // Remote references are URLs and are not expected on disk.
1591
- if (Internal.remote.splitRemoteRef(ref).status === "success") {
1592
- return undefined;
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
- const filePath = path.join(valRoot, ref);
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.0",
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.148.7",
33
- "@valbuild/server": "0.150.0",
34
- "@valbuild/shared": "0.149.7"
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",