npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@swagger-api/apidom-ls

v1.0.1

Published

ApiDOM based language service library.

Readme

ApiDOM Language Service (apidom-ls)

The ApiDOM Language Service (apidom-ls) contains the language smarts powering ApiDOM supported languages processing, specifically editing experience.

ApiDOM Language Service APIs adhere to LSP Protocol and are therefore usable via a LSP Server wrapper in a variety of editors and IDEs.

Installation

After prerequisites for installing this package are satisfied, you can install it via npm CLI by running the following command:

 $ npm install @swagger-api/apidom-ls

Supported specifications

The ApiDOM Language Service fully supports the following API specifications:

  • OpenAPI 2.0
  • OpenAPI 3.0.x
  • OpenAPI 3.1.0
  • AsyncAPI 2.x.y

Quick start

Initializing ApiDOM Language Service

import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

The capabilities of the ApiDOM Language Service can be extended by providing custom configuration.

import { DocumentLink } from 'vscode-languageserver-types';
import { TextDocument } from 'vscode-languageserver-textdocument';
import {
  Element,
  MemberElement,
  isStringElement,
} from "@swagger-api/apidom-core";
import { InfoElement } from '@swagger-api/apidom-ns-asyncapi-2';
import { getLanguageService, LinksProvider, config } from '@swagger-api/apidom-ls';
import type {
  LanguageSettings,
  ProviderMode,
  LinksContext,
  LinksProviderResult,
  NamespaceVersion,
} from '@swagger-api/apidom-ls';

// Defining custom Links Provider

class RefLinksProvider implements LinksProvider {
  break(): boolean {
    return false;
  }

  providerMode(): ProviderMode {
    return ProviderMode.REF;
  }

  configure(settings: LanguageSettings): void {}

  async doRefLinks(
    textDocument: TextDocument,
    api: Element,
    currentRefLinks: DocumentLink[],
    linksContext?: LinksContext,
  ): Promise<LinksProviderResult> {
    for (const link of currentRefLinks) {
      if (link.target && link.target.startsWith('https://example.com')) {
        link.target = link.target.replace('example.com', 'github.com');
      }
    }
    return {
      mergeStrategy: MergeStrategy.IGNORE,
      links: [],
    };
  }

  name(): string {
    return 'RefProvider';
  }

  namespaces(): NamespaceVersion[] {
    return [
      {
        namespace: 'asyncapi',
        version: '2.6.0',
      },
    ];
  }
}

// Defining custom validation rules

const metadata = config();
const customMetadata = {
  metadataMaps: metadata.metadataMaps
    ? JSON.parse(JSON.stringify(metadata.metadataMaps))
    : undefined,
  rules: metadata.rules ? JSON.parse(JSON.stringify(metadata.rules)) : undefined,
  tokens: metadata.tokens ? JSON.parse(JSON.stringify(metadata.tokens)) : undefined,
  symbols: metadata.symbols ? JSON.parse(JSON.stringify(metadata.symbols)) : undefined,
  linterFunctions: metadata.linterFunctions,
};

// Defining custom linter functions

const apilintEqualsCustom = (element: Element, expectedValues: string[]) => {
  if (element) {
    if (!isStringElement(element)) {
      return false;
    }

    return expectedValues.includes(toValue(element));
  }

  return true;
};

customMetadata.linterFunctions = {
  asyncapi: {
    apilintEqualsCustom,
  },
};

// Defining custom rules

const camelCaseTitle = {
  name: 'SB-API-052-title',
  description: 'title MUST follow camelCase',
  recommended: true,
  code: 20001,
  source: 'apilint',
  message: 'title MUST follow camelCase',
  given: '$.info.title',
  givenFormat: 'JSONPATH',
  severity: 1,
  linterFunction: 'apilintValueCasing',
  linterParams: ['camel'],
  marker: 'key',
  data: {},
};

const versionEquals = {
  code: 70202,
  source: "apilint",
  message: "version must be equal to one of the specified values",
  severity: 1,
  linterFunction: "apilintEqualsCustom",
  linterParams: ["1.0.0", "2.0.0"],
  given: "$.info.version",
  givenFormat: "JSONPATH",
  marker: "value",
  data: {},
};

customMetadata.rules = {
  asyncapi: {
    lint: [camelCaseTitle, versionEquals],
  },
};

