TypeFox / monaco-languageclient

Repo hosts npm packages for monaco-languageclient, vscode-ws-jsonrpc, monaco-editor-wrapper, @typefox/monaco-editor-react and monaco-languageclient-examples
https://www.npmjs.com/package/monaco-languageclient
MIT License
1.05k stars 178 forks source link

Failed create new MonacoLanguageClient instance | Error: Default api is not ready yet, do not forget to import 'vscode/localExtensionHost' and wait for services initialization #649

Closed cjayashantha closed 5 months ago

cjayashantha commented 5 months ago

browser console error (tried in Chrome and Edge)

core.mjs:6531 ERROR Error: Default api is not ready yet, do not forget to import 'vscode/localExtensionHost' and wait for services initialization
    at Object.get (api.js:25:23)
    at new DidOpenTextDocumentFeature (textSynchronization.js:14:42)
    at MonacoLanguageClient.registerBuiltinFeatures (client.js:1273:30)
    at new _BaseLanguageClient (client.js:270:14)
    at new MonacoLanguageClient (index.js:9:9)
    at _LsService.createLanguageClient (ls.service.ts:61:12)
    at webSocket.onopen [as __zone_symbol__ON_PROPERTYopen] (ls.service.ts:40:37)
    at WebSocket.wrapFn (zone.js:775:39)
    at _ZoneDelegate.invokeTask (zone.js:400:33)
    at core.mjs:18229:55

Trying to connectino to a webscoket in LS server

angular component

constructor(lsService: LsService) {
    this.lsSerice = lsService;
    this.model = monaco.editor.createModel(
      '',
      this.ANGUAGE_ID,
      monaco.Uri.parse(
        `file:///rule-${Math.random()}.${(this.LANGUAGE_EXTENSION)}`
      )
    );
  }

ngOnInit(): void {

    console.log('on component init');

    this.codeEditorInstance = monaco.editor.create(this.monacoEditor.nativeElement, {
      model: this.model,
      value: 'const',
      language: this.LANGUAGE_ID,
    });
    this.lsSerice.initWS();
  }

ls.service.ts

// imports
import { Injectable } from '@angular/core';
import {
  WebSocketMessageReader,
  WebSocketMessageWriter,
  toSocket,
} from "vscode-ws-jsonrpc";
import {CloseAction, ErrorAction, MessageTransports} from "vscode-languageclient";
import {MonacoLanguageClient} from "monaco-languageclient";

// methods

public initWS(){
    try{
      console.log('Initializing WS server')
      this.createWebSocketClient(this.LSP_SERVICE).then(() => {
        console.log('connected')
      });
    }catch (e) {
      console.log(e);
      console.log('------------------');
    }
  }

private createWebSocketClient(url: string) {
    return new Promise((resolve, reject) => {
      const webSocket = new WebSocket(url);

      webSocket.onopen = () => {
        const socket = toSocket(webSocket);
        const reader = new WebSocketMessageReader(socket);
        const writer = new WebSocketMessageWriter(socket);
        const languageClient = this.createLanguageClient({reader, writer});

        languageClient.start();

        resolve(languageClient);

        reader.onClose(() => {
          /**
           * When a WebSocket Connection is Closed, create another WebSocket Monaco Language Client
           */
          this.createWebSocketClient(url);
        });
      };

      webSocket.onerror = (error) => {
        reject(error);
      };
    });
  }

  private createLanguageClient(transports: MessageTransports){
    return new MonacoLanguageClient({  // Error occurs here 
      name: 'LS Language Client',
      clientOptions: {
        documentSelector: ['ls'],
        errorHandler: {
          error: () => ({ action: ErrorAction.Continue }),
          closed: () => ({ action: CloseAction.DoNotRestart }),
        },
      },
      connectionProvider: {
        get: () => {
          return Promise.resolve(transports);
        },
      },
    });
  };

package.json

dependances

"@angular/animations": "^17.3.0",
"@angular/common": "^17.3.0",
"@angular/compiler": "^17.3.0",
"@angular/core": "^17.3.0",
"@angular/forms": "^17.3.0",
"@angular/platform-browser": "^17.3.0",
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"monaco-editor": "^0.44.0",
"monaco-languageclient": "^8.3.1",
"ngx-monaco-editor-v2": "^17.0.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"vscode-languageclient": "^9.0.1",
"vscode-ws-jsonrpc": "^3.3.1",
"zone.js": "~0.14.3"

React version works, only the Angular version is giving error

Thanks in advance

kaisalmen commented 5 months ago

Hi @cjayashantha you need to call initServices, see: https://github.com/TypeFox/monaco-languageclient/blob/main/packages/examples/src/bare/client.ts#L25 You can all it without any config, It ensures the monaco-vscode-api service and localExtensionHost are initialized or just import import 'vscode/localExtensionHost'; as done here: https://github.com/TypeFox/monaco-languageclient/blob/main/packages/examples/src/bare/client.ts#L7

cjayashantha commented 5 months ago

thanks @kaisalmen . this worked.

I referred this post Teaching the Language Server Protocol to Microsoft's Monaco Editor initServices part was missing.

kaisalmen commented 5 months ago

I referred this post Teaching the Language Server Protocol to Microsoft's Monaco Editor

This article is seven years old. The implementation changed substantially in the last two years (see here and here). Core concept described in the port are still valid, though.