Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

4 changes: 4 additions & 0 deletions docs/action/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Action",
"position": 5
}
57 changes: 57 additions & 0 deletions docs/action/http.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
sidebar_position: 2
---

# HTTP

This page shows how you can use the HTTP connection to request or proxy internal APIs.

## Request

```php
<?php

use Fusio\Worker;
use Fusio\Engine;
use Psr\Log\LoggerInterface;

return function(Worker\ExecuteRequest $request, Worker\ExecuteContext $context, Engine\ConnectorInterface $connector, Engine\Response\FactoryInterface $response, Engine\DispatcherInterface $dispatcher, LoggerInterface $logger) {
/** @var \GuzzleHttp\Client $client */
$client = $connector->getConnection('Http');

$resp = $client->request('POST', '/my_api', [
'json' => ['my_payload' => 'foobar']
]);

if ($resp->getStatusCode() !== 200) {
return $response->internalServerError('Could not call internal API');
}

$data = \json_decode((string) $resp->getBody());

return $response->ok($data);
};

```

## Proxy

```php
<?php

use Fusio\Worker;
use Fusio\Engine;
use Psr\Log\LoggerInterface;

return function(Worker\ExecuteRequest $request, Worker\ExecuteContext $context, Engine\ConnectorInterface $connector, Engine\Response\FactoryInterface $response, Engine\DispatcherInterface $dispatcher, LoggerInterface $logger) {
/** @var \GuzzleHttp\Client $client */
$client = $connector->getConnection('Http');

$resp = $client->request('POST', '/my_api', [
'json' => ['my_payload' => 'foobar']
]);

return $response->proxy($resp);
};

```
30 changes: 30 additions & 0 deletions docs/action/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

# Action

An action contains the business logic of your API endpoint. Fusio provides out of the
box predefined actions which handle common tasks like selecting data from a table or
proxy a request to an internal API. You can discover all existing actions at the
[action index](/docs/backend/api/action/).

## Worker

Besides these available actions which can be configured Fusio provides `Worker` actions
which allow you to specify the action logic directly at the backend using a specific
programming language. These worker actions can be used to implement custom backend logic.

![worker_php_designer](/img/action/worker_php_designer.png)

The following pages provide a first insight how you can solve common tasks.

* [SQL](./sql)
* [HTTP](./http)

Take a look at the [PHP API](./php_api) for a complete reference of the internal API.

## Development

Internally every action is always a PHP class which handles the actual logic.
Instead of using the `Worker` actions you can also directly implement your action
as PHP class which implements an `ActionInterface`. Take a look at the
[custom action](/docs/development/custom_action) guide, this is intended for
developers who like to build OOP systems using PHP classes and dependency injection.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# Invoke async action
# Invoke Async Action

Fusio provides an option to execute an action in async mode. This means that if a request arrives at this action the
request gets placed in a queue and will be executed later on in the background. To make an action async you need to
Expand Down
39 changes: 36 additions & 3 deletions docs/concepts/php_api.md → docs/action/php_api.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
sidebar_position: 3
---

# PHP API

Fusio provides a specific PHP-API in every action which can be used to produce a response. This API describes all
Expand Down Expand Up @@ -100,14 +104,43 @@ different kind of services i.e. ElasticSearch, MongoDB, AMQP, etc.
|-------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `getConnection(string/int $connectionId)` | Returns an arbitrary connection to a remote service. It is recommended to use the connection name but you can also use the actual database id of the connection |

The following table shows the connection type mapping:

| Name | Return | Website | Class |
|---------------|----------------------------------------------|----------------------------------------------------|--------------------------------------------------------|
| AMQP | `PhpAmqpLib\Connection\AMQPStreamConnection` | https://github.com/php-amqplib/php-amqplib | `Fusio\Adapter\Amqp\Connection\Amqp` |
| Beanstalk | `Pheanstalk\Pheanstalk` | https://github.com/pda/pheanstalk | `Fusio\Adapter\Beanstalk\Connection\Beanstalk` |
| Elasticsearch | `Elasticsearch\Client` | https://github.com/elastic/elasticsearch-php | `Fusio\Adapter\Elasticsearch\Connection\Elasticsearch` |
| GraphQL | `Fusio\Adapter\GraphQL\ClientInterface` | https://github.com/apioo/fusio-adapter-graphql/ | `Fusio\Adapter\GraphQL\Connection\GraphQL` |
| HTTP | `GuzzleHttp\Client` | http://docs.guzzlephp.org/en/latest/ | `Fusio\Adapter\Http\Connection\Http` |
| Memcache | `Memcache` | https://www.php.net/manual/book.memcache.php | `Fusio\Adapter\Memcache\Connection\Memcache` |
| MongoDB | `MongoDB\Database` | https://github.com/mongodb/mongo-php-library | `Fusio\Adapter\Mongodb\Connection\MongoDB` |
| Redis | `Predis\Client` | https://github.com/predis/predis | `Fusio\Adapter\Redis\Connection\Redis` |
| SMTP | `Symfony\Component\Mailer\Mailer` | https://symfony.com/doc/current/mailer.html | `Fusio\Adapter\Smtp\Connection\Smtp` |
| SOAP | `SoapClient` | https://www.php.net/manual/class.soapclient.php | `Fusio\Adapter\Soap\Connection\Soap` |
| SQL | `Doctrine\DBAL\Connection` | http://www.doctrine-project.org/projects/dbal.html | `Fusio\Adapter\Sql\Connection\Sql` |