// Defining custom refractor plugins

const refractorPlugin = () => () => ({
  visitor: {
    MemberElement(element: MemberElement) {
      if (
        isStringElement(element.key) &&
        element.key.equals("additionalInfo")
      ) {
        element.value = InfoElement.refract(element.value);
      }
    },
  },
});

// Initializing ApiDOM Language Service with custom configuration

const refLinksProvider = new RefLinksProvider();

const customContext = {
  metadata: customMetadata,
  linksProviders: [refLinksProvider],
  refractorPlugins: {
    'asyncapi-2': [refractorPlugin()],
  }
};

const languageService = getLanguageService(customContext);

Validation

The ApiDOM Language Service can validate the document according to the rules of the given specification and provide a list of detected errors and warnings.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
info:
  title: Example API
components:
  schemas:
    Order:
      type: object
      properties:
        id:
          type: integer
          format: int64
          example: 1
        status:
          type: string
          enum: placed
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const diagnostics = await languageService.doValidation(document);
[
  {
    "range": {
      "start": {
        "line": 0,
        "character": 0
      },
      "end": {
        "line": 0,
        "character": 5
      }
    },
    "message": "should always have a 'channels' section",
    "severity": 1,
    "code": 30102,
    "source": "apilint",
    "data": {
      "quickFix": [
        {
          "message": "add 'channels' section",
          "action": "addChild",
          "snippetYaml": "channels: \n  \n",
          "snippetJson": "\"channels\": {\n  \n  },\n"
        }
      ]
    }
  },
  {
    "range": {
      "start": {
        "line": 1,
        "character": 0
      },
      "end": {
        "line": 1,
        "character": 4
      }
    },
    "message": "should always have a 'version'",
    "severity": 1,
    "code": 70201,
    "source": "apilint",
    "data": {
      "quickFix": [
        {
          "message": "add 'version' field",
          "action": "addChild",
          "snippetYaml": "version: \n  ",
          "snippetJson": "\"version\": \"\",\n    "
        }
      ]
    }
  },
  {
    "range": {
      "start": {
        "line": 14,
        "character": 16
      },
      "end": {
        "line": 14,
        "character": 22
      }
    },
    "message": "enum' value must be an array with unique values",
    "severity": 1,
    "code": 10009,
    "source": "apilint",
    "data": {}
  }
]

Documentation

The ApiDOM Language Service can provide documentation for the symbol at the specified position in the document.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = 'asyncapi: 2.6.0';

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const documentation = await languageService.doHover(document, {
  line: 0,
  character: 3,
});
{
  "contents": {
    "kind": "markdown",
    "value": "***asyncapi***: **asyncApiVersion**\n\n#### [AsyncAPI Version String](https://www.asyncapi.com/docs/reference/specification/v2.6.0#A2SVersionString)\n\nThe version string signifies the version of the AsyncAPI Specification that the document complies to.\nThe format for this string _must_ be `major`.`minor`.`patch`.  The `patch` _may_ be suffixed by a hyphen and extra alphanumeric characters.\n\\\n\\\nA `major`.`minor` shall be used to designate the AsyncAPI Specification version, and will be considered compatible with the AsyncAPI Specification specified by that `major`.`minor` version.\nThe patch version will not be considered by tooling, making no distinction between `1.0.0` and `1.0.1`.\n\\\n\\\nIn subsequent versions of the AsyncAPI Specification, care will be given such that increments of the `minor` version should not interfere with operations of tooling developed to a lower minor version. Thus a hypothetical `1.1.0` specification should be usable with tooling designed for `1.0.0`."
  },
  "range": {
    "start": {
      "line": 0,
      "character": 0
    },
    "end": {
      "line": 0,
      "character": 8
    }
  }
}

Definition location

The ApiDOM Language Service can find the location of the definition referenced at the specified position in the document.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { Position } from 'vscode-languageserver-types';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
channels:
  petstore.inventory.added:
    publish:
      message:
        name: Inventory
        contentType: application/json
        payload:
          "$ref": "#/components/schemas/Inventory"
components:
  schemas:
    Inventory:
      type: object
      additionalProperties:
        type: integer
        format: int64
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const position = Position.create(8, 22);

