docs(noco-docs-prev): init commit

Signed-off-by: Wing-Kam Wong <wingkwong.code@gmail.com>
This commit is contained in:
Wing-Kam Wong
2022-04-04 13:07:10 +08:00
parent df9d7624af
commit fe8a016529
41 changed files with 34413 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
---
title: 'Accessing APIs'
description: 'Accessing APIs'
position: 1000
category: 'Developer Resources'
menuTitle: 'Accessing APIs'
---
## REST APIs
- Go to NocoDB Project, click the rightmost button and click ``Copy auth token``.
![image](https://user-images.githubusercontent.com/35857179/126187328-745943f2-c780-4109-b967-1b3f1c4a1dcd.png)
- Click the same button and click ``Swagger APIs Doc``.
![image](https://user-images.githubusercontent.com/35857179/126187534-32c41de9-f17d-4f95-9acc-88aaed044b36.png)
- Select ``Schemes`` and Click ``Authorize``.
![image](https://user-images.githubusercontent.com/35857179/126188482-f3aacabf-dbc5-41a8-a190-9f225347ebd1.png)
- Paste the token you just copy in step 1 and click Authorize
![image](https://user-images.githubusercontent.com/35857179/126188510-b3790348-6809-4182-911a-a4031ace2fd2.png)
## GraphQL APIs
- Go to NocoDB Project, click the rightmost button and click ``Copy auth token``.
![image](https://user-images.githubusercontent.com/35857179/126187624-03ee550d-71eb-499f-ad8b-54e32a94f729.png)
- Click the same button and click ``GraphQL APIs`.
![image](https://user-images.githubusercontent.com/35857179/126187581-22503b8d-f6dd-4a4e-8b12-a475c27354a2.png)
- Click ``REQUEST HEADERS``.
![image](https://user-images.githubusercontent.com/35857179/126188122-1aa7b153-f05a-46fd-953b-751376d708bf.png)
- Paste the token you just copy in step 1.
```json
{
"xc-auth": "YOUR_AUTH_TOKEN"
}
```

View File

@@ -0,0 +1,25 @@
---
title: 'API Tokens'
description: 'API Tokens'
position: 1040
category: 'Developer Resources'
menuTitle: 'API Tokens'
---
## API Tokens
NocoDB allows creating API tokens which allow it to be integrated seamlessly with 3rd party apps.
### Which HTTP Header to use ?
- ```xc-token``` header should be set when invoking the NocoDB APIs with the token.
### How to create a token ?
- ![1](https://user-images.githubusercontent.com/5435402/133734223-49bb1567-6cd2-43e5-bdda-aaccda741070.png)
- ![2](https://user-images.githubusercontent.com/5435402/133734234-5ca542b1-5843-46f7-b97b-9e686c6bf7ac.png)
- ![3](https://user-images.githubusercontent.com/5435402/133734238-33d5bdd0-5c97-4dbe-8e49-744193c3ac20.png)
- ![4](https://user-images.githubusercontent.com/5435402/133734239-7b530235-3352-497b-b23c-3a701290a569.png)
- ![5](https://user-images.githubusercontent.com/5435402/133734241-0f25bbd0-ab92-430a-9987-cc745d5b1b47.png)
- ![6](https://user-images.githubusercontent.com/5435402/133734243-6dc8527e-573d-45e2-8cd8-13a8beea0dfa.png)

View File

@@ -0,0 +1,795 @@
---
title: 'GraphQL APIs'
position: 1020
category: 'Developer Resources'
menuTitle: 'GraphQL APIs'
---
## Features
* Generates GraphQL APIs for **ANY** MySql, Postgres, MSSQL, Sqlite database :fire:
* Serves GraphQL queries irrespective of naming conventions of primary keys, foreign keys, tables etc :fire:
* Support for composite primary keys :fire:
* Usual suspects : CRUD, List, FindOne, Count, Exists, Distinct
* Pagination
* Sorting
* Column filtering - Fields :fire:
* Row filtering - Where :fire:
* Bulk insert, Bulk delete, Bulk read :fire:
* Relations - automatically detected
* Aggregate functions
* More
* Upload single file
* Upload multiple files
* Download file
* Authentication
* Access Control
## API Overview
### Query
| **Resolver** | **Arguments** | **Returns** | **Description** |
|---|---|---|---|
| [TableName**List**](#tablenamelist) | where: String, limit: Int, offset: Int, sort: String | [TableName] | List of table rows |
| [TableName**Read**](#tablenameread) | id:String | TableName | Get row by primary key |
| [TableName**Exists**](#tablenameexists) | id: String | Boolean | Check row exists by primary key |
| [TableName**FindOne**](#tablenamefindone) | where: String | TableName | Find row by where conditions |
| [TableName**Count**](#tablenamecount) | where: String | Int | Get rows count |
| [TableName**Distinct**](#tablenamedistinct) | columnName: String, where: String, limit: Int, offset: Int, sort: String | [TableName] | Get distinct rows based on provided column names |
| [TableName**GroupBy**](#tablenamegroupby) | fields: String, having: String, limit: Int, offset: Int, sort: String | [TableNameGroupBy] | Group rows by provided columns |
| [TableName**Aggregate**](#tablenameaggregate) | columnName: String!, having: String, limit: Int, offset: Int, sort: String, func: String! | [TableNameAggregate] | Do aggregation based on provided column name aggregate function |
| [TableName**Distribution**](#tablenamedistribution) | min: Int, max: Int, step: Int, steps: String, columnName: String! | [distribution] | Get distributed list |
### Mutations
| **Resolver** | **Arguments** | **Returns** | **Description** |
|---|---|---|---|
| [TableName**Create**](#tablenamecreate) | data:TableNameInput | TableName | Insert row into table |
| [TableName**Update**](#tablenameupdate) | id:String,data:TableNameInput | TableName | Update table row using primary key |
| [TableName**Delete**](#tablenamedelete) | id:String | TableName | Delete table row using primary id |
| [TableName**CreateBulk**](#tabelenamecreatebulk) | data: [TableNameInput] | [Int] | Bulk row insert |
| [TableName**UpdateBulk**](#tablenamebulk) | data: [TableNameInput] | [Int] | Bulk row update |
| [TableName**DeleteBulk**](#tablenamedeletebulk) | data: [TableNameInput] | [Int] | Bulk row delete |
### Query params
| **Param** | **Description** | **Default value** |**Example Value**|
|---|---|---|---|
| where | Logical Expression | | `(colName,eq,colValue)~or(colName2,gt,colValue2)` <br />[Usage: Comparison operators](#comparison-operators) <br />[Usage: Logical operators](#logical-operators) |
| limit | Number of rows to get(SQL limit value) | 10 | 20 |
| offset | Offset for pagination(SQL offset value) | 0 | 20 |
| sort | Sort column name, where use `-` as prefix for descending sort | | column_name |
| fields | Required column names in result | * | column_name_1,column_name_2 |
#### Comparison operators
```
eq - '=' - (colName,eq,colValue)
not - '!=' - (colName,not,colValue)
gt - '>' - (colName,gt,colValue)
ge - '>=' - (colName,ge,colValue)
lt - '<' - (colName,lt,colValue)
le - '<=' - (colName,le,colValue)
is - 'is' - (colName,is,true/false/null)
isnot - 'is not' - (colName,isnot,true/false/null)
in - 'in' - (colName,in,val1,val2,val3,val4)
btw - 'between' - (colName,btw,val1,val2)
nbtw - 'not between'- (colName,nbtw,val1,val2)
like - 'like' - (colName,like,%name)
```
#### Example use of comparison operators - complex example
```
PaymentList(where:"(checkNumber,eq,JM555205)~or((amount,gt,200)~and(amount,lt,2000))")
```
#### Logical operators
```
~or - 'or'
~and - 'and'
~not - 'not'
```
## Examples
### TableNameList
<code-group>
<code-block label="Request" active>
```
CountryList {
country_id
country
last_update
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryList": [
{
"country_id": 1,
"country": "Afghanistan",
"last_update": "1139978640000",
"CityCount": 1
},
{
"country_id": 2,
"country": "Algeria",
"last_update": "1139978640000",
"CityCount": 3
},
{
"country_id": 3,
"country": "American Samoa",
"last_update": "1139978640000",
"CityCount": 1
}
]
}
}
```
</code-block>
</code-group>
#### List + where
<code-group>
<code-block label="Request" active>
```
{
CountryList(where:"(country,like,United%)") {
country_id
country
last_update
CityCount
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryList": [
{
"country_id": 101,
"country": "United Arab Emirates",
"last_update": "1139958840000",
"CityCount": 3
},
{
"country_id": 102,
"country": "United Kingdom",
"last_update": "1139958840000",
"CityCount": 8
},
{
"country_id": 103,
"country": "United States",
"last_update": "1139958840000",
"CityCount": 35
}
]
}
}
```
</code-block>
</code-group>
[Usage : comparison operators](#comparison-operators)
#### List + where + sort
<code-group>
<code-block label="Request" active>
```
{
CountryList(where:"(country,like,United%)",sort:"-country") {
country_id
country
last_update
CityCount
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryList": [
{
"country_id": 103,
"country": "United States",
"last_update": "1139958840000",
"CityCount": 35
},
{
"country_id": 102,
"country": "United Kingdom",
"last_update": "1139958840000",
"CityCount": 8
},
{
"country_id": 101,
"country": "United Arab Emirates",
"last_update": "1139958840000",
"CityCount": 3
}
]
}
}
```
</code-block>
</code-group>
#### List + where + sort + offset
<code-group>
<code-block label="Request" active>
```
{
CountryList(where:"(country,like,United%)",sort:"-country",offset:1) {
country_id
country
last_update
CityCount
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryList": [
{
"country_id": 102,
"country": "United Kingdom",
"last_update": "1139958840000",
"CityCount": 8
},
{
"country_id": 101,
"country": "United Arab Emirates",
"last_update": "1139958840000",
"CityCount": 3
}
]
}
}
```
</code-block>
</code-group>
#### List + limit
<code-group>
<code-block label="Request" active>
```
{
CountryList(limit:6) {
country
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryList": [
{
"country": "Afghanistan"
},
{
"country": "Algeria"
},
{
"country": "American Samoa"
},
{
"country": "Angola"
},
{
"country": "Anguilla"
},
{
"country": "Argentina"
}
]
}
}
```
</code-block>
</code-group>
[](#query)
### TableNameRead
<code-group>
<code-block label="Request" active>
```
CountryRead(id:"1") {
country_id
country
last_update
}
```
</code-block>
<code-block label="Response">
```json
"data": {
"CountryRead": {
"country_id": 1,
"country": "Afghanistan",
"last_update": "1139978640000",
"CityCount": 1
}
}
```
</code-block>
</code-group>
[](#query)
### TableNameExists
<code-group>
<code-block label="Request" active>
```
CountryExists(id:"1")
```
</code-block>
<code-block label="Response">
```json
"data": {
"CountryExists": true
}
```
</code-block>
</code-group>
[](#query)
### TableNameFindOne
<code-group>
<code-block label="Request" active>
```
CountryFindOne(where:"(country_id,eq,1)") {
country_id
country
last_update
CityCount
}
```
</code-block>
<code-block label="Response">
```json
"data": {
"CountryFindOne": {
"country_id": 1,
"country": "Afghanistan",
"last_update": "1139978640000",
"CityCount": 1
}
}
```
</code-block>
</code-group>
[](#query)
### TableNameCount
<code-group>
<code-block label="Request" active>
```
CountryCount
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryCount": 109
}
}
```
</code-block>
</code-group>
[](#query)
### TableNameDistinct
<code-group>
<code-block label="Request" active>
```
{
CountryDistinct(columnName:"last_update",limit:3) {
last_update
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryDistinct": [
{
"last_update": "1139958840000"
},
{
"last_update": "1578323893000"
},
{
"last_update": "1578321201000"
}
]
}
}
```
</code-block>
</code-group>
[](#query)
### TableNameGroupBy
<code-group>
<code-block label="Request" active>
```
{
CountryGroupBy(fields:"last_update",limit:1) {
country_id
country
last_update
count
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryGroupBy": [
{
"country_id": null,
"country": null,
"last_update": "1139958840000",
"count": 109
}
]
}
}
```
</code-block>
</code-group>
[](#query)
### TableNameAggregate
<code-group>
<code-block label="Request" active>
```
{
PaymentAggregate(columnName:"amount",func:"min,max,avg,count") {
count
avg
min
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"PaymentAggregate": [
{
"count": 16048,
"avg": 4.200743,
"min": 0
}
]
}
}
```
[](#query)
### TableNameDistribution
<code-group>
<code-block label="Request" active>
```
{
PaymentDistribution (columnName:"amount"){
range
count
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"PaymentDistribution": [
{
"range": "0-4",
"count": 8302
},
{
"range": "5-8",
"count": 3100
},
{
"range": "9-11.99",
"count": 371
}
]
}
}
```
</code-block>
</code-group>
[](#mutations)
### TableNameCreate
<code-group>
<code-block label="Request" active>
```
mutation {
CountryCreate(data: {country: "test"}) {
country_id
country
last_update
CityCount
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryCreate": {
"country_id": 10264,
"country": "test",
"last_update": null,
"CityCount": 0
}
}
}
```
</code-block>
</code-group>
[](#mutations)
### TableNameUpdate
<code-group>
<code-block label="Request" active>
```
mutation {
CountryUpdate(data: {country: "test_new"}, id: "10264") {
country_id
country
last_update
CityCount
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryUpdate": {
"country_id": null,
"country": null,
"last_update": null,
"CityCount": null
}
}
}
```
</code-block>
</code-group>
[](#mutations)
### TableNameDelete
<code-group>
<code-block label="Request" active>
```
mutation {
CountryDelete(id: "10264") {
country_id
country
last_update
CityCount
}
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryDelete": {
"country_id": null,
"country": null,
"last_update": null,
"CityCount": null
}
}
}
```
</code-block>
</code-group>
[](#mutations)
### TableNameCreateBulk
<code-group>
<code-block label="Request" active>
```
mutation {
CountryCreateBulk(data:[{country:"test 2"},{country:"test 3"}])
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryCreateBulk": [
10265
]
}
}
```
</code-block>
</code-group>
[](#mutations)
### TableNameUpdateBulk
<code-group>
<code-block label="Request" active>
```
mutation {
CountryUpdateBulk(data: [{country: "test 2", country_id: 10265}, {country: "test 3", country_id: 10266}])
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryUpdateBulk": [
1,
1
]
}
}
```
</code-block>
</code-group>
[](#mutations)
### TableNameDeleteBulk
<code-group>
<code-block label="Request" active>
```
mutation {
CountryDeleteBulk(data: [{country_id: 10265}, {country_id: 10266}])
}
```
</code-block>
<code-block label="Response">
```json
{
"data": {
"CountryDeleteBulk": [
1,
1
]
}
}
```
</code-block>
</code-group>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
---
title: "Webhooks"
description: "Webhooks"
position: 1030
category: "Developer Resources"
menuTitle: "Webhooks"
---
## Triggers
Webhooks allows user to trigger on certain operations on following database operations
- AFTER INSERT
- AFTER UPDATE
- AFTER DELETE
The triggers will trigger asynchronously without blocking the actual operation.
### Applications/services
| Trigger | Details |
| --------------- | ---------------------------------------------- |
| Email | Send email to certain email addresses |
| Slack | Notify via Slack channel |
| Microsoft Teams | Notify via Microsoft Teams channel |
| Discord | Notify via Discord channel |
| Mattermost | Notify via Mattermost channel |
| Twilio | Send SMS to certain mobile numbers |
| Whatsapp Twilio | Send Whatsapp messages to numbers using Twilio |
| URL | Invoke an HTTP API |
## Accessing Data: Handlebars
The current row data and other details will be available in the hooks payload so the user can use [handlebar syntax](https://handlebarsjs.com/guide/#simple-expressions) to use data.
> We are using [Handlebars](https://handlebarsjs.com/) library to parse the payload internally.
### Example
For a table with column names (id, title, created_at, updated_at).
For INSERT/ UPDATE based triggers, use following handlebars to access corresponding **data** fields.
- {{ **data**.id }}
- {{ **data**.title }}
- {{ **data**.created_at }}
- {{ **data**.updated_at }}
Note that, for Update trigger - all the fields in the ROW will be accessible, not just the field updated.
For DELETE based triggers, **only** {{ data.id }} is accessible representing ID of the column deleted.
For all trigger, following **user** information associated with person trigger can be accessed.
- {{ **user**.id }} : Unique auto incremented NocoDB system value
- {{ **user**.email }} : User E-mail.
- {{ **user**.roles }} : User Role amongst [Owner, Creator, Editor, Commenter, Viewer].
### JSON format
Use {{ json data }} {{ json user }} to dump complete data & user information available in JSON format
### Additional references:
[Handlebar Guide](https://handlebarsjs.com/guide/).
# Application Guide
## Discord
### 1. Create WebHook
- On Discord, open your Server Settings and head into the Integrations tab:
- Click the "Create Webhook" button to create a new webhook!
![Screenshot 2022-02-22 at 1 21 59 PM](https://user-images.githubusercontent.com/86527202/155087088-8f9fd762-9ff9-41a6-aed4-0f22add77fe6.png)
- Choose channel to which this webhook will post to.
- Copy webhook URL
![Screenshot 2022-02-22 at 1 23 18 PM](https://user-images.githubusercontent.com/86527202/155087126-c2cdd7b2-518a-46a5-82a5-aa90fe51a709.png)
(Sample webhook URL: https://discord.com/api/webhooks/945558283756908644/GNUtiGuzfOky6wZ4ce30XuXc1sbPK3Od7EC-4t6hihh5Fovv6oU9OsdT6mGuoL1QlTzj).
Detailed procedure for discord webhook described [here](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks).
### 2. Install Plugin
- Open 'App Store' (under Settings), hover over Discord tile. Click 'Install'.
![Screenshot 2022-02-22 at 11 30 36 AM](https://user-images.githubusercontent.com/86527202/155085257-5bdde1d9-d7b5-471d-bf44-3c3920e7b853.png)
- Provide a name of your choice (not to be confused with Discord Channel name).
- Paste Discord Webhook URL copied from Step (1.) above.
![Screenshot 2022-02-22 at 11 31 21 AM](https://user-images.githubusercontent.com/86527202/155085287-f5e45aab-fd33-4138-a7a9-6eddc6dc140b.png)
### 3. Configure
- Open project, associated table.
- Click 'More' > 'Webhooks'.
![Screenshot 2022-02-22 at 11 16 18 AM](https://user-images.githubusercontent.com/86527202/155085373-f9b438ed-98c3-4fb1-9209-1bb52736a35d.png)
- Click 'Add New Webhook'
![Screenshot 2022-02-22 at 11 18 04 AM](https://user-images.githubusercontent.com/86527202/155085629-2c4260c6-6d0c-490d-bd6e-092cbb9faeb5.png)
- Configure
- **Title**: Name of your choice to identify this Webhook.
- **Event**: Trigger event. Choose between.
- After Insert: Trigger event for new ROW insertion.
- After Update: Trigger event for existing ROW updation.
- After Delete: Trigger event for ROW deletion
- **On Condition**: [Optional] Enable if you wish to associate additional condition/constraint with the trigger configured above.
- **Notification**: Select 'Discord'.
- **Select Discord Channels**: Select from the drop down list, channel name configured in Step (2). Please click on 'Reload' if drop down list is empty.
- **Body**: Message to be posted over Discord channel, via webhooks on trigger of configured event.
- Body can contain plain text &
- Handlebars {{ }}
## Slack
### 1. Create WebHook
- Details to create slack webhook are captured [here](https://api.slack.com/messaging/webhooks)
### 2. Install Plugin
- Procedure remain same as listed for DISCORD channel configuration above
### 3. Configure Webhook
- Procedure remain same as listed for DISCORD channel configuration above
## Microsoft Teams
### 1. Create WebHook
- On Teams, open your channel, click on three-dots menu (far right) and select 'Connectors'
<img width="319" alt="154971352-6912d53b-cf71-4edd-a319-1c85be85f0c5" src="https://user-images.githubusercontent.com/86527202/155095745-91abd708-834f-4f0e-a33c-ac362e60af0f.png">
- Select incoming webhook & click 'Configure'
<img width="442" alt="154971434-0ced97f7-205a-4e2e-8f88-17092cb7771a" src="https://user-images.githubusercontent.com/86527202/155095741-b23ad6b2-1276-46e3-8ada-0d0a871115bb.png">
- Create webhook, Copy webhook URL
![154971683-db16be7f-4f07-4447-8f2e-ac50e133bef8](https://user-images.githubusercontent.com/86527202/155095733-c339a914-5d78-408c-8f1e-9cd75a7783e8.png)
### 2. Install Plugin
- Open 'App Store' (under Settings), hover over 'Microsoft Teams' tile. Click 'Install'.
![Screenshot 2022-02-22 at 7 32 52 PM](https://user-images.githubusercontent.com/86527202/155148122-60844b42-7d2a-4c0f-9778-a5bc4f9c0107.png)
- Provide a name of your choice (not to be confused with Teams Channel name).
- Paste MS Teams Webhook URL copied from Step (1.) above.
<img width="414" alt="154971222-7fe2c25a-d8c6-46b0-ba1e-a05ff1cf6537" src="https://user-images.githubusercontent.com/86527202/155095720-ff1c052c-a4a7-4c10-8f30-d779dac336f3.png">
### 3. Configure
- Open project, associated table.
- Click 'More' > 'Webhooks'.
![Screenshot 2022-02-22 at 11 16 18 AM](https://user-images.githubusercontent.com/86527202/155085373-f9b438ed-98c3-4fb1-9209-1bb52736a35d.png)
- Click 'Add New Webhook'
![Screenshot 2022-02-22 at 11 18 04 AM](https://user-images.githubusercontent.com/86527202/155085629-2c4260c6-6d0c-490d-bd6e-092cbb9faeb5.png)
- Configure
- **Title**: Name of your choice to identify this Webhook.
- **Event**: Trigger event. Choose between.
- After Insert: Trigger event for new ROW insertion.
- After Update: Trigger event for existing ROW updation.
- After Delete: Trigger event for ROW deletion
- **On Condition**: [Optional] Enable if you wish to associate additional condition/constraint with the trigger configured above.
- **Notification**: Select 'Microsoft Teams'.
- **Select Teams Channels**: Select from the drop down list, channel name configured in Step (2). Please click on 'Reload' if drop down list is empty.
- **Body**: Message to be posted over Teams channel, via webhooks on trigger of configured event.
- Body can contain plain text &
- Handlebars {{ }}