Skip to content

Commit 2944e2f

Browse files
committed
refine implementation and tests
1 parent 2d643a2 commit 2944e2f

File tree

5 files changed

+195
-136
lines changed

5 files changed

+195
-136
lines changed

labs/playground1/sqls/artist/artists.sql

Lines changed: 0 additions & 8 deletions
This file was deleted.

labs/playground1/sqls/artist/artists.yaml

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/extension-api-caller/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,33 @@ Allow to call APIs from other sources for VulcanSQL, provided by [Canner](https:
1616
extensions:
1717
api: '@vulcan-sql/extension-api-caller'
1818
```
19+
20+
## Usage
21+
22+
To pass the path parameters:
23+
24+
```sql
25+
{% set a_variable_you_can_define = { "path": { "id": 1 } } %}
26+
SELECT {{ a_variable_you_can_define | rest_api(url='https://dummyjson.com/products/:id') }}
27+
```
28+
29+
To pass the query parameters:
30+
31+
```sql
32+
{% set a_variable_you_can_define = { "query": { "q": "phone" } } %}
33+
SELECT {{ a_variable_you_can_define | rest_api(url='https://dummyjson.com/products/search') }}
34+
```
35+
36+
To issue the POST request:
37+
38+
```sql
39+
{% set a_variable_you_can_define = { "body": { "title": "BMW Pencil" } } %}
40+
SELECT {{ a_variable_you_can_define | rest_api(url='https://dummyjson.com/products/add', method='POST') }}
41+
```
42+
43+
To pass the headers and multiple fields:
44+
45+
```sql
46+
{% set a_variable_you_can_define = { "headers": { "Content-Type": "application/json" }, "body": { "title": "BMW Pencil" } } %}
47+
SELECT {{ a_variable_you_can_define | rest_api(url='https://dummyjson.com/products/add', method='POST') }}
48+
```

packages/extension-api-caller/src/lib/filters/restApiCaller.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
FunctionalFilter,
33
InternalError,
44
createFilterExtension,
5+
getLogger,
56
} from '@vulcan-sql/core';
67

78
import axios from 'axios';
@@ -12,23 +13,49 @@ export const RestApiCallerFilter: FunctionalFilter = async ({
1213
}) => {
1314
if (!args['url']) throw new InternalError('url is required');
1415

15-
const url = args['arg'] && args['arg'] === ':id' ? `${args['url']}/${value}` : args['url'];
16+
const logger = getLogger({
17+
scopeName: 'CORE',
18+
});
19+
let url = args['url'];
1620
const httpMethod = args['method'] || 'get';
21+
1722
let options: any = {
18-
url: url,
1923
method: httpMethod,
20-
params: args['arg'] && args['arg'] !== ':id' ? { [args['arg']]: value } : {},
24+
url,
2125
}
22-
if (args['body']) {
23-
options = {...options, body: JSON.parse(args['body'])}
26+
27+
if ('path' in value) {
28+
for (const key in value['path']) {
29+
url = url.replace(`:${key}`, value['path'][key]);
30+
}
31+
options = {...options, url}
2432
}
25-
if (args['headers']) {
26-
options = {...options, headers: JSON.parse(args['headers'])}
33+
34+
if ('query' in value) {
35+
options = {...options, params: value['query']}
2736
}
2837

29-
const results = await axios(options);
38+
if ('body' in value) {
39+
options = {...options, data: value['body']}
40+
}
3041

31-
return JSON.stringify(results.data);
42+
if ('headers' in value) {
43+
options = {...options, headers: value['headers']}
44+
}
45+
46+
try {
47+
logger.info('API request:', options);
48+
const results = await axios(options);
49+
logger.info('API response:', results.data);
50+
return JSON.stringify(results.data);
51+
} catch (error: any) {
52+
const message = error.response
53+
? `response status: ${error.response.status}, response data: ${JSON.stringify(error.response.data)}`
54+
: `remote server does not response. request ${error.toJSON()}}`;
55+
throw new InternalError(
56+
`Failed to execute API request "${url}" data, ${message}`
57+
);
58+
}
3259
};
3360

3461
export const [Builder, Runner] = createFilterExtension(

0 commit comments

Comments
 (0)