@likec4/language-server 1.46.0 → 1.46.3

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.
@@ -1,12 +1,11 @@
1
1
  import { isLikeC4Config, normalizeIncludeConfig, validateProjectConfig, } from '@likec4/config';
2
- import { BiMap, delay, invariant, memoizeProp, nonNullable } from '@likec4/core/utils';
2
+ import { BiMap, invariant, memoizeProp, nonNullable } from '@likec4/core/utils';
3
3
  import { wrapError } from '@likec4/log';
4
4
  import { deepEqual } from 'fast-equals';
5
5
  import { interruptAndCheck, URI, WorkspaceCache, } from 'langium';
6
6
  import picomatch from 'picomatch';
7
- import { hasAtLeast, isNullish, map, pipe, prop, sortBy } from 'remeda';
7
+ import { filter, hasAtLeast, isNullish, map, pipe, prop, sortBy } from 'remeda';
8
8
  import { joinRelativeURL, parseFilename, withoutProtocol, withTrailingSlash, } from 'ufo';
9
- import { isLikeC4Builtin } from '../likec4lib';
10
9
  import { logger as mainLogger } from '../logger';
11
10
  const logger = mainLogger.getChild('ProjectsManager');
12
11
  function normalizeUri(uri) {
@@ -21,6 +20,13 @@ function normalizeUri(uri) {
21
20
  return uri.uri.toString();
22
21
  }
23
22
  }
23
+ /**
24
+ * Returns a predicate that checks if the given path is included in the project folder.
25
+ */
26
+ function isParentFolderFor(uri) {
27
+ const path = normalizeUri(uri);
28
+ return (p) => path.startsWith(p.folder);
29
+ }
24
30
  export function ProjectFolder(folder) {
25
31
  folder = normalizeUri(folder);
26
32
  return withTrailingSlash(folder);
@@ -155,7 +161,7 @@ export class ProjectsManager {
155
161
  id,
156
162
  folderUri: project.folderUri,
157
163
  config: project.config,
158
- ...(project.includePaths && { includePaths: project.includePaths.map(p => p.uri) }),
164
+ ...(project.includePaths && { includePaths: map(project.includePaths, prop('uri')) }),
159
165
  };
160
166
  }
