dp-command
v1.2.1
Published
CLI for interacting with APIs
Downloads
2
Readme
dp
Use your terminal to interact with APIs. Any API.
Index
Motivation
The problem
Interacting with an API as an admin can be sometimes hard or not user-friendly. You might have a web app for users, but no UI for amdin features.
Building a UI only for few admin features is not worth it.
So, how do you end up interacting with the admin API? Using Postman, curl, browser...
The solution
dp
is a tool to interact with any API. Ideally, these API endpoints can be configured to work with dp
,
keeping in mind it is a CLI tool.
💡 You can design API endpoints to work with dp
With dp
, you can have access to different APIs, configure the command you will use and the token.
Installation
You can install the dp
command using the following command:
npm i -g dp-command@latest
Usage
Add an instance
To add an API, use the following command:
dp add
You will be prompted to add the name and endpoint of the API.
The name will be used to access that instance. For example, you will be able to use:
dp <your-app-name> health
This will make a GET
request to <your-endpoint>/health
.
Edit an instance
You can edit an instance using:
dp update <your-app-name> [--name=NAME] [--endpoint=ENDPOINT] [--token=TOKEN] [--remote-code-execution={0|1}]
Delete an instance
You can delete an instance using:
dp rm <your-app-name>
List all instances
You can list all instances using the following command. It will be printed as a table.
dp ls
Delete all instances
If you need to do a factory reset you can use the following command to delete the dp
configuration:
dp delete-configuration
API design
Base path
Since the API design for using dp
is specific for this goal, you might want to separate these endpoints
from your main API. You can create your dp
endpoints inside a path, such as https://api.example.com/dp
Configure your instance endpoint (Edit an instance)
Tokens
dp
can send tokens on the requests made to APIs. It will use the header Authorization
and will use a Bearer
token.
Configure your instance token (Edit an instance)
Requests
All requests will use the GET
or POST
methods. The POST
method will be used when the API returns a prompt.
The API endpoints will be built based on the command given.
dp <your-app-name> users john-doe shadowban --hours=5
turns into:
GET <your-endpoint>/users/john-doe/shadowban?hours=5
With this in mind, you can reorder your API organization to make the command feel more natural:
dp <your-app-name> shadowban john-doe --hours=5
turns into:
GET <your-endpoint>/shadowban/john-doe?hours=5
POST method
The POST
method will be used when dp
submits a prompt to the API. The endpoint path will be same, with the same query parameters, but it will include a body too.
User Agent
The requests made through dp
will include a User-Agent
header with the value dp-command / <VERSION>
.
<VERSION>
is the npm package version. So, for version 1.0.2
, the User-Agent
would be dp-command / 1.1.0
.
Format
Ideally, the API should return the responses in JSON
. This way, dp
can parse and execute logic based on the returned data.
If dp
can't parse the JSON
, it will return the response as text.
Errors
When the API wants to return an error, it can return a JSON
with the following formats:
{ "error": { "message": "ERROR_MESSAGE" } }
{ "success": false }
The first example will throw an error and print "ERROR_MESSAGE" on the terminal
Interaction with terminal
The API can interact with the terminal by returning these kind of elements. You can combine all the elements in the same API response.
Message
Make a message appear in the terminal:
{ "message": "Hello world" }
This will print "Hello world" in the terminal.
Table
Make a table appear in the terminal:
{ "table": {
"content": [
{ "Header": "content", "Header 2": "content" },
{ "Header": "content", "Header 2": "content" }
]
}}
You can make the table vertical using:
{ "table": {
"vertical": true,
"content": [
{ "Name": "John"},
{ "Surname": "Doe"}
]
}}
Prompt
The API can send a form/prompt to be submitted from the terminal. These are the different options for creating prompts:
{ "prompt": [
{
"type": "text",
"name": "name",
"title": "Name",
"placeholder": "Please write a name"
},
{
"type": "password",
"name": "code",
"title": "Secret code"
},
{
"type": "confirm",
"name": "public",
"title": "Make user public"
},
{
"type": "select",
"name": "user_type",
"title": "User type",
"options": [
{ "value": "admin", "label": "Admin" },
{ "value": "user", "label": "User" },
]
},
{
"type": "hidden",
"name": "process",
"value": "create_user"
}
]}
After all the prompts are completed, dp
will send back the answers to the same endpoint, but using the POST
method and attaching the answers as the body of the request.
Prompt flow example
1. The user executes a command
dp <your-app-name> register-user
2. A request is made to the API
GET <your-endpoint>/register-user
3. The API responds
{ "prompt": [
{
"type": "text",
"name": "username",
"title": "Username",
"placeholder": "A good username"
}
]}
4. dp
prompts a question to the user
Username:
> john-doe
5. The user submits the question
6. dp
sends the result to the API
POST <your-endpoint>/register-user
{ "username": "john-doe" }
7. The API responds
{ "message": "User created" }
8. dp
shows the user the message sent by the API
User created
Command
The API can send a command to be executed in the user's terminal. For doing so, the user needs to have the instance configured to execute commands.
dp update <your-app-name> --remote-code-execution=1
The API has to respond the following to execute a command:
{ "command": "ls -l" }
If the user hasn't configured the instance to execute the command, it will print the command in the terminal.
Token
The API can set user's instance token. Useful for when creating a login flow using dp
or to log out.
{ "token": "95687afb5d9a2a9fa39038f991640b0c" }
You will be able to use:
dp <your-app-name> login
// API can return a prompt for username and password and then, if correct, return a token
and
dp <your-app-name> logout
// API can return an empty token to remove user's local token
Example
For this example, we will be using npoint.io to host our server response.
Our endpoint is https://api.npoint.io/383cab3939da2e10034e.
To make it work, you need to follow the next steps:
1. Create an instance
dp add
For the name, use example
, for the endpoint use https://api.npoint.io
2. (Optional) Make the code executable
dp update example --remote-code-execution=1
3. Execute the "command"
dp example 383cab3939da2e10034e
This will return a message, a table, a prompt, and execute a command (ls
).
Content of https://api.npoint.io/383cab3939da2e10034e:
{
"message": "Hey! This is a test",
"table": {
"content": [
{
"Name": "John",
"Surname": "Doe",
"Email": "[email protected]"
},
{
"Name": "Jane",
"Surname": "Doe",
"Email": "[email protected]"
}
]
},
"prompt": [
{
"type": "text",
"name": "name",
"title": "Name",
"placeholder": "Please write a name"
},
{
"type": "password",
"name": "code",
"title": "Secret code"
},
{
"type": "confirm",
"name": "public",
"title": "Make user public"
},
{
"type": "select",
"name": "user_type",
"title": "User type",
"options": [
{
"value": "admin",
"label": "Admin"
},
{
"value": "user",
"label": "User"
}
]
}
],
"command": "ls"
}
Aliases
For faster typing, you can create an alias to your dp
instance.
For example, instead of using
dp <your-app-name> orders ls
you can use:
<your-app-name> orders ls
This can be done creating an alias. Edit your ~/.bashrc
file and add the following line:
alias <your-app-name>="dp <your-app-name>"
People
The original author of dp
is itaibo
You can contribute too!