0.0.29 • Published 2 years ago

@pnmougel/monaco-rest-client v0.0.29

Weekly downloads
-
License
-
Repository
-
Last release
2 years ago

Monaco Rest client

This package provides a rest client for the monaco editor.

Demo

Try the demo

Configuration

You can configure the rest client language with the following options :

paramdefaulttypedescription
validatetruebooleanIf set to false, disable schema validation
allowTrailingCommatruebooleanIf set to false, trailing commas will generate error
schemaDefundefinedobjectAllows to define custom schema. See bellow.
singleRequestfalsebooleanIf true, only a single request is allowed.
allowCommentstruebooleanIf false, comments will generate errors.
openApiSpecundefinedOpenAPIObjectThe OpenApi specification to use
customOptions{}objectCustom options that can be used by custom resolvers
customPathCompletionundefinedCustomPathCompletionResolverFunction used to resolve custom path param
customQueryCompletionundefinedCustomQueryCompletionResolverFunction used to resolve custom query param
customBodyCompletionundefinedCustomBodyCompletionResolverFunction used to resolve custom body param
featuresobjectAllows to disable monaco features. By default, all features are enabled.

Configure the rest client

You can configure the rest client either at startup with the setupRestCLient function.

const options: RestClientOptions = {...}
// At creation
const restClient = setupRestClient(monaco, options)

// Update options
restClient.options = options

When the options are updated, the webworker will also be restarted.

Set configuration option for a specific model

If you have multiple monaco editor in the same page and you want them to have different options, you can use setModelOptions to define custom options for a specific model.

// Setup editor model
const modelUri = 'inmemory://model.json'
const model = monaco.editor.createModel('...', 'rest-client-lang', modelUri);

// Default language options
const restClient = setupRestClient(monaco, {})

// Options that will be used only for the provided model
restClient.setModelOptions(modelUri, {})

Custom completions

You can provide custom function to add custom completions items to the language, for example to propose custom completion of path parameters.

You can define the functions customPathCompletion, customQueryCompletion and customBodyCompletion respectively for the path, query parameter and body contexts

Each of these function must return Promise<CustomCompletionItem[]> or CustomCompletionItem[]. The array can be empty if there is no completion to provide.

export interface CustomCompletionItem {
    // Label displayed in the completion result
    label: string;
    // Optional description for the item
    description?: string;
    // Integer corresponding to the completion icon
    kind: number;
    // Optional type that will be displayed at the right of the label and in the infobox
    type?: string;
}

Custom path completion

const options: RestClientOptions = {
  customPathCompletion: (
    // Name of the path parameter without the surrounding `{` and `}`
    paramName: string,
    // The schema corresponding to the path parameter
    paramSchema: any,
    // The `customOptions` parameter (see below "Provide options to custom completer")
    options: any) => {}
}

Custom body completion

const options: RestClientOptions = {
  customBodyCompletion: (
    // 'key' if the completion corresponds to an object 'key', 'value' otherwise.
    kind: 'key' | 'value',
    // The schema corresponding to completion
    schema: any,
    // Object describing the current endpoint. 
    ctx: CustomBodyCompletionContext,
    // The `customOptions` parameter (see below "Provide options to custom completer")
    options: any) => {}
}

Custom query param completion

const options: RestClientOptions = {
  customQueryCompletion: (
    // 'key' if the completion corresponds to an query param key
    // 'value'  if the completion corresponds to an query param value
    kind: 'key' | 'value',
    // Name of the query key if kind is `key`
    paramName: string,
    // The schema corresponding to completion
    paramSchema: any,
    // The `customOptions` parameter (see below "Provide options to custom completer")
    options: any) => {}
}

Example

const options: RestClientOptions = {
  customPathCompletion: (paramName: string, paramSchema: any, options: any) => {
    if(paramName === 'index') {
      return [{
        label: 'Test 1',
        description: paramSchema.description,
        kind: 1,
      }, {
        label: 'Test 2',
        description: paramSchema.description,
        kind: 2,
      }]
    } else {
      return []
    }
  }
}

Provide options to custom completer

The completion functions will be run in the webworker context, thus you will not be able to access any of your client application context (e.g., window). If you want to pass options to these functions, use the customOptions parameter.

window.serverUrl = 'https://...'

const options: RestClientOptions = {
  customOptions: {
    test: 'https://...'
  },
  customPathCompletion: (paramName: string, paramSchema: any, options: any) => {
    // This will be generate an error at runtome. 
    // `window` is not defined in the webworker context
    fetch(window.serverUrl)
    
    // This will work
    fetch(options.serverUrl)
  }
}

Define custom schema

Instead of allowing the user to write an endpoint (e.g., GET /_search) you can force the language to validate only against a JSON schema. The behavior of the language will then be very similar to the monaco bundled json language.