161
167
  /**
@@ -190,7 +196,7 @@ export class ProjectsManager {
190
196
  if (typeof document === 'string' || URI.isUri(document)) {
191
197
  let docUriAsString = normalizeUri(document);
192
198
  const project = this.findProjectForDocument(docUriAsString);
193
- return project.exclude ? project.exclude(withoutProtocol(docUriAsString)) : false;
199
+ return !!project.exclude && project.exclude(withoutProtocol(docUriAsString));
194
200
  }
195
201
  let isExcluded = this.#excludedDocuments.get(document);
196
202
  if (isExcluded === undefined) {
@@ -199,6 +205,26 @@ export class ProjectsManager {
199
205
  }
200
206
  return isExcluded;
201
207
  }
208
+ /**
209
+ * Checks if the specified document is included by the project.
210
+ */
211
+ isIncluded(projectId, document) {
212
+ if (typeof document === 'string' || URI.isUri(document)) {
213
+ let project = this.#projects.find(p => p.id === projectId);
214
+ if (!project || !project.includePaths) {
215
+ return false;
216
+ }
217
+ return project.includePaths.some(isParentFolderFor(document));
218
+ }
219
+ return this.isIncluded(projectId, document.uri);
220
+ }
221
+ includedInProjects(document) {
222
+ if (typeof document === 'string' || URI.isUri(document)) {
223
+ let docUriAsString = normalizeUri(document);
224
+ return pipe(this.#projects, filter(p => !!p.includePaths && p.includePaths.some(isParentFolderFor(docUriAsString))), map(p => p.id));
225
+ }
226
+ return this.includedInProjects(document.uri);
227
+ }
202
228
  /**
203
229
  * Checks if it is a config file and it is not excluded by default exclude pattern
204
230
  *
@@ -218,7 +244,7 @@ export class ProjectsManager {
218
244
  /**
219
245
  * Registers likec4 project by config file.
220
246
  */
221
- async registerConfigFile(configFile) {
247
+ async registerConfigFile(configFile, cancelToken) {
222
248
  if (DefaultProject.exclude(configFile.path)) {
223
249
  throw new Error(`Path to ${configFile.fsPath} is excluded by: ${DefaultProject.config.exclude.join(', ')}`);
224
250
  }
@@ -229,7 +255,7 @@ export class ProjectsManager {
229
255
  const config = await this.services.workspace.FileSystemProvider.loadProjectConfig(configFile);
230
256
  const path = joinRelativeURL(configFile.path, '..');
231
257
  const folderUri = configFile.with({ path });
232
- return await this.registerProject({ config, folderUri });
258
+ return await this.registerProject({ config, folderUri }, cancelToken);
233
259
  }
234
260
  catch (error) {
235
261
  this.services.lsp.Connection?.window.showErrorMessage(`LikeC4: Failed to register project at ${configFile.fsPath}`);
@@ -240,7 +266,7 @@ export class ProjectsManager {
240
266
  * Registers (or reloads) likec4 project by config file or config object.
241
267
  * If there is some project registered at same folder, it will be reloaded.
242
268
  */
243
- async registerProject(opts) {
269
+ async registerProject(opts, cancelToken) {
244
270
  const config = validateProjectConfig(opts.config);
245
271
  const folder = ProjectFolder(opts.folderUri);
246
272
  let project = this.#projects.find(p => p.folder === folder);
@@ -265,7 +291,9 @@ export class ProjectsManager {
265
291
  // if there is any project within subfolder or parent folder
266
292
  // we need to reset assigned to documents project IDs
267
293
  mustReset = this.#projects.some(p => p.folder.startsWith(folder) || folder.startsWith(p.folder));
268
- this.#projects = pipe([...this.#projects, project], sortBy([({ folder }) => withoutProtocol(folder).split('/').length, 'desc']));
294
+ this.#projects = pipe([...this.#projects, project], sortBy(
295
+ // sort by folder depth (longest first)
296
+ [({ folder }) => withoutProtocol(folder).split('/').length, 'desc']));
269
297
  logger.info `register project ${project.id} folder: ${folder}`;
270
298
  }
271
299
  else {
@@ -296,7 +324,7 @@ export class ProjectsManager {
296
324
  }
297
325
  // Resolve include paths relative to project folder
298
326
  if (project.includeConfig.paths && hasAtLeast(project.includeConfig.paths, 1)) {
299
- project.includePaths = project.includeConfig.paths.map(includePath => {
327
+ project.includePaths = map(project.includeConfig.paths, includePath => {
300
328
  const resolvedPath = joinRelativeURL(project.folderUri.path, includePath);
301
329
  const uri = project.folderUri.with({ path: resolvedPath });
302
330
  return {
@@ -312,6 +340,7 @@ export class ProjectsManager {
312
340
  if (otherProject.id === project.id)
313
341
  continue;
314
342
  if (includePath.folder.startsWith(otherProject.folder) || otherProject.folder.startsWith(includePath.folder)) {
343
+ mustReset = true;
315
344
  logger.warn('Project "{projectId}" include path "{includePath}" overlaps with project "{otherProjectId}" folder. ' +
316
345
  'Files in overlapping areas will only belong to one project.', { projectId: project.id, includePath: includePath.folder, otherProjectId: otherProject.id });
317
346
  }
@@ -320,6 +349,7 @@ export class ProjectsManager {
320
349
  for (const otherIncludePath of otherProject.includePaths) {
321
350
  if (includePath.folder.startsWith(otherIncludePath.folder)
322
351
  || otherIncludePath.folder.startsWith(includePath.folder)) {
352
+ mustReset = true;
323
353
  logger.warn('Project "{projectId}" include path "{includePath}" overlaps with project "{otherProjectId}" ' +
324
354
  'include path "{otherIncludePath}". Files in overlapping areas will only belong to one project.', {
325
355
  projectId: project.id,
@@ -339,7 +369,7 @@ export class ProjectsManager {
339
369
  this.#projectIdToFolder.set(project.id, folder);
340
370
  // Reset assigned project IDs if no projects reload is active
341
371
  if (mustReset && !this.#activeReload) {
342
- await this.rebuidProject(project.id).catch(error => {
372
+ await this.rebuidProject(project.id, cancelToken).catch(error => {
343
373
  logger.warn('Failed to rebuild project {projectId} after config change', {
344
374
  projectId: project.id,
345
375
  error,
@@ -362,11 +392,11 @@ export class ProjectsManager {
362
392
  }).id;
363
393
  }
364
394
  #activeReload = null;
365
- async reloadProjects() {
395
+ async reloadProjects(cancelToken) {
366
396
  try {
367
397
  if (!this.#activeReload) {
368
398
  logger.debug `schedule reload projects`;
369
- this.#activeReload = this._reloadProjects();
399
+ this.#activeReload = this._reloadProjects(cancelToken);
370
400
  }
371
401
  else {
372
402
  logger.debug `reload projects is already in progress, waiting`;
@@ -377,49 +407,47 @@ export class ProjectsManager {
377
407
  this.#activeReload = null;
378
408
  }
379
409
  }
380
- async _reloadProjects() {
381
- // debounce reload projects
382
- await delay(200);
410
+ async _reloadProjects(cancelToken) {
383
411
  const folders = this.services.workspace.WorkspaceManager.workspaceFolders;
384
412
  if (!folders) {
385
413
  logger.warn('No workspace folders found');
386
414
  return;
387
415
  }
388
- await this.services.workspace.WorkspaceLock.write(async (cancelToken) => {
389
- logger.debug `start reload projects`;
390
- const configFiles = [];
391
- for (const folder of folders) {
392
- try {
393
- logger.debug `scan projects in folder ${folder.uri}`;
394
- const files = await this.services.workspace.FileSystemProvider.scanProjectFiles(URI.parse(folder.uri));
395
- for (const file of files) {
396
- if (file.isFile && this.isConfigFile(file.uri)) {
397
- logger.debug `found config ${file.uri.fsPath}`;
398
- configFiles.push(file.uri);
399
- }
416
+ logger.debug `start reload projects`;
417
+ const configFiles = [];
418
+ for (const folder of folders) {
419
+ try {
420
+ logger.debug `scan projects in folder ${folder.uri}`;
421
+ const files = await this.services.workspace.FileSystemProvider.scanProjectFiles(URI.parse(folder.uri));
422
+ for (const file of files) {
423
+ if (file.isFile && this.isConfigFile(file.uri)) {
424
+ logger.debug `found config ${file.uri.fsPath}`;
425
+ configFiles.push(file.uri);
400
426
  }
401
427
  }
402
- catch (error) {
403
- logger.error('Failed to scanProjectFiles, {folder}', { folder: folder.uri, error });
404
- }
405
428
  }
406
- if (configFiles.length === 0 && this.#projects.length !== 0) {
407
- logger.warning('No config files found, but some projects were registered before');
429
+ catch (error) {
430
+ logger.error('Failed to scanProjectFiles, {folder}', { folder: folder.uri, error });
408
431
  }
409
- await interruptAndCheck(cancelToken);
410
- this.#projects = [];
411
- this.#projectIdToFolder.clear();
412
- for (const uri of configFiles) {
413
- try {
414
- await this.registerConfigFile(uri);
415
- }
416
- catch (error) {
417
- logger.error('Failed to load config file {uri}', { uri: uri.fsPath, error });
418
- }
432
+ }
433
+ if (configFiles.length === 0 && this.#projects.length !== 0) {
434
+ logger.warning('No config files found, but some projects were registered before');
435
+ }
436
+ this.#projects = [];
437
+ this.#projectIdToFolder.clear();
438
+ for (const uri of configFiles) {
439
+ if (cancelToken) {
440
+ await interruptAndCheck(cancelToken);
419
441
  }
420
- this.reset();
421
- await this.services.workspace.WorkspaceManager.rebuildAll(cancelToken);
422
- });
442
+ try {
443
+ await this.registerConfigFile(uri, cancelToken);
444
+ }
445
+ catch (error) {
446
+ logger.error('Failed to load config file {uri}', { uri: uri.fsPath, error });
447
+ }
448
+ }
449
+ this.reset();
450
+ await this.services.workspace.WorkspaceManager.rebuildAll(cancelToken);
423
451
  }
424
452
  uniqueProjectId(name) {
425
453
  let id = name;
@@ -430,28 +458,17 @@ export class ProjectsManager {
430
458
  return id;
431
459
  }
432
460
  reset() {
461
+ logger.debug('reset');
433
462
  this.#defaultProject = undefined;
434
463
  if (this.#defaultProjectId && !this.#projectIdToFolder.has(this.#defaultProjectId)) {
435
464
  this.#defaultProjectId = undefined;
436
465
  }
437
- this.services.workspace.LangiumDocuments.all.forEach(doc => {
438
- if (isLikeC4Builtin(doc.uri)) {
439
- return;
440
- }
441
- // Remove assigned project ID to force re-calculation
442
- delete doc.likec4ProjectId;
443
- });
466
+ this.services.workspace.LangiumDocuments.resetProjectIds();
444
467
  this.documentBelongsTo.clear();
445
468
  this.mappingsToProject.clear();
446
469
  this.#excludedDocuments = new WeakMap();
447
470
  }
448
471
  async rebuidProject(projectId, cancelToken) {
449
- if (!cancelToken) {
450
- return await this.services.workspace.WorkspaceLock.write(async (ct) => {
451
- await this.rebuidProject(projectId, ct);
452
- });
453
- }
454
- logger.info `rebuild project ${projectId}`;
455
472
  // reset default project cache
456
473
  this.#defaultProject = undefined;
457
474
  const project = this.#projects.find(p => p.id === projectId) ?? this.default;
@@ -460,18 +477,18 @@ export class ProjectsManager {
460
477
  }
461
478
  const log = logger.getChild(project.id);
462
479
  const folder = project.folder;
463
- const includePathStrings = project.includePaths?.map(p => p.folder) ?? [];
480
+ const includePaths = project.includePaths;
464
481
  const docs = this.services.workspace.LangiumDocuments
465
482
  .all
466
483
  .filter(doc => {
467
484
  if (project.exclude?.(doc.uri.path)) {
468
485
  return false;
469
486
  }
470
- const docUriStr = doc.uri.toString();
487
+ const docUriStr = normalizeUri(doc.uri);
471
488
  if (docUriStr.startsWith(folder)) {
472
489
  return true;
473
490
  }
474
- if (includePathStrings.some(includePath => docUriStr.startsWith(includePath))) {
491
+ if (includePaths && includePaths.some(isParentFolderFor(docUriStr))) {
475
492
  return true;
476
493
  }
477
494
  const docdir = withTrailingSlash(joinRelativeURL(docUriStr, '..'));
@@ -480,10 +497,10 @@ export class ProjectsManager {
480
497
  .map(d => d.uri)
481
498
  .toArray();
482
499
  if (docs.length > 0) {
483
- this.reset();
484
- log.info('rebuild documents: {docs}', {
500
+ log.info('rebuild project documents: {docs}', {
485
501
  docs: docs.length,
486
502
  });
503
+ this.reset();
487
504
  await this.services.workspace.DocumentBuilder
488
505
  .update(docs, [], cancelToken)
489
506
  .catch(error => {
@@ -492,23 +509,22 @@ export class ProjectsManager {
492
509
  });
493
510
  });
494
511
  }
512
+ else {
513
+ log.debug('no documents in project, skipping rebuild');
514
+ }
495
515
  }
496
516
  findProjectForDocument(documentUri) {
497
517
  return this.mappingsToProject.get(documentUri, () => {
498
- const project = this.#projects.find(({ folder }) => documentUri.startsWith(folder));
518
+ const hasThisDoc = isParentFolderFor(documentUri);
519
+ const project = this.#projects.find(hasThisDoc);
499
520
  if (project) {
500
521
  return project;
501
522
  }
502
- const projectWithInclude = this.#projects.find(({ includePaths }) => {
503
- if (!includePaths)
504
- return false;
505
- return includePaths.some(includePath => documentUri.startsWith(includePath.folder));
523
+ const projectIncludingThisDoc = this.#projects.find(({ includePaths }) => {
524
+ return !!includePaths && includePaths.some(hasThisDoc);
506
525
  });
507
- if (projectWithInclude) {
508
- return projectWithInclude;
509
- }
510
526
  // If the document is not part of any project, assign it to the global project ID
511
- return this.default;
527
+ return projectIncludingThisDoc ?? this.default;
512
528
  });
513
529
  }
514
530
  // The mapping between document URIs and their corresponding project ID
@@ -1,6 +1,6 @@
1
1
  import type { BuildOptions, Cancellation, FileSelector, FileSystemNode, LangiumDocument, LangiumDocumentFactory } from 'langium';
2
2
  import { DefaultWorkspaceManager } from 'langium';
3
- import type { WorkspaceFolder } from 'vscode-languageserver';
3
+ import { type WorkspaceFolder } from 'vscode-languageserver';
4
4
  import { URI } from 'vscode-uri';
5
5
  import type { FileSystemProvider } from '../filesystem';
6
6
  import type { LikeC4SharedServices } from '../module';
@@ -1,6 +1,7 @@
1
1
  import { invariant } from '@likec4/core';
2
2
  import { DefaultWorkspaceManager } from 'langium';
3
3
  import { hasAtLeast } from 'remeda';
4
+ import { CancellationToken } from 'vscode-languageserver';
4
5
  import { URI } from 'vscode-uri';
5
6
  import * as BuiltIn from '../likec4lib';
6
7
  import { logger, logWarnError } from '../logger';
@@ -39,7 +40,7 @@ export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
39
40
  const projects = this.services.workspace.ProjectsManager;
40
41
  for (const entry of configFiles) {
41
42
  try {
42
- await projects.registerConfigFile(entry.uri);
43
+ await projects.registerConfigFile(entry.uri, CancellationToken.None);
43
44
  }
44
45
  catch (error) {
45
46
  logWarnError(error);
@@ -113,11 +114,6 @@ export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
113
114
  return null;
114
115
  }
115
116
  async rebuildAll(cancelToken) {
116
- if (!cancelToken) {
117
- return await this.services.workspace.WorkspaceLock.write(async (ct) => {
118
- await this.rebuildAll(ct);
119
- });
120
- }
121
117
  const docs = this.services.workspace.LangiumDocuments.all.map(d => d.uri).toArray();
122
118
  logger.info('invalidate and rebuild all {docs} documents', { docs: docs.length });
123
119
  this.services.workspace.Cache.clear();
@@ -0,0 +1,159 @@
1
+ {
2
+ "name": "@likec4/language-server",
3
+ "description": "LikeC4 Language Server",
4
+ "version": "1.45.0",
5
+ "license": "MIT",
6
+ "bugs": "https://github.com/likec4/likec4/issues",
7
+ "homepage": "https://likec4.dev",
8
+ "author": "Denis Davydkov <denis@davydkov.com>",
9
+ "files": [
10
+ "bin",
11
+ "dist",
12
+ "**/package.json",
13
+ "!**/__mocks__/",
14
+ "!**/__tests__/",
15
+ "!**/*.spec.*",
16
+ "!**/*.map"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/likec4/likec4.git",
21
+ "directory": "packages/language-server"
22
+ },
23
+ "engines": {
24
+ "node": "^20.19.0 || >=22.18.0"
25
+ },
26
+ "engineStrict": true,
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "bin": {
30
+ "likec4-language-server": "./bin/likec4-language-server.mjs"
31
+ },
32
+ "exports": {
33
+ ".": {
34
+ "sources": "./src/index.ts",
35
+ "default": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ }
39
+ },
40
+ "./likec4lib": {
41
+ "sources": "./src/likec4lib.ts",
42
+ "default": {
43
+ "types": "./dist/likec4lib.d.ts",
44
+ "import": "./dist/likec4lib.js",
45
+ "default": "./dist/likec4lib.js"
46
+ }
47
+ },
48
+ "./browser-worker": {
49
+ "sources": "./src/browser-worker.ts",
50
+ "default": {
51
+ "types": "./dist/browser-worker.d.ts",
52
+ "import": "./dist/browser-worker.js",
53
+ "default": "./dist/browser-worker.js"
54
+ }
55
+ },
56
+ "./browser": {
57
+ "sources": "./src/browser.ts",
58
+ "default": {
59
+ "types": "./dist/browser.d.ts",
60
+ "import": "./dist/browser.js",
61
+ "default": "./dist/browser.js"
62
+ }
63
+ },
64
+ "./protocol": {
65
+ "sources": "./src/protocol.ts",
66
+ "default": {
67
+ "types": "./dist/protocol.d.ts",
68
+ "import": "./dist/protocol.js",
69
+ "default": "./dist/protocol.js"
70
+ }
71
+ },
72
+ "./bundled": "./dist/bundled.mjs"
73
+ },
74
+ "publishConfig": {
75
+ "registry": "https://registry.npmjs.org",
76
+ "access": "public",
77
+ "types": "dist/index.d.ts",
78
+ "module": "dist/index.js"
79
+ },
80
+ "scripts": {
81
+ "typecheck": "tsc -b --verbose",
82
+ "build": "unbuild",
83
+ "prepack": "likec4ops prepack",
84
+ "pack": "pnpm pack",
85
+ "postpack": "cp likec4-language-server-$npm_package_version.tgz package.tgz || true",
86
+ "pregenerate": "rm -f src/generated/* || true",
87
+ "watch:langium": "langium generate --watch",
88
+ "watch:ts": "tsc --watch",
89
+ "generate": "langium generate && tsx scripts/generate-icons.ts",
90
+ "dev": "run-p \"watch:*\"",
91
+ "lint": "oxlint --type-aware",
92
+ "lint:fix": "oxlint --type-aware --fix",
93
+ "lint:package": "pnpx publint ./package.tgz",
94
+ "clean": "likec4ops clean contrib src/generated src/generated-lib",
95
+ "test": "vitest run --no-isolate",
96
+ "test-dbg": "vitest run --no-isolate -t formating",
97
+ "vitest:ui": "vitest --no-isolate --ui",
98
+ "test:watch": "vitest"
99
+ },
100
+ "dependencies": {
101
+ "@hpcc-js/wasm-graphviz": "catalog:utils",
102
+ "bundle-require": "catalog:utils",
103
+ "esbuild": "catalog:esbuild"
104
+ },
105
+ "devDependencies": {
106
+ "@hono/node-server": "catalog:hono",
107
+ "@likec4/config": "workspace:*",
108
+ "@likec4/core": "workspace:*",
109
+ "@likec4/devops": "workspace:*",
110
+ "@likec4/icons": "workspace:*",
111
+ "@likec4/layouts": "workspace:*",
112
+ "@likec4/log": "workspace:*",
113
+ "@likec4/tsconfig": "workspace:*",
114
+ "@modelcontextprotocol/sdk": "catalog:mcp",
115
+ "@msgpack/msgpack": "^3.1.2",
116
+ "@smithy/util-base64": "^4.3.0",
117
+ "@types/natural-compare-lite": "catalog:utils",
118
+ "@types/node": "catalog:",
119
+ "@types/picomatch": "catalog:utils",
120
+ "@types/vscode": "catalog:vscode",
121
+ "@types/which": "^3.0.4",
122
+ "chokidar": "catalog:utils",
123
+ "defu": "catalog:utils",
124
+ "esm-env": "catalog:utils",
125
+ "fast-equals": "catalog:utils",
126
+ "fdir": "catalog:utils",
127
+ "fetch-to-node": "^2.1.0",
128
+ "hono": "catalog:hono",
129
+ "immer": "catalog:utils",
130
+ "indent-string": "^5.0.0",
131
+ "json5": "catalog:utils",
132
+ "langium": "catalog:langium",
133
+ "langium-cli": "catalog:langium",
134
+ "nano-spawn": "catalog:utils",
135
+ "natural-compare-lite": "catalog:utils",
136
+ "oxlint": "catalog:",
137
+ "p-debounce": "catalog:utils",
138
+ "p-queue": "catalog:utils",
139
+ "p-timeout": "catalog:utils",
140
+ "picomatch": "catalog:utils",
141
+ "pretty-ms": "^9.2.0",
142
+ "remeda": "catalog:utils",
143
+ "strip-indent": "catalog:utils",
144
+ "tsx": "catalog:",
145
+ "turbo": "catalog:",
146
+ "type-fest": "catalog:utils",
147
+ "typescript": "catalog:",
148
+ "ufo": "catalog:utils",
149
+ "unbuild": "catalog:",
150
+ "vitest": "catalog:vitest",
151
+ "vscode-jsonrpc": "catalog:vscode",
152
+ "vscode-languageserver": "catalog:vscode",
153
+ "vscode-languageserver-protocol": "catalog:vscode",
154
+ "vscode-languageserver-types": "catalog:vscode",
155
+ "vscode-uri": "catalog:vscode",
156
+ "which": "^5.0.0",
157
+ "zod": "catalog:utils"
158
+ }
159
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@likec4/language-server",
3
3
  "description": "LikeC4 Language Server",
4
- "version": "1.46.0",
4
+ "version": "1.46.3",
5
5
  "license": "MIT",
6
6
  "bugs": "https://github.com/likec4/likec4/issues",
7
7
  "homepage": "https://likec4.dev",
@@ -21,7 +21,7 @@
21
21
  "directory": "packages/language-server"
22
22
  },
23
23
  "engines": {
24
- "node": "^20.19.0 || >=22.18.0"
24
+ "node": ">=22.21.1"
25
25
  },
26
26
  "engineStrict": true,
27
27
  "type": "module",
@@ -76,35 +76,35 @@
76
76
  "access": "public"
77
77
  },
78
78
  "dependencies": {
79
- "@hpcc-js/wasm-graphviz": "1.16.0",
79
+ "@hpcc-js/wasm-graphviz": "1.17.0",
80
80
  "bundle-require": "^5.1.0",
81
- "esbuild": "0.27.0"
81
+ "esbuild": "0.27.1"
82
82
  },
83
83
  "devDependencies": {
84
- "@hono/node-server": "^1.19.6",
84
+ "@hono/node-server": "^1.19.7",
85
85
  "@modelcontextprotocol/sdk": "^1.22.0",
86
86
  "@msgpack/msgpack": "^3.1.2",
87
87
  "@smithy/util-base64": "^4.3.0",
88
88
  "@types/natural-compare-lite": "^1.4.2",
89
- "@types/node": "~22.19.1",
89
+ "@types/node": "~22.19.3",
90
90
  "@types/picomatch": "^4.0.2",
91
91
  "@types/vscode": "^1.106.1",
92
92
  "@types/which": "^3.0.4",
93
- "chokidar": "^4.0.3",
93
+ "chokidar": "^5.0.0",
94
94
  "defu": "^6.1.4",
95
95
  "esm-env": "^1.2.2",
96
- "fast-equals": "^5.3.3",
96
+ "fast-equals": "^5.4.0",
97
97
  "fdir": "6.4.0",
98
98
  "fetch-to-node": "^2.1.0",
99
- "hono": "^4.10.7",
100
- "immer": "^10.2.0",
99
+ "hono": "^4.11.1",
100
+ "immer": "^11.0.1",
101
101
  "indent-string": "^5.0.0",
102
102
  "json5": "^2.2.3",
103
103
  "langium": "3.5.0",
104
104
  "langium-cli": "3.5.2",
105
- "nano-spawn": "^1.0.3",
105
+ "nano-spawn": "^2.0.0",
106
106
  "natural-compare-lite": "^1.4.0",
107
- "oxlint": "1.31.0",
107
+ "oxlint": "1.33.0",
108
108
  "p-debounce": "4.0.0",
109
109
  "p-queue": "8.1.1",
110
110
  "p-timeout": "6.1.4",
@@ -118,7 +118,7 @@
118
118
  "typescript": "5.9.3",
119
119
  "ufo": "1.6.1",
120
120
  "unbuild": "3.5.0",
121
- "vitest": "4.0.15",
121
+ "vitest": "4.0.16",
122
122
  "vscode-jsonrpc": "8.2.1",
123
123
  "vscode-languageserver": "9.0.1",
124
124
  "vscode-languageserver-protocol": "3.17.5",
@@ -126,13 +126,13 @@
126
126
  "vscode-uri": "3.1.0",
127
127
  "which": "^5.0.0",
128
128
  "zod": "^3.25.76",
129
- "@likec4/config": "1.46.0",
130
- "@likec4/core": "1.46.0",
129
+ "@likec4/core": "1.46.3",
131
130
  "@likec4/devops": "1.42.0",
132
- "@likec4/icons": "1.46.0",
133
- "@likec4/layouts": "1.46.0",
134
- "@likec4/log": "1.46.0",
135
- "@likec4/tsconfig": "1.46.0"
131
+ "@likec4/config": "1.46.3",
132
+ "@likec4/icons": "1.46.1",
133
+ "@likec4/layouts": "1.46.3",
134
+ "@likec4/log": "1.46.1",
135
+ "@likec4/tsconfig": "1.46.1"
136
136
  },
137
137
  "scripts": {
138
138
  "typecheck": "tsc -b --verbose",