### $response

The response factory MUST be used to create a response for an action. It is a factory method which returns a specific
response object. Please always use this factory since this gives us the freedom to change the response implementation.

| Name | Description |
|-------------------------------------------------------|-------------------------------|
| `build(int $statusCode, array $headers, mixed $body)` | Creates a new response object |
| Name | Description |
|---------------------------------------------------------|-------------------------------------------------------------|
| `build(int $statusCode, array $headers, mixed $body)` | Builds a new response object |
| `proxy(Response $response)` | Proxies a response from an internal HTTP request |
| `ok(mixed $body, array $headers = [])` | Builds an ok (200) success response |
| `created(mixed $body, array $headers = [])` | Builds a created (201) success response |
| `accepted(mixed $body, array $headers = [])` | Builds an accepted (202) success response |
| `noContent(array $headers = [])` | Builds a no content (204) success response |
| `badRequest(mixed $body, array $headers = [])` | Builds a bad request (400) client error response |
| `forbidden(mixed $body, array $headers = [])` | Builds a forbidden (403) client error response |
| `notFound(mixed $body, array $headers = [])` | Builds a not found (404) client error response |
| `conflict(mixed $body, array $headers = [])` | Builds a conflict (409) client error response |
| `gone(mixed $body, array $headers = [])` | Builds a gone (410) client error response |
| `internalServerError(mixed $body, array $headers = [])` | Builds an internal server error (500) server error response |
| `notImplemented(mixed $body, array $headers = [])` | Builds a not implemented (501) server error response |

### $processor

Expand Down
103 changes: 103 additions & 0 deletions docs/action/sql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
sidebar_position: 1
---

# SQL

This page shows how you can use the SQL connection to query data from a table.

## Fetch All

```php
<?php

use Fusio\Worker;
use Fusio\Engine;
use Psr\Log\LoggerInterface;

return function(Worker\ExecuteRequest $request, Worker\ExecuteContext $context, Engine\ConnectorInterface $connector, Engine\Response\FactoryInterface $response, Engine\DispatcherInterface $dispatcher, LoggerInterface $logger) {
/** @var \Doctrine\DBAL\Connection $connection */
$connection = $connector->getConnection('System');

$params = [];
$query = 'SELECT id, title, content, insert_date FROM my_table';

$entries = [];
$result = $connection->fetchAllAssociative($query, $params);
foreach ($result as $row) {
$entries[] = [
'id' => (int) $row['id'],
'name' => $row['title'],
'description' => $row['content'],
'insertDate' => $row['insert_date'],
];
}

return $response->ok([
'entries' => $entries,
]);
};

```

## Fetch Assoc

```php
<?php

use Fusio\Worker;
use Fusio\Engine;
use Psr\Log\LoggerInterface;

return function(Worker\ExecuteRequest $request, Worker\ExecuteContext $context, Engine\ConnectorInterface $connector, Engine\Response\FactoryInterface $response, Engine\DispatcherInterface $dispatcher, LoggerInterface $logger) {
/** @var \Doctrine\DBAL\Connection $connection */
$connection = $connector->getConnection('System');

$id = $request->getArguments()->get('id');
if (empty($id)) {
return $response->badRequest('Provided no id');
}

$query = 'SELECT id, title, content, insert_date FROM my_table WHERE id = :id';

$row = $connection->fetchAssociative($query, ['id' => $id]);
if (empty($row)) {
return $response->notFound('Row not found');
}

return $response->ok($row);
};

```

## Insert

