Skip to content

Latest commit

 

History

History
895 lines (692 loc) · 33.3 KB

README.md

File metadata and controls

895 lines (692 loc) · 33.3 KB

RESTool 2.0 (demo)

RESTool Sample App

The best tool in the neighborhood. Managing your RESTful APIs has never been so easy.

RESTool gives you an out of the box UI that connects to your RESTful API with a simple configuration file.

The idea behind it is simple. Given the fact that each entity in your API has a RESTful implementation, RESTool will provide you UI tool for managing these entities in no time by simply editing a configuration file. No front end engineers, no JavaScript, no CSS, no html. Just a simple JSON file.

Live Demo: https://dsternlicht.github.io/RESTool/


What's New in V2?

While RESTool originally was developed with Angular, we decided to rewrite it from scratch and move to React. The main reason we moved to React is the community. Since React is so popular we believe that choosing React over Angular will get a much wider community support.

Some new features and capabilities in V2:

  • From Angular to React & Typescript
  • Full mobile support
  • Cards layout
  • Custom app colors
  • Data path extraction from arrays
  • New & improved design
  • Custom favicon support
  • Custom icons for actions
  • Better error handling in configuration and requests

Getting started

If you only interested in using RESTool on its latest version as a management tool for your RESTful API, read the docs about configuration, deployment, and consuming RESTool from CDN.

If you wish to extend RESTool's functionality and develop on top of it, please go to the development section.


Configuration

One of the best things about RESTool (and the reason we actually built it) is that you don't need to develop anything. Everything is configurable and may be set simply by editing a configuration file (config.json).

The config.json file should be placed in the root folder of the project, alongside with the index.html file.

You can copy ./public/config-sample.json to ./public/config.json and adopt the settings to your liking.

Here's a detailed list of properties you could add to your configuration file (just in case, we added a config-sample.json file you could learn from).

Property Type Required? Description
name string true The name of your app.
pages array true A list of pages in your app, each page will be presented as a separated tab, and will have his own methods and properties.
baseUrl string false Base url of the api. This will prefix the url of all the api methods defined for all pages. This is normally the domain plus a base path. For example: "https://restool-sample-app.herokuapp.com/api"

Note: If different pages use different base urls this should not be used. Instead, you should explicitly define absolute urls for each method.
requestHeaders object false A list of key-value headers you wish to add to every request we're making.

For example:
{ Authentication: 'SECRET_KEY', 'X-USER-ID': 'USER_ID' }.
errorMessageDataPath string[] false The path within an error response object to look for an error message. If multiple are provided, each will be tried in order until a message is found.
unauthorizedRedirectUrl string false Path to navigate to when the api returns a 401 (Unauthorized) error. You can use :returnUrl to pass a return location. For example: "/login/myLoginPage?return=:returnUrl"
favicon string false A URL for you app's favicon.
customStyles object false Custom styles
customLabels object false Custom labels
customLink string false External Link for navigation item (instead of default page app)

Dynamic configuration file

RESTool also support dynamic js configuration file. Just replace the config.json file with config.js file with this content:

export default {
  // Content is the same as the json config file
}

NOTE: In case you're using the build folder, the config.js must be placed in the folder /build/static/js.

Pages

Each page is an object and represents a resource in your API. It should have the following properties:

Property Type Required? Description
name string true The name of the page. This will be presented in the menu.
id string true A unique identifier for the page. RESTool will use it to navigate between pages.
description string false A short description about the page and its usage.
requestHeaders object false A list of key-value headers you wish to add to every request we're making.

For example:
{ Authentication: 'SECRET_KEY', 'X-USER-ID': 'USER_ID' }.
methods object true A list of all methods which are available in your RESTful API.
customActions object[] false A list of extra (non RESTful) endpoints available in your RESTful API. Specifically customActions is a list of PUT or POST method objects.

Read more about custom actions here.
customLabels object false Custom labels

Methods

A method object will tell RESTool how to work with your API. Available methods:

  • getAll
  • getSingle
  • post
  • put
  • delete

Each method has the following common properties (which could be extended specifically for each use case):

Property Type Required? Description
url string true The url for making the request. The url could be either relative or absolute. If a baseUrl is defined then you should only provide a relative path. For example: /users/:id.

The url could contain parameters that will be extracted if needed. For example: https://website.com/users/:id - note that the parameter name in the url should match the one you're returning in your API.
actualMethod string ("get", "put", "post", "delete", "patch") false Since not everyone implements the RESTful standard, if you need to make a 'post' request in order to update an exiting document, you may use this property.
requestHeaders object false Same as above, but for specific method.
queryParams array false An array of query parameters fields that will be added to the request.