There is three ways to define a custom schema :

  • Provide the path and method refering to a schema in the specification
/**
 * The schema used for the json will be the schema corresponding of the `GET /_search` endpoint
 */
const options: RestClientOptions = {
  schemaDef: {
    type: 'path',
    path: '_search',
    method: 'GET'
  }
}
  • Provide a ref to a schema in the specification
/**
 * The schema used for the json will be the schema resolved for the ref `#/components/search/Request` in the specification
 */
const options: RestClientOptions = {
  schemaDef: {
    type: 'ref',
    $ref: '#/components/search/Request'
  }
}
  • Provide a completely custom schema not necessarily existing in the specification.
/**
 * The schema used for the json will be the custom schema { type: 'object', properties: {...}}
 */
const options: RestClientOptions = {
  schemaDef: {
    type: 'schema',
    schema: {
      type: 'object',
      properties: {...}
    }
  }
}

Disable monaco features

You can disable specific monaco features using the features parameter.

const options: RestClientOptions = {
  features: {
    // Disable completion
    completionItems: false,
    // Disable tooltip on hover
    hovers: false,
    // Disable folding
    foldingRanges: false,
    // Disable request validation
    diagnostics: false,
    // Disable request formating
    rangeFormatting: false,
    // Disable code lens (e.g., run action)
    codeLens: false,
    // Disable tokenization (if this is disabled, most of the other features are likely to not run correctly)
    tokens: false,
  }
}

Install & usage

To use this package you MUST use monaco-editor-core and not monaco-editor

npm i @pnmougel/monaco-rest-client monaco-editor-core

Webpack config

In the webpack config, add an entry point for the web worker.

module.exports = {
  entry: {
    // Rest client webworker
    'rest-client.worker': '@pnmougel/monaco-rest-client/dist/rest-client.worker.js',
    // Monaco webworker
    'editor.worker': 'monaco-editor-core/esm/vs/editor/editor.worker.js',
    // Other entrypoints
  },
  output: {
    filename: (chunkData) => {
      switch (chunkData.chunk.name) {
        case 'editor.worker':
          return 'editor.worker.js';
        case 'rest-client.worker':
          return "rest-client.worker.js"
        default:
          return '[name].bundle.js'
      }
    },
  },
}

Vue-cli fix

In the optimization.splitChunks.cacheGroups section of your webpack config ensure that the chunks parameter of each entry is either not set or set to async. If you are using vue-cli it is likely to be the case.

You can check the generated webpack config for vue with the command vue inspect.

To fix this behavior enable chainWebpack in vue.config.js

{
  ...
  chainWebpack: config => {
    const splitChunks = config.optimization.get('splitChunks')
    Object.entries(splitChunks.cacheGroups).forEach(([key, value]) => {
      value.chunks = 'async'
    })
    config.optimization.splitChunks(splitChunks)
  }
}

Application setup

Load the webworkers in the entry point of your application and setup the rest client language

import { restClientLanguageId, setupRestClient } from '@pnmougel/monaco-rest-client'
import * as monaco from 'monaco-editor-core'

(window as any).MonacoEnvironment = {
    getWorker: (moduleId: string, label: string) => {
        if (label === restClientLanguageId) {
            return new Worker('./rest-client.worker.js')
        }
        return new Worker('./editor.worker.js')
    },
}

const restClient = setupRestClient(monaco, {
  allowTrailingComma: true,
  openApiSpec: esSpec,
  features: {
    codeLens: true,
  },
  customOptions: {},
  customPathCompletion,
  customBodyCompletion,
})

Enable an open api spec for an editor

import { restClientLanguageId } from '@pnmougel/monaco-rest-client'

const openApiSpec: {
  // Your open api specification
}
const editor = monaco.editor.create(...)
restClient.setOpenApiSpec(openApiSpec, editor.getModel())

Register a query runner

// Register the editor action to run queries
restClient.registerRunQueryAction(editor)
restClient.setQueryRunner(editor.getModel().uri.toString(), (query) => {
  console.log(query)
})

NPM commands

Deploy the package

npm publish
0.0.28

2 years ago

0.0.29

2 years ago

0.0.20

2 years ago

0.0.21

2 years ago

0.0.22

2 years ago

0.0.23

2 years ago

0.0.24

2 years ago

0.0.25

2 years ago

0.0.18

2 years ago

0.0.19

2 years ago

0.0.26

2 years ago

0.0.27

2 years ago

0.0.16

3 years ago

0.0.17

3 years ago

0.0.15

3 years ago

0.0.14

3 years ago

0.0.12

3 years ago

0.0.10

3 years ago

0.0.11

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago

0.0.0

3 years ago