const location = await languageService.doProvideDefinition(document, {
  textDocument: document,
  position,
});
{
  "uri": "foo://bar/file.yaml",
  "range": {
    "start": {
      "line": 12,
      "character": 6
    },
    "end": {
      "line": 16,
      "character": 0
    }
  }
}

Definition

The ApiDOM Language Service can retrieve the definition of the reference at the specified position in the document.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { Position } from 'vscode-languageserver-types';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
channels:
  petstore.inventory.added:
    publish:
      message:
        name: Inventory
        contentType: application/json
        payload:
          "$ref": "#/components/schemas/Inventory"
components:
  schemas:
    Inventory:
      type: object
      additionalProperties:
        type: integer
        format: int64
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const definition = await languageService.doHover(document, {
  line: 8,
  character: 22,
});
{
  "contents": {
    "kind": "markdown",
    "value": "***$ref***: **string**\n\n\n\n\n\n```yaml\ntype: object\nadditionalProperties:\n  type: integer\n  format: int64\n\n\n```"
  },
  "range": {
    "start": {
      "line": 8,
      "character": 18
    },
    "end": {
      "line": 8,
      "character": 50
    }
  }
}

Completion

The ApiDOM Language Service can provide context-aware completion suggestions for the specified position in the document.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { Position } from 'vscode-languageserver-types';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
info:
  title: Example API
  
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const position = Position.create(3, 2);

const completion = await languageService.doCompletion(document, {
  textDocument: document,
  position,
});
{
  "items": [
    {
      "label": "version",
      "insertText": "version: '$1'",
      "kind": 14,
      "insertTextFormat": 2,
      "documentation": {
        "kind": "markdown",
        "value": "**REQUIRED.** Provides the version of the application API (not to be confused with the specification version)."
      }
    },
    {
      "label": "description",
      "insertText": "description: $1",
      "kind": 14,
      "insertTextFormat": 2,
      "documentation": {
        "kind": "markdown",
        "value": "A short description of the application. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation."
      }
    },
    {
      "label": "termsOfService",
      "insertText": "termsOfService: $1",
      "kind": 14,
      "insertTextFormat": 2,
      "documentation": {
        "kind": "markdown",
        "value": "A URL to the Terms of Service for the API. This MUST be in the form of an absolute URL."
      }
    },
    {
      "label": "contact",
      "insertText": "contact: \n  $1",
      "kind": 14,
      "insertTextFormat": 2,
      "documentation": {
        "kind": "markdown",
        "value": "[Contact Object](https://www.asyncapi.com/docs/reference/specification/v2.6.0#contactObject)\n\\\n\\\nContact information for the exposed API."
      }
    },
    {
      "label": "license",
      "insertText": "license: \n  $1",
      "kind": 14,
      "insertTextFormat": 2,
      "documentation": {
        "kind": "markdown",
        "value": "[License Object](https://www.asyncapi.com/docs/reference/specification/v2.6.0#licenseObject)\n\\\n\\\nLicense information for the exposed API."
      }
    }
  ],
  "isIncomplete": false
}

Reference completion

The ApiDOM Language Service can suggest possible references that can be inserted at the specified position in the document.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { Position } from 'vscode-languageserver-types';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
channels:
  petstore.inventory.added:
    publish:
      message:
        name: Inventory
        contentType: application/json
        payload:
          "$ref": "#/components/schemas/Inventory"
components:
  schemas:
    Inventory:
      type: object
      additionalProperties:
        type: integer
        format: int64
    Category:
      type: object
      properties:
        id:
          type: integer
          format: int64
          example: 1
        name:
          type: string
          example: Dogs
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const position = Position.create(8, 22);