If your url includes the name of the parameter, it will be used as part of the path rather than as a query parameter. For example if your url is /api/contact/234/address you might make a parameter called contactId then set the url as follows: /api/contact/:contactId/address.

Each query param item is an object. See input fields
fields array false A list of Input fields that will be used as the body of the request.

For the getAll request, the fields will be a list to display fields and will be used to render the main view.

getAll - additional properties

We'll use this request in order to get a list of items from our API. This type of GET request has the following additional properties:


dataPath (string)

Use this field to let RESTool know from where it should extract the data from. For example, if your API is returning the following JSON response:


{
  success: true,
  data: []
}

The dataPath you'll want to use will be data.

If your API returning:


{
  success: true,
  data: {
    created: 1578314296120,
    items: []
  }
}

The dataPath will be data.items.


display (object: { type: "table" | "cards" })

RESTool allows you to control how to output the data. The display object has a type property that will define how to display the data. RESTool supports two display type: "table" and "cards".

{
  "display": {
    "type": "cards"
  },
  ...
}

sortBy (string | string[])

One or more paths to properties in the result object to sort the list by.


pagination (Pagination)

Optional. This allows to handle pagination. See Pagination.


dataTransform (Function | async Function)

Optional. Relevant only when using dynamic (js) config. A function to allow manipulation on the response data. Useful for changing\adding data for display purposes.

Here is an example for adding a new field named wiki to the data:

{
  ...
  "dataTransform": items => items.map(item => Object.assign(item, { wiki: `https://en.wikipedia.org/wiki/${item.name}` }))
}

getSingle

This method will be fired once you hit the edit button on an item in order to get a single item's data. By default, if this method hasn't been set, when editing an item, RESTool will take the raw data from the original getAll request.

An example of a getSingle request:

{
  "url": "/character/:id",
  "dataPath": "data",
  "queryParams": [],
  "requestHeaders": {}
}

dataTransform (Function | async Function)

Optional. Relevant only when using dynamic (js) config. A function to allow manipulation on the response data. Useful for changing\adding data for display purposes.

Here is an example for adding a new field named wiki to the data:

{
  ...
  "dataTransform": item => Object.assign(item, { wiki: `https://en.wikipedia.org/wiki/${item.name}` })
}

post

The post method will be used to create new items in your API resource.

Example:

{
  "url": "/character",
  "fields": [
    {
      "name": "name",
      "label": "Name",
      "type": "text"
    },
    {
      "name": "location",
      "label": "Location",
      "type": "select",
      "options": ["Kings Landing", "Beyond the Wall", "Winterfell"]
    },
    {
      "name": "isAlive",
      "label": "Alive?",
      "type": "boolean"
    }
  ]
}
dataTransform (Function | async Function)

Optional. Relevant only when using dynamic (js) config. A function to allow manipulation on the data before making the request.

Here is an example for transforming an array of ids into an array of objects.

{
  ...
  "dataTransform": (body) => {
    body.character.ids = body.character.ids.map((id) => {
      return {
        id: id,
      }
    })
    return body
  },
  ...
}

put - additional properties

The put method will be used to update an existing item in your API resource.

Example:

{
  "put": {
    "url": "/character/:id",
    "actualMethod": "post",
    "includeOriginalFields": false,
    "fields": [
      {
        "name": "location",
        "label": "Location",
        "type": "select",
        "options": ["Kings Landing", "Beyond the Wall", "Winterfell"]
      },
      {
        "name": "isAlive",
        "label": "Alive?",
        "type": "boolean"
      }
    ]
  }
}
includeOriginalFields (boolean)

When set to true, all fields from the original object are merged and sent in the request body. Default is false.

dataTransform (Function | async Function)

Optional. Relevant only when using dynamic (js) config. A function to allow manipulation on the data before making the request.

Here is an example for transforming an array of ids into an array of objects.

{
  ...
  "dataTransform": (body) => {
    body.character.ids = body.character.ids.map((id) => {
      return {
        id: id,
      }
    })
    return body
  },
  ...
}

delete

The delete method will be used to delete an existing item in your API resource.

Example:

{
  "delete": {
    "url": "/character/:id"
  }
}

Pagination

The pagination property allows you to handle pagination on .

Here's a list of variable names you may change:

Name Value Description
type `'buttons' 'infinite-scroll'`
source 'query' Where the pagination parameters are written to. Only supports query parameters for now.
params object Parameters definition for pagniation purposes. See below.
fields object Definition of informations that will be returned by the API. See below.

The params field has the following properties that all can be defined with a input field