```php
<?php

use Fusio\Worker;
use Fusio\Engine;
use Psr\Log\LoggerInterface;

return function(Worker\ExecuteRequest $request, Worker\ExecuteContext $context, Engine\ConnectorInterface $connector, Engine\Response\FactoryInterface $response, Engine\DispatcherInterface $dispatcher, LoggerInterface $logger) {
/** @var \Doctrine\DBAL\Connection $connection */
$connection = $connector->getConnection('System');

$payload = $request->getPayload();

$name = $payload->name ?? null;
if (empty($name)) {
return $response->badRequest('No name provided');
}

$connection->insert('my_table', [
'name' => $name,
]);

return $response->created([
'success' => true,
]);
};

```

16 changes: 8 additions & 8 deletions docs/use_cases/api_gateway/worker.md → docs/action/worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ In case your endpoint needs to execute more complex business logic we provide
a worker system which allows you to implement your business logic in different
programming languages:

* [Java/Groovy](../../backend/api/action/worker-java.md)
* [Javascript](../../backend/api/action/worker-javascript.md)
* [PHP](../../backend/api/action/worker-php.md)
* [Python](../../backend/api/action/worker-python.md)
* [Java/Groovy](../backend/api/action/worker-java.md)
* [Javascript](../backend/api/action/worker-javascript.md)
* [PHP](../backend/api/action/worker-php.md)
* [Python](../backend/api/action/worker-python.md)

## Setup

Expand Down Expand Up @@ -37,7 +37,7 @@ the JavaScript worker will use the `mysql2` package and the Java worker uses the
Please take a look at every worker page, where we list all implementation types,
through this you also know which methods are available:

* [Java/Groovy](../../backend/api/action/worker-java.md)
* [Javascript](../../backend/api/action/worker-javascript.md)
* [PHP](../../backend/api/action/worker-php.md)
* [Python](../../backend/api/action/worker-python.md)
* [Java/Groovy](../backend/api/action/worker-java.md)
* [Javascript](../backend/api/action/worker-javascript.md)
* [PHP](../backend/api/action/worker-php.md)
* [Python](../backend/api/action/worker-python.md)
4 changes: 4 additions & 0 deletions docs/ai/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "AI",
"position": 6
}
25 changes: 25 additions & 0 deletions docs/ai/action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

# Action Agent

The action agent helps you to build custom action business logic.
You can simply describe what you want to build and the agent tries
to generate the fitting action logic. For example we could describe
the following logic:

> Create an action which returns popular composers of the 19th century

For the action agent Fusio has a special view which shows on the right
the generated code in an editor.

![action_agent](/img/ai/action_agent.png)

You can of course send also more messages to improve or fix the generated
code. If you use the "Execute" button Fusio will create/update the action
and execute it and directly return the response of the action.

![action_agent_execute](/img/ai/action_agent_execute.png)

Through this you have an easy feedback loop to work together with the LLM
agent to produce the fitting logic. Internally the agent has access to all
tools regarding connections, and it can also discover the structure of your
database.
24 changes: 24 additions & 0 deletions docs/ai/architect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

# Architect Agent

The architect agent is an agent which helps to build complete operations, it delegates
the generation of the action, schema and database to the sub-agents. This increases the
quality of the output since the architect agent is only responsible to build a high level
blueprint and each sub-agent generates the actual implementation. For example we could
describe the following:

> Create a Twitter like app where users can publish messages, a user can follow other users and each user has a timeline where the messages of each followed user is shown

The LLM then tries to generate all operations to implement the described use case
and shows them as preview on the right s.

![architect_agent](/img/ai/architect_agent.png)

The action, schema and database fields are prompts which are passed to the sub-agents.
It is also possible to select a different sub-agent in case you want to create an agent for your case.
If you click on "Execute" the agent will create all actions, schemas, database and the operations.

![architect_agent_execute](/img/ai/architect_agent_execute.png)

Note the LLM can of course make mistakes and you should see this only as a starting point
to quickly build a first prototype of your app.
16 changes: 16 additions & 0 deletions docs/ai/database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

# Database Agent

The database agent helps to generate a database schema for a relational
database like Postgres or Mysql. In the message you need to describe what
entries you like to persist for example:

> Create a table to store todo entries

The LLM tries to generate the fitting tables and foreign key relations
and shows a preview on the right s.

![database_agent](/img/ai/database_agent.png)

If the schema looks good you can use the "Execute" button to actually
create the schema on the selected connection.
12 changes: 12 additions & 0 deletions docs/ai/general.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

# General Agent

The general agent is a basic agent which tries to help and answer questions about
your Fusio instance. You can ask any kind of question and the agent tries to return
a useful answer for example:

> show me all available operations

The LLM would then use the internal tool to get all operations.

![general_agent](/img/ai/general_agent.png)
Loading
Loading