const completion = await languageService.doCompletion(document, {
  textDocument: document,
  position,
});
{
  "items": [
    {
      "label": "#/components/schemas/Category",
      "insertText": "'#/components/schemas/Category$1'",
      "kind": 18,
      "documentation": "type: object\n      properties:\n        id:\n          type: integer\n          format: int64\n          example: 1\n        name:\n          type: string\n          example: Dogs\n",
      "insertTextFormat": 2,
      "sortText": "a",
      "filterText": "\"#/components/schemas/Inventory\"",
      "textEdit": {
        "range": {
          "start": {
            "line": 8,
            "character": 18
          },
          "end": {
            "line": 8,
            "character": 50
          }
        },
        "newText": "'#/components/schemas/Category$1'"
      }
    },
    {
      "label": "#/components/schemas/Inventory/additionalProperties",
      "insertText": "'#/components/schemas/Inventory/additionalProperties$1'",
      "kind": 18,
      "documentation": "type: integer\n        format: int64",
      "insertTextFormat": 2,
      "sortText": "c",
      "filterText": "\"#/components/schemas/Inventory\"",
      "textEdit": {
        "range": {
          "start": {
            "line": 8,
            "character": 18
          },
          "end": {
            "line": 8,
            "character": 50
          }
        },
        "newText": "'#/components/schemas/Inventory/additionalProperties$1'"
      }
    },
    {
      "label": "#/components/schemas/Category/properties/name",
      "insertText": "'#/components/schemas/Category/properties/name$1'",
      "kind": 18,
      "documentation": "type: string\n          example: Dogs\n",
      "insertTextFormat": 2,
      "sortText": "d",
      "filterText": "\"#/components/schemas/Inventory\"",
      "textEdit": {
        "range": {
          "start": {
            "line": 8,
            "character": 18
          },
          "end": {
            "line": 8,
            "character": 50
          }
        },
        "newText": "'#/components/schemas/Category/properties/name$1'"
      }
    },
    {
      "label": "#/components/schemas/Category/properties/id",
      "insertText": "'#/components/schemas/Category/properties/id$1'",
      "kind": 18,
      "documentation": "type: integer\n          format: int64\n          example: 1",
      "insertTextFormat": 2,
      "sortText": "e",
      "filterText": "\"#/components/schemas/Inventory\"",
      "textEdit": {
        "range": {
          "start": {
            "line": 8,
            "character": 18
          },
          "end": {
            "line": 8,
            "character": 50
          }
        },
        "newText": "'#/components/schemas/Category/properties/id$1'"
      }
    }
  ],
  "isIncomplete": false
}

Semantic Tokens

The ApiDOM Language Service can provide semantic tokens for the document, enabling context-aware syntax highlighting.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
components:
  schemas:
    Inventory:
      type: object
      additionalProperties:
        type: integer
        format: int64
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const tokens = await languageService.computeSemanticTokens(document);
{
  "data": [
     0,  0, 8, 14, 0,  1,  0, 10, 16,  0, 1, 2,
     7, 18, 0,  1, 4,  9, 23,  0,  1,  6, 4, 3,
    64,  0, 6,  6, 0, 64,  1,  6, 20, 23, 0, 1,
     8,  4, 3, 64, 0,  6,  7,  0, 64,  1, 8, 6,
     3, 64, 0,  8, 5,  0, 64
  ]
}

Dereferencing

The ApiDOM Language Service can dereference the document, replacing the references with their actual definitions.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { Position } from 'vscode-languageserver-types';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
channels:
  petstore.inventory.added:
    publish:
      message:
        name: Inventory
        contentType: application/json
        payload:
          "$ref": "#/components/schemas/Inventory"
components:
  schemas:
    Inventory:
      type: object
      additionalProperties:
        type: integer
        format: int64
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const dereferenced = await languageService.doDeref(document);
"asyncapi": "2.6.0"
"channels":
  "petstore.inventory.added":
    "publish":
      "message":
        "name": "Inventory"
        "contentType": "application/json"
        "payload":
          "type": "object"
          "additionalProperties":
            "type": "integer"
            "format": "int64"
"components":
  "schemas":
    "Inventory":
      "type": "object"
      "additionalProperties":
        "type": "integer"
        "format": "int64"

JSON Pointer Position

The ApiDOM Language Service can find a position in the document corresponding to the given JSON Pointer.

import { TextDocument } from 'vscode-languageserver-textdocument';
import { getLanguageService } from '@swagger-api/apidom-ls';

const apidomContext = {};
const languageService = getLanguageService(apidomContext);

const asyncapiDoc = `asyncapi: 2.6.0
components:
  schemas:
    Inventory:
      type: object
      additionalProperties:
        type: integer
        format: int64
`;

const document = TextDocument.create('foo://bar/file.yaml', 'apidom', 0, asyncapiDoc);

const jsonPointer = '/components/schemas/Inventory';

const position = await languageService.getJsonPointerPosition(document, jsonPointer);
{
  "line": 4,
  "character": 6
}