Name Value Required? Description
page object true The parameter definition of the page number.
limit object false The parameter definition of the maximum number of items to be returned by the API.
sortBy object false The parameter definition of the sorting value.
descending object false The parameter definition of the order in which the API should return items. false by default.

The fields field has the following properties that all can be defined with a { dataPath: string } object

Name Value Required? Description
total object False The total of items available on the API endpoint. This will allow RESTool to know when there is no more pages to navigate to.

Custom Actions

A list of extra (non RESTful) endpoints available in your RESTful API. Specifically customActions is a list of PUT or POST method objects. For example this could enable an endpoint like: PUT /users/:id/disable

These use the same format as the method objects defined below.

The default HTTP method used is PUT but this can be overwritten using the actualMethod parameter.

If customActions is not empty then for each action RESTool will generate an action button on each data row.

You may configure the icon of the action by adding an icon property. RESTool uses font-awesome and you may use any icon name you want from their collection.

Here's an example for a configuration of 2 custom actions:

{
  "customActions": [
    {
      "name":"Send Email",
      "url": "/character/:id/sendEmail",
      "actualMethod": "post",
      "icon": "envelope",
      "fields": [
        {
          "name": "id",
          "type": "text",
          "label": "ID",
          "readonly": true
        },
        {
          "name": "title",
          "type": "text",
          "label": "Email Title",
          "required": true
        },
        {
          "name": "body",
          "type": "text",
          "label": "Email Body",
          "required": true
        }
      ]
    },
    {
      "name":"Disable Character",
      "url": "/character/:id/disable",
      "actualMethod": "post",
      "icon": "minus-circle",
      "fields": [
        {
          "name": "id",
          "type": "text",
          "label": "Contact ID",
          "readonly": true
        }
      ]
    }
  ]
}

dataTransform (Function | async Function)

Optional. Relevant only when using dynamic (js) config. A function to allow manipulation on the body data. Useful for changing/adding data before the PUT.

Here is an example for changing payload to literal:

{
  ...
  "dataTransform": item => { return item.value}
}

Custom Styles

The customStyles property allows you to control the look & feel of your RESTool app. The object will contains a vars property where you'll be able to change the deafult colors of RESTool.

Here's a list of variable names you may change:

Name Value Description
appText string Root text color.
appBackground string App background color.
navBackground string Navigation menu background color.
navText string Navigation menu text color.
navItemText string Navigation item text color.
navItemHoverBackground string Navigation item background color on hover event.
navItemActiveBackground string Active navigation item background color.
actionButtonBackground string Action button background color.
actionButtonHoverBackground string Action button background color on hover event.
actionButtonText string Action button text color.
cardBackground string Card background color.
addButtonText string Add button text color.
addButtonBackground string Add button background color.
addButtonHoverBackground string Add button background color. (hover event)
submitButtonText string Submit button text color.
submitButtonBackground string Submit button background color.
submitButtonHoverBackground string Submit button background color. (hover event)

Usage example in config.json file:

{
  ...
  "customStyles": {
    "vars": {
      "appBackground": "#888",
      "navBackground": "#333"
      "navItemHoverBackground": "#454545"
    }
  }
}

Custom Labels

The customLabels property allows you to control the different labels that are shown across the pages of your RESTool app. The object has three fields that contain properties that you can customize: buttons, formTitles and placeholders.

List of variable names you may change within the buttonsproperty:

Name Value Description Default value
addItem string Content of the add button on a page. + Add Item
editItem string Title of the edit button on a row or a card. Edit
deleteItem string Title of the delete button on a row or a card. Delete
clearInput string Title of the clear button on form inputs. Clear
closeForm string Title of the close button in forms. Close
addArrayItem string Title of the add button on arrays inputs in forms. Add Item
submitItem string Content of the submit button on forms.

List of variable names you may change within the formTitles property:

Name Value Description Default value
addItem string Content of the add button on a page. Add Item
editItem string Title of the edit button on a row or a card. Edit Item

List of variable names you may change within the placeholders property:

Name Value Description Default value
object string JSON input placeholder. Enter JSON...
array string JSON array input placeholder. Enter JSON array...
text string Text input placeholder. Enter text...
number string Number input placeholder. 0
color string Color input placeholder. Enter color...
email string Email input placeholder. Enter email...
password string Password input placeholder. Enter password...
date string Date input placeholder. Enter date...
file string File input placeholder. Select file...

List of variable names you may change within the pagination property:

