feat: initial commit

This commit is contained in:
2023-02-09 12:16:36 +01:00
commit 26d6ac24a2
125 changed files with 11291 additions and 0 deletions

View File

@ -0,0 +1,3 @@
# API Client
> `TODO`

104
doc/apps/my-first-app.md Normal file
View File

@ -0,0 +1,104 @@
# Créer ma première application
## 1. Télécharger le CLI
1. Se rendre à l'adresse https://forge.cadoles.com/arcad/edge/releases
2. Télécharger la dernière version du binaire `cli` disponible dans la page.
## 2. Créer l'arborescence de son application
L'arborescence d'une "Edge App" doit correspondre à une structure prédéfinie.
```bash
my-app
|-> manifest.yml # Le fichier "manifeste" décrivant votre application
|-> public # Répertoire contenant tous les fichiers accessibles publiquement
|-> server
|-> main.js # Le point d'entrée pour le code "serveur" de votre application
```
## 3. Compléter le fichier `manifest.yml`
Ce fichier est le manifeste de votre application. Il permet au serveur d'identifier celle ci et de récupérer des informations la concernant.
```yaml
---
# L'identifiant de votre application. Il doit être globalement unique.
# Un identifiant du type nom de domaine inversé est en général conseillé (ex: tld.mycompany.myapp)
id: tld.mycompany.myapp
# Le titre de votre application.
title: My App
# Les mots-clés associés à votre applications.
tags: ["chat"]
# La description de votre application.
# Vous pouvez utiliser la syntaxe Markdown pour la mettre en forme.
description: |>
A simple demo application
```
## 4. Créer la page d'accueil
Créer le fichier `my-app/public/index.html`:
```html
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>My App</h1>
<!-- Inclure le SDK -->
<script type="text/javascript" src="/edge/sdk/client.js"></script>
<script type="text/javascript">
// On utilise le SDK via la variable globale "Edge"
// pour se connecter au serveur de notre application.
Edge.connect().then(() => {
// Une fois connecté, on envoie un message au serveur.
Edge.send({ "hello": "world" });
});
// On écoute les messages en provenance du serveur.
Edge.addEventListener("message", (evt) => {
console.log("New server message", evt.detail)
});
</script>
</body>
</html>
```
## 5. Créer le fichier `server/main.js`
Ce fichier est nécessaire, même vide.
```javascript
// La fonction "onInit()" (si déclarée) est automatiquement
// exécutée au démarrage du serveur de votre application.
function onInit() {
}
// La fonction "onClientMessage(message)" est automatiquement
// exécutée quand le serveur de votre application reçoit un
// message en provenance du client.
function onClientMessage(message) {
console.log(message);
// On utilise le module "net" pour renvoyer un message au client
net.send({ "my": "message" });
}
```
## 6. Exécuter votre application en local
Utiliser le CLI téléchargé préalablement pour lancer votre nouvelle application localement.
```bash
cli app run -p ./chemin/vers/app
```
La page d'accueil devrait être accessible à l'adresse http://localhost:8080.

3
doc/apps/package-app.md Normal file
View File

@ -0,0 +1,3 @@
# Empaqueter une application
> `TODO`

View File

@ -0,0 +1,9 @@
# API Serveur
Listes des modules disponibles côté serveur.
- [`console`](./console.md)
- [`context`](./context.md)
- [`net`](./net.md)
- [`rpc`](./rpc.md)
- [`store`](./store.md)

View File

@ -0,0 +1,3 @@
## Module `console`
> `TODO`

View File

@ -0,0 +1,70 @@
## Module `context`
Ce permet de manipuler les informations de contexte liées à la réception de messages ou à l'utilisation de certains modules.
### `context.new()`
Renvoie un nouveau contexte vide.
#### Arguments
Aucun
#### Valeur de retour
Un nouvel objet de contexte.
#### Usage
```js
var ctx = context.new();
```
### `context.get(ctx, key)`
Récupère la valeur associée à la clé `key` dans le contexte si celle ci existe.
#### Arguments
- `ctx` **context** Contexte duquel extraire la valeur souhaitée
- `key` **string** Clé associé à la valeur à récupérer
#### Valeur de retour
Valeur associée à la clé ou `null`.
#### Usage
```js
function onClientMessage(ctx, message) {
var sessionId = context.get(ctx, "mykey");
console.log(sessionId);
}
```
### `context.SESSION_ID`
Clé permettant de récupérer la clé de session associé au client émetteur du message courant.
#### Usage
```js
function onClientMessage(ctx, message) {
var sessionId = context.get(ctx, context.SESSION_ID);
console.log(sessionId);
}
```
### `context.ORIGINAL_REQUEST`
Clé permettant de récupérer la requête HTTP à l'origine de la connexion du client.
_Cette propriété est utilisée par le module [`auth`](./auth.md) pour récupérer l'utilisateur associé au client._
#### Usage
```js
function onClientMessage(ctx, message) {
var request = context.get(ctx, context.ORIGINAL_REQUEST);
console.log(request);
}
```

View File

