Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@codingame/monaco-vscode-api
Advanced tools
NPM module that allows to use every part of VSCode, including the monaco editor
npm install vscode@npm:@codingame/monaco-vscode-api
npm install monaco-editor@npm:@codingame/monaco-vscode-editor-api
npm install -D @types/vscode
@codingame/monaco-vscode-api
is installed as an alias to vscode
to be able to run import * as vscode from 'vscode'
, similar to what is done inside a VSCode extension
@codingame/monaco-vscode-editor-api
is installed as an alias to monaco-editor
because it provides the same api as the official monaco-editor
monaco-editor
, as well as this library by default, uses standalone
version or the VSCode services, which are much simpler than the one used in VSCode.
You may want to provide your custom implementations of them. To do so, you can use the initialize
method from vscode/services
.
Also, monaco-editor doesn't provide types for them, so this library exports them.
Example:
import { INotificationService, initialize } from 'vscode/services'
class MyCustomNotificationService implements INotificationService { ... }
await initialize({
get [INotificationService.toString()] () {
return new MyCustomNotificationService(...)
}
})
Additionally, several packages that include the VSCode version of some services (with some glue to make it work with monaco) are published:
Base (included by default): @codingame/monaco-vscode-base-service-override
Monarch:
Host (included by default): @codingame/monaco-vscode-host-service-override
Extensions (included by default): @codingame/monaco-vscode-extensions-service-override
Files (included by default): @codingame/monaco-vscode-files-service-override
file://
files, but also adds the support for lazy loaded extension files. It adds separate memory user files (e.g. config, keybindings), cache files and log filesfile://
filesQuickAccess (included by default): @codingame/monaco-vscode-quickaccess-service-override
Notifications: @codingame/monaco-vscode-notifications-service-override
Dialogs: @codingame/monaco-vscode-dialogs-service-override
Model: @codingame/monaco-vscode-model-service-override
Editor: @codingame/monaco-vscode-editor-service-override
views
and workbench
services. Do not use more than 1 services at the same timeViews: @codingame/monaco-vscode-views-service-override
editor
and workbench
services. Do not use more than 1 service at the same timeConfiguration: @codingame/monaco-vscode-configuration-service-override
Keybindings: @codingame/monaco-vscode-keybindings-service-override
Languages: @codingame/monaco-vscode-languages-service-override
onLanguage:${language}
event (to load VSCode extension listening to those events)Textmate: @codingame/monaco-vscode-textmate-service-override
Themes: @codingame/monaco-vscode-theme-service-override
Snippets: @codingame/monaco-vscode-snippets-service-override
Debug: @codingame/monaco-vscode-debug-service-override
Preferences: @codingame/monaco-vscode-preferences-service-override
Output: @codingame/monaco-vscode-output-service-override
Terminal: @codingame/monaco-vscode-terminal-service-override
Search: @codingame/monaco-vscode-search-service-override
Markers: @codingame/monaco-vscode-markers-service-override
SCM: @codingame/monaco-vscode-scm-service-override
Testing: @codingame/monaco-vscode-testing-service-override
Language detection worker: @codingame/monaco-vscode-language-detection-worker-service-override
Storage: @codingame/monaco-vscode-storage-service-override
LifeCycle: @codingame/monaco-vscode-lifecycle-service-override
Remote agent: @codingame/monaco-vscode-remote-agent-service-override
Refer to vscode_server.md for the server part
Accessibility: @codingame/monaco-vscode-accessibility-service-override
Workspace trust: @codingame/monaco-vscode-workspace-trust-service-override
Extension Gallery: @codingame/monaco-vscode-extension-gallery-service-override
Chat: @codingame/monaco-vscode-chat-service-override
Notebook: @codingame/monaco-vscode-notebook-service-override
Welcome: @codingame/monaco-vscode-welcome-service-override
Walkthrough: @codingame/monaco-vscode-walkthrough-service-override
User data profile: @codingame/monaco-vscode-user-data-profile-service-override
User data sync: @codingame/monaco-vscode-user-data-sync-service-override
Ai: @codingame/monaco-vscode-ai-service-override
Task: @codingame/monaco-vscode-task-service-override
Outline: @codingame/monaco-vscode-outline-service-override
Timeline: @codingame/monaco-vscode-timeline-service-override
Workbench: @codingame/monaco-vscode-workbench-service-override
editor
and views
service. Do not use more than 1 service at the same timeComments
Edit-sessions
Emmet
triggerExpansionOnTab
command for the emmet default extensionInteractive
Issue
Multi diff editor
Performance
Relauncher
Share
Survey
Update
Localization
Set Display Language
command or from the extension gallery extension packs)Secret Storage
secretStorageProvider
)Usage:
import * as vscode from 'vscode'
import { initialize } from 'vscode/services'
import getEditorServiceOverride from '@codingame/monaco-vscode-editor-service-override'
import getConfigurationServiceOverride, { updateUserConfiguration, configurationRegistry } from '@codingame/monaco-vscode-configuration-service-override'
await initialize({
...getEditorServiceOverride((model, input, sideBySide) => {
// Open a new editor here and return it
// It will be called when for instance the user ctrl+click on an import
}),
...getConfigurationServiceOverride()
})
updateUserConfiguration(`{
"editor.fontSize": 12,
"[java]": {
"editor.fontSize": 15,
}
}`)
initialize
can only be called once ( and it should be called BEFORE creating your first editor).
The official monaco-editor
package provides a function to create models: monaco.editor.createModel
.
This method creates a standalone model that cannot be found or used by any VSCode services.
The recommended way is to used the createModelReference
method instead (added on top of the official monaco-editor api) which returns instead a reference to a model.
It has some pros:
To work, it needs the file to exist on the virtual filesystem. It can be achieved either by:
registerFileSystemOverlay
from the files service override, which can be cleaned when not needed anymore (recommended)createModelReference
function, which writes the file content to the virtual filesystem before creating the modelbefore:
import * as monaco from 'monaco-editor'
const model = monaco.editor.createModel(...)
const editor = monaco.editor.create({ model, ... })
...
model.dispose()
editor.dispose()
after:
import * as monaco from 'monaco-editor'
import { RegisteredFileSystemProvider, RegisteredMemoryFile, registerFileSystemOverlay } from '@codingame/monaco-vscode-files-service-override'
const fileUri = monaco.Uri.file(<file uri>);
const fileSystemProvider = new RegisteredFileSystemProvider(false)
fileSystemProvider.registerFile(new RegisteredMemoryFile(fileUri, <file content>))
const overlayDisposable = registerFileSystemOverlay(1, fileSystemProvider)
const modelRef = await monaco.editor.createModelReference(fileUri)
const editor = monaco.editor.create({ model: modelRef.object.textEditorModel })
...
await modelRef.object.save()
...
modelRef.dispose()
editor.dispose()
overlayDisposable.dispose()
createModelReference
return a reference to a model. The value is fetched from the memory filesystem.
The reference can then be disposed, the model will only be disposed if there is no remaining references.
To be able to use the VSCode api directly from your code, you need to import vscode/localExtensionHost
and wait for the services to be initialized.
You will then be able to import it as if you were in a VSCode extension:
import * as vscode from 'vscode'
import 'vscode/localExtensionHost'
const range = new vscode.Range(...)
vscode.languages.registerCompletionItemProvider(...)
You can also register a new extension from its manifest:
import { registerExtension, initialize, ExtensionHostKind } from 'vscode/extensions'
await initialize()
const { registerFileUrl, getApi } = registerExtension({
name: 'my-extension',
publisher: 'someone',
version: '1.0.0',
engines: {
vscode: '*'
},
contributes: {
}
}, ExtensionHostKind.LocalProcess)
registerFileUrl('/file-extension-path.json', new URL('./file-real-path.json', import.meta.url).toString())
const vscode = await getApi()
vscode.languages.registerCompletionItemProvider(...)
VSCode uses a bunch of default extensions. Most of them are used to load the default languages and grammars (see https://github.com/microsoft/vscode/tree/main/extensions).
This library bundles and publishes them and allows to import the ones you want:
import '@codingame/monaco-vscode-javascript-default-extension'
import '@codingame/monaco-vscode-json-default-extension'
...
See the full list
VSCode extensions are bundled as vsix files. This library publishes a rollup plugin (vite-compatible) that allows to load a vsix file.
import vsixPlugin from '@codingame/monaco-vscode-rollup-vsix-plugin'
...
plugins: [
...,
vsixPlugin()
]
import './extension.vsix'
This library also offers the possibility to localize vscode and the extensions in the supported languages. To do so, import one of the following packages before anything else:
@codingame/monaco-vscode-language-pack-cs
@codingame/monaco-vscode-language-pack-de
@codingame/monaco-vscode-language-pack-es
@codingame/monaco-vscode-language-pack-fr
@codingame/monaco-vscode-language-pack-it
@codingame/monaco-vscode-language-pack-ja
@codingame/monaco-vscode-language-pack-ko
@codingame/monaco-vscode-language-pack-pl
@codingame/monaco-vscode-language-pack-pt-br
@codingame/monaco-vscode-language-pack-qps-ploc
@codingame/monaco-vscode-language-pack-ru
@codingame/monaco-vscode-language-pack-tr
@codingame/monaco-vscode-language-pack-zh-hans
@codingame/monaco-vscode-language-pack-zh-hant
⚠️ The language pack should be imported and loaded BEFORE anything else from this library is loaded. Otherwise, some translations would be missing and an error would be displayed in the console. ⚠️
Try it out on https://monaco-vscode-api.netlify.app/
There is a demo that showcases the service-override features. It includes:
From CLI run:
# build monaco-vscode-api (the demo use it as a local dependency)
npm ci
npm run build
# start demo
cd demo
npm ci
npm start
# OR: for vite debug output
npm run start:debug
For the debug feature, also run:
npm run start:debugServer
⚠️ Building monaco-vscode-api is only supported on Linux or Mac. It you use Windows, have a look at WSL ⚠️
Many packages are published with the same version, and almost all of them depend on the @codingame/monaco-vscode-api
main package (with strict version range).
It is VERY important that only a single version of ALL the packages is installed, otherwise weird things can happen.
You can check that npm list vscode
only lists a single version.
Starting from v2, monaco-editor-webpack-plugin can't be used
Here's the alternative for each options:
filename
: it can be configured at the webpack level directlypublicPath
: it can be configured at the webpack level or by hands when redistering the worker in window.MonacoEnvironment
.languages
: Import VSCode language extensions (@codingame/monaco-vscode-xxx-default-extension
) or (@codingame/@codingame/monaco-vscode-standalone-*
). Please obey: VSCode extensions can only be used if themes
and textmate
service overrides are configured and monaco languages can only be used if those two services are not configured (see here for further details).features
: With this lib, you can't remove editor features.globalAPI
: you can set window.MonacoEnvironment.globalAPI
to trueWebpack makes all file go through all matching loaders. This libraries need to load a lot of internals resources, including HTML, svg and javascript files (for default extension codes).
We need webpack to let those file untouched:
Fortunately, all the assets are loaded via the new URL('asset.extension', import.meta.url)
syntax, and webpack provide a way to exclude the file loaded that way: dependency: { not: ['url'] }
see https://webpack.js.org/guides/asset-modules/
This library uses a lot the new URL('asset.extension', import.meta.url)
syntax which is supported by vite
While it works great in build
mode (because rollup is used), there is some issues in watch
mode:
import.meta.url
is not replaced while creating bundles, it is an issue when the syntax is used inside a dependencyThere are workarounds for both:
import.meta.url
by the original module path:import importMetaUrlPlugin from '@codingame/esbuild-import-meta-url-plugin'
{
...
optimizeDeps: {
esbuildOptions: {
plugins: [importMetaUrlPlugin]
}
}
}
Not allowed to load local resource:
errorsThe short version: set up and use a custom webpack config file and add this under module
:
parser: {
javascript: {
url: true,
}
}
See this issue or this StackOverflow answer for more details, and this discussion for more context.
The typescript language features extensions requires SharedArrayBuffer to enable project wide intellisense or only a per-file intellisense is provided.
It requires crossOriginIsolated to be true, which requires assets files to be servers with some specific headers:
same-origin
require-corp
or credentialless
At least thoses files should have the headers:
webWorkerExtensionHostIframe.html
extensionHost.worker.js
If adding those headers is not an options, you can have a look at https://github.com/gzuidhof/coi-serviceworker, but only if you are not using webviews as it introduces problems then.
This project was mainly created to make the implementation of monaco-languageclient more robust and maintainable.
monaco-languageclient uses vscode-languageclient which was built to run inside a VSCode extension. VSCode extensions communicate with the editor via an API they can import into their code.
The VSCode api exports:
The first implementations of monaco-languageclient were using a fake VSCode api implementation. The vscode-languageclient was hacked so the VSCode<->protocol object converters were mainly bypassed, so the fake VSCode api was receiving Language Server Protocol objects. Then the objects were transformed using custom transformers into Monaco objects to communicate with the monaco api.
This approach has some disadvantages:
With this library, it would be possible to plug vscode-languageclient directly on top of monaco, monaco-languageclient still helps to do so by:
FAQs
VSCode public API plugged on the monaco editor
The npm package @codingame/monaco-vscode-api receives a total of 44,976 weekly downloads. As such, @codingame/monaco-vscode-api popularity was classified as popular.
We found that @codingame/monaco-vscode-api demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.