Name Value Description Default value
itemsCount string Label displaying the items count when pagination option is on with type infinite-scroll. Use :currentCountFrom, :currentCountTo and :totalCount to display relevant data anywhere in your custom label. Showing :currentCountFrom-:currentCountTo out of :totalCount items
editItem string Title of the edit button on a row or a card. Edit Item

Usage example in config.json file:

{
  ...
  "customLabels": {
    "buttons": {
      "addItem": "+ New item",
      "editItem": "Modify"
    },
    "formTitles": {
      "addItem": "New item form"
    },
    "placeholders": {
      "color": "Enter color in HEX format..."
    }
  }
}

Display fields

The list of fields you want to present in the main view of the app. Each one is an object and could have the following properties:

Property Type Required? Description
name string true The property name of the field that contains the value in the API result.
type string true This will help RESTool to render the main view. See a list of available type below.
label string false A label that describes the field. Will be presented as table headers in the main view.
dataPath string false Read more about dataPath here.
filterable boolean false Set to true to enable a text control to do simple client-side filtering by values of this field. Can be specified for multiple fields.
truncate boolean false Causes long values to be truncated. By default, truncation is not enabled for fields.
htmlCode string false HTML code to display in a cell. Use {value} to insert item value at this place.
queryShortcut object false A shortcut to add a query parameter to the url. For example, if you have a field called "name" and you want to add a query parameter called "name" with the value of the field, you can set this to "name". Object example: { name: 'search', value: 'name=' }
url string false If the type of the field is set to url, this property can be used to provide a custom URL that receives the value of this field as a parameter. If url is not provided, the value of the field will be the target of the anchor. Example below.

Example for URL field:

fields: [
  {
    "name": "someValue",
    "type": "url",
    "label": "External",
    "url": "https://example.com/products/:someValue"
  }
]

Display field types

Here's a list of available display field types:

  • text - will parse the value as a text
  • url - will render an anchor element with a clickable link
  • image - will render an image from the url
  • colorbox - will render a #RRGGBB hex string as an 80 x 20 pixel colored rectangle, overlaid with the hex color string
  • boolean - will render as a green or red dot

Input fields

A list of fields you want us to send as the body of the request. Each one is an object and could have the following properties:

Property Type Required? Description
name string true The name of the field / parameter to be sent.
label string false A label that describes the field. This will act as a label in RESTool's forms.
dataPath string false Use this field to let RESTool know what is the path of this field in the body of the request. Read more about dataPath here.
type string true Use the type field to define the type of the field. See a list of available type below.
options string[] false Add the options field if you chose a select as a type. This field should contain an array of options to be displayed in the select box.

For example: ["Amazon", "Google", { "display": "Microsoft", "value": "ms" }]
arrayType string false For array field type, you should specify another property called arrayType so RESTool will know how to present & send the data in the POST and PUT methods. Array type could be object or text.
value any false Set a default value to the field.
required boolean false If true, a field will be marked as required on PUT and POST forms.
readOnly boolean false If true, a field will be displayed, but not editable. It's data will still be added to the PUT and POST requests.
placeholder string false Input field placeholder.
accept string false An optional setting for file type inputs. When set, the file input's accept property will perform file type filtering when browsing for files.

For example: { "accept": ".png,.jpeg,image/*" }
useInUrl boolean false If true, a field can be used as a parameter in a PUT url. Otherwise only fields retrieved in the original GET can be used as parameters. It's data will still be added to the PUT request body.
optionSource object false Use the optionSource field to load options for a select box from a REST service. If this is used with options, the items from options will be added to the select box before those fetched from the api. Read more about it here.
multi boolean false If true, select-multi dropdown will allow for multiple selections from a pre-defined list. Make sure defining the right input type first: "type": "select-multi".
selectLimit number unlimited An optional setting for limiting the multiple selections from a pre-defined list.

Input field types

Available options:

  • text - A simple text input (if "type" is not defined, text will be the default).
  • long-text - A larger text input
  • object - An object type of field (will use JSON.stringify() to present it, and will parse on update).
  • encode - If you want the value to be encoded before being sent, use this type. GET All page only.
  • integer - A text box for positive and negative integers.
  • number - A text box for positive and negative floating point numbers.
  • boolean - This will render a checkbox.
  • date - A text box for date format. Falls back to a simple text input on unsupported browsers.
  • email - A text box for an email address. Falls back to a simple text input on unsupported browsers.
  • color - A color selector yielding #RRGGBB hex value strings. Falls back to a simple text input on unsupported browsers.
  • select - This will render a select box. See options and optionSource properties
  • select-multi - This will render a multiselect box by means of multiselect-react-dropdown third-party component.
  • array - Enter multiple values. POST and PUT page only.
  • file - A file-input form element, to upload files as Content-Type: multipart/form-data. All non-file form inputs will be sent as individual string values. The current implementation supports only one file input per form.
  • password - A password text box.
  • note - A plain text note within the other fields. Use note property for text. label is optional.
  • hidden - Set to true if you want the value to be sent but not to be editable.