@ -0,0 +1,53 @@
## Module `net`
Ce module permet d'envoyer des messages aux clients connectés au serveur.
### `net.send(sessionIdOrContext, data)`
Envoie un message au client connecté au serveur.
#### Arguments
- `sessionIdOrContext` **string|context** Identifiant de session du client ou contexte portant l'identifiant de session du client. Voir la documentation du module [`context`](./context.md).
- `data` **object** Données à envoyer au client
#### Valeur de retour
Aucune
#### Usage
**Côté client**
```js
// Les données envoyées par le serveur sont accessibles
// via la propriété evt.detail.
Edge.on('message', evt => console.log(evt.detail));
Edge.connect();
```
**Côté serveur**
```js
function onInit() {
var ctx = context.background();
net.send(ctx, {"foo", "bar"});
}
```
### `net.broadcast(data)`
Envoie un message à l'ensemble des clients connectés au serveur.
#### Arguments
- `data` **object** Données à envoyer aux clients connectés
#### Valeur de retour
Aucune
#### Usage
Voir usage `net.send()`.

View File

@ -0,0 +1,3 @@
# Module `rpc`
> TODO

View File

@ -0,0 +1,173 @@
## Module `store`
Ce module permet de stocker et récupérer des données structurées ("documents") sur le serveur.
### `store.upsert(ctx, collection, doc)`
Enregistre un document dans une collection.
Si le document a une propriété `_id` celle ci est utilisée comme identifiant. Dans le cas contraire elle sera autogénérée par le moteur de stockage.
#### Arguments
- `ctx` **context** Le contexte d'exécution. Voir la documentation du module [`context`](./context.md)
- `collection` **string** Nom de la collection dans laquelle retrouver le document
- `doc` **object** Le document à enregistrer
#### Valeur de retour
Le document dans sa forme après enregistrement.
#### Usage
```js
var ctx = context.get();
var obj = store.upsert(ctx, "myCollection", {"foo": "bar"});
```
### `store.get(ctx, collection, docId)`
Retourne le document associé à l'identifiant `docId` ou `null` si celui ci n'est pas trouvé.
#### Arguments
- `ctx` **context** Le contexte d'exécution. Voir la documentation du module [`context`](./context.md)
- `collection` **string** Nom de la collection dans laquelle retrouver le document
- `docId` **string** Identifiant du document à récupérer
#### Valeur de retour
le document stocké si il existe, `null` sinon.
#### Usage
```js
function onInit() {
var ctx = context.get();
var obj = store.get(ctx, "myCollection", "doc-id");
}
```
### `store.delete(ctx, collection, docId)`
Supprime le document associé à l'identifiant dans la collection.
#### Arguments
- `ctx` **context** Le contexte d'exécution. Voir la documentation du module [`context`](./context.md)
- `collection` **string** Nom de la collection dans laquelle retrouver le document
- `docId` **string** Identifiant de le document à supprime
#### Valeur de retour
Aucune
#### Usage
```js
var ctx = context.get();
store.delete(ctx, "myCollection", "my-item-id");
```
### `store.query(ctx, collection, doc, filter?, options?)`
Filtre la collection et récupère les documents associés à la requête.
#### Arguments
- `ctx` **context** Le contexte d'exécution. Voir la documentation du module [`context`](./context.md)
- `collection` **string** Nom de la collection dans laquelle retrouver le document
- `filter` **object** Filtre à appliquer à la collection, voir "Filtres".
- `options` **object** Options de filtrage, voir "Options".
##### Filtres
Un filtre se construit à partir d'une hiérarchie d'opérateurs sous la forme d'un document.
On distingue deux types d'opérateurs:
- Les opérateurs de combinaison logique;
- Les opérateurs de filtrage.
Les opérateurs d'combinaison logique prennent la forme suivante:
```
{
"<comb_op>": [
<filter_op>,
<filter_op>,
etc
]
}
```
**Exemple**
```json
{
"and": [
{ "eq": { "myAttr1": "foo" } },
{ "neq": { "myAttr2": "bar" } }
]
}
```
Ce filtre serait traduit en syntaxe SQL en `myAttr1 = "foo" AND myAttr2 != "bar"`.
Voici la liste des opérateurs de combinaison logique:
- `and` - "ET" logique
- `or` - "OU" logique
- `not` - Négation logique
Les opérateurs de filtrage prennent la forme suivantes:
```
{
<filter_op>: {
"key1": "val1",
"key2": "val2",
"key3": "val3",
etc
}
}
```
**Exemple**
```json
{ "gt": { "foo": "bar" } },
```
Voici la liste des opérateurs de filtrage:
- `eq` - Comparaison `==`
- `neq` - Comparaison `!=`
- `gt` - Comparaison `>`
- `gte` - Comparaison `>=`
- `lt` - Comparaison `<`
- `lte` - Comparaison `<=`
- `like` - Comparaison type `LIKE` MySQL/SQLite
- `in` - Comparaison type `IN` MySQL/SQLite
##### Options
#### Valeur de retour
Tableau d'documents correspondant au filtre.
#### Usage
```js
var ctx = context.get();
var results = store.query(ctx, "myCollection", {
eq: {
"foo": "bar",
}
}, {
limit: 10,
offset: 5,
orderBy: "foo",
orderDirection: "asc",
});
```