Option source

Use the optionSource field to load options for a select box from a REST service. If this is used with options, the items from options will be added to the select box before those fetched from the api.

You can use the following properties on the optionSource object:

  • url - url to fetch data from
  • dataPath - let us know where we should take the data from
  • displayPath - property of the object to take the display value from
  • valuePath - property of the object to take the option value from
  • sortBy - one or more properties to sort the objects by
  • queryParamAlias - query parameter alias used in multiselect's onSearch function. Default value is q

For example:

fields: [
  {
    name: "bestFriend",
    label: "Best Friend",
    type: "select",
    optionSource: {
      url: "https://restool-sample-app.herokuapp.com/api/character",
      dataPath: null,
      displayPath: "name",
      valuePath: "id",
      sortBy: ["name"]
    }
  }
]

Multiselect with q as a search query alias (default):

fields: [
  {
    name: "bestFriend",
    label: "Best Friend",
    type: "select-multi",
    multi: true,
    optionSource: {
      url: "https://restool-sample-app.herokuapp.com/api/character",
      dataPath: null,
      displayPath: "name",
      valuePath: "id",
      sortBy: ["name"]
    }
  }
]

Searhcing for Arya keyword results in the following request URL: https://restool-sample-app.herokuapp.com/api/character?q=Arya

Multiselect with custom search query alias:

fields: [
  {
    name: "bestFriend",
    label: "Best Friend",
    type: "select-multi",
    multi: true,
    optionSource: {
      url: "https://restool-sample-app.herokuapp.com/api/character",
      dataPath: null,
      displayPath: "name",
      valuePath: "id",
      sortBy: ["name"]
      queryParamAlias: "friend"
    }
  }
]

Searhcing for Arya keyword results in the following request URL: https://restool-sample-app.herokuapp.com/api/character?friend=Arya


Data path

Use this field to help RESTool understand what's the path to get to the field's value in the raw data. For example, if this is a single result's data:

[
  {
    name: 'Daniel',
    email: '[email protected]',
    details: {
      isAwesome: true,
      numberOfChildrens: 1
    }
  },
  ...
]

And you want to present the numberOfChildrens field in the main view, the data path for this field will be details, and the name should be numberOfChildrens.

dataPath also supports extracting value from an array:

[
  {
    childrens: [
      {
        nickName: 'Spiderman'
      },
      {
        nickName: 'Ironman'
      }
    ]
  },
  ...
]

You may use the following data path to extract the first children's nickName: childrens.0 and the field's name will be nickName.

Another usage of this field is to help RESTool to build up the request body. Let's assume that you want to build the following request body:

{
  name: 'Daniel',
  details: {
    thumbnail: {
    url: 'http://bit.ly/2fqDxfQ'
    }
  }
}

The field name will be url, the type will be text, and the data path will be details.thumbnail. RESTool will build the body of the request dynamically according to the dataPath and name of the field.


Development

Clone RESTool repository to get started.

git clone https://github.com/dsternlicht/RESTool.git
cd RESTool

Install project dependencies by running:

npm i

We used React for developing this awesome tool so no need to install anything globally.

In order to start developing:

  • Make sure you copy the /public/config-sample.json to /public/config.json.
  • Start the mocks server by running npm run server.
  • Start the development server by running npm start.
  • Browse to http://localhost:3000/.
  • The app will automatically reload on changes.

Build

Once you're ready, run npm run build in order build the project. The build artifacts will be stored in the build/ folder. The build folder is the one you want to deploy to your server.


Deploy

  • Copy the build folder with all of its content.
  • Edit the config.json file, and add your configuration.
  • Deploy the build folder to your servers, and make sure you serve the index.html file.
  • Enjoy! 😎

Consume from CDN

Instead of using the build folder, you may also consume RESTool as a script from CDN in an HTML page:

<script src="https://unpkg.com/restool"></script>

In this case you'll want to set a config file directly on the window object:

<script>
  window.RESTool = {
    config: {
      remoteUrl: '{CONFIG_FILE_URL}'
    }
  };
</script>

Full example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>RESTool App</title>
  </head>
  <body>
    <script>
      window.RESTool = {
        config: {
          remoteUrl: '{CONFIG_FILE_URL}'
        }
      };
    </script>
    <script src="https://unpkg.com/restool"></script>
  </body>
</html>

Created By