@frenchbaas/js 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +135 -29
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -14,56 +14,136 @@ npm install @frenchbaas/js
14
14
  import { FrenchBaas } from '@frenchbaas/js'
15
15
 
16
16
  const client = new FrenchBaas({
17
- url: 'https://app.frenchbaas.com',
18
- apiKey: 'votre-clé-api',
17
+ url: 'https://api.frenchbaas.fr',
18
+ apiKey: 'votre-clé-api', // trouvée dans Dashboard → Projet
19
19
  })
20
20
  ```
21
21
 
22
+ ---
23
+
22
24
  ## Auth
23
25
 
24
26
  ```js
25
27
  // Inscription
26
- const { user } = await client.auth.signUp({ email: 'a@b.com', password: 'secret' })
28
+ const { user, access_token } = await client.auth.signUp({ email: 'a@b.com', password: 'secret' })
27
29
 
28
30
  // Connexion
29
- const { user } = await client.auth.login({ email: 'a@b.com', password: 'secret' })
31
+ const { user, access_token } = await client.auth.login({ email: 'a@b.com', password: 'secret' })
30
32
 
31
33
  // Déconnexion
32
34
  await client.auth.logout()
33
35
 
34
- // État
36
+ // État de la session
35
37
  client.auth.getUser() // { id, email } | null
36
38
  client.auth.isLoggedIn() // boolean
37
39
  ```
38
40
 
39
- ## Collections (documents)
41
+ ---
42
+
43
+ ## Collections & documents
40
44
 
41
45
  ```js
42
- const col = client.collection('collection-uuid')
46
+ const col = client.collection('uuid-de-la-collection')
43
47
 
44
- // Lire (paginé)
48
+ // Lister (paginé, max 100 par page)
45
49
  const { data, meta } = await col.get({ page: 1, perPage: 20 })
50
+ // meta → { total, page, per_page, total_pages }
46
51
 
47
- // Récupérer un document par son ID
48
- const doc = await col.getById('doc-id')
52
+ // Récupérer un document par ID
53
+ const doc = await col.getById('doc-uuid')
54
+ // doc → { id, data, created_at, updated_at }
49
55
 
50
- // Créer
56
+ // Créer un document
51
57
  const doc = await col.create({ title: 'Hello', published: true })
52
58
 
53
- // Mettre à jour
54
- const doc = await col.update('doc-id', { title: 'Modifié' })
59
+ // Mettre à jour (merge partiel — seuls les champs fournis changent)
60
+ const doc = await col.update('doc-uuid', { title: 'Modifié' })
55
61
 
56
62
  // Supprimer
57
- await col.delete('doc-id')
63
+ await col.delete('doc-uuid')
64
+
65
+ // Schéma de la collection (noms de champs, types, visibilité)
66
+ const { schema } = await col.schema()
67
+ ```
68
+
69
+ ### Visibilité des collections
70
+
71
+ | Visibilité | Lecture | Écriture |
72
+ |------------|---------|---------|
73
+ | `public` | Sans token | Token requis |
74
+ | `authenticated` | Token requis | Token requis |
75
+ | `private` | Créateur uniquement | Créateur uniquement |
76
+
77
+ ### Permissions SDK sur les champs
78
+
79
+ Le développeur peut configurer une permission sur chaque champ d'une collection.
80
+ Ces règles sont appliquées **côté serveur**, de façon transparente pour le SDK.
81
+
82
+ | Permission | Comportement à la création | Comportement à la mise à jour |
83
+ |---|---|---|
84
+ | `writable` | L'utilisateur écrit librement **(défaut)** | Modifiable |
85
+ | `forced` | Remplacé par la valeur définie par le dev | Ignoré (non modifiable) |
86
+ | `inject_user_id` | Injecté automatiquement avec l'ID de l'utilisateur | Ignoré |
87
+ | `inject_user_email` | Injecté automatiquement avec l'email de l'utilisateur | Ignoré |
88
+ | `inject_timestamp` | Injecté automatiquement avec la date/heure serveur | Ignoré |
89
+ | `readonly` | Ignoré (seul le dev peut écrire ce champ) | Ignoré |
90
+
91
+ ```js
92
+ // Même si vous envoyez role: 'admin', le serveur force 'client' si le champ est en mode forced
93
+ await client.collection('users').create({ role: 'admin', email: 'x@x.com' })
94
+ // → { role: 'client', email: 'x@x.com' }
95
+
96
+ // Les champs inject_* n'ont pas besoin d'être envoyés
97
+ await client.collection('orders').create({ total: 99.99 })
98
+ // → { total: 99.99, created_by_email: 'user@example.com' } ← injecté par le serveur
99
+ ```
100
+
101
+ Ces permissions se configurent dans le Dashboard → collection → schéma → colonne **SDK permission**.
102
+
103
+ ---
104
+
105
+ ## Webhooks
106
+
107
+ Si une collection a un `before_create_url` ou `before_update_url` configuré,
108
+ FrenchBaas appelle votre endpoint **avant chaque écriture en base**.
109
+ Votre serveur peut valider, enrichir ou rejeter les données.
110
+
111
+ Un rejet lève automatiquement une `ValidationError` côté SDK avec le message
112
+ renvoyé par votre webhook.
58
113
 
59
- // Schéma de la collection
60
- const schema = await col.schema()
114
+ ```js
115
+ import { ValidationError } from '@frenchbaas/js'
116
+
117
+ try {
118
+ await client.collection('col-uuid').create({ montant: 150 })
119
+ } catch (e) {
120
+ if (e instanceof ValidationError) {
121
+ // e.message contient le message renvoyé par votre webhook
122
+ // ex : "Stock insuffisant", "Utilisateur banni", etc.
123
+ console.error('Rejeté par le webhook :', e.message)
124
+ }
125
+ }
126
+
127
+ // Même comportement pour update()
128
+ try {
129
+ await client.collection('col-uuid').update('doc-uuid', { montant: 200 })
130
+ } catch (e) {
131
+ if (e instanceof ValidationError) {
132
+ console.error('Mise à jour refusée :', e.message)
133
+ }
134
+ }
61
135
  ```
62
136
 
137
+ > La configuration des webhooks (URL, secret HMAC) se fait dans le Dashboard
138
+ > ou via l'API REST. Voir la [documentation webhooks](https://frenchbaas.fr/documentation.html#webhooks).
139
+
140
+ ---
141
+
63
142
  ## Gestion des erreurs
64
143
 
65
144
  ```ts
66
145
  import {
146
+ FrenchBaasError,
67
147
  AuthError,
68
148
  ValidationError,
69
149
  NotFoundError,
@@ -74,29 +154,54 @@ import {
74
154
  } from '@frenchbaas/js'
75
155
 
76
156
  try {
77
- await client.collection('col-id').create({ title: 'Test' })
157
+ await client.collection('col-uuid').create({ title: 'Test' })
78
158
  } catch (e) {
79
- if (e instanceof AuthError) console.error('Non connecté ou session expirée')
80
- if (e instanceof ValidationError) console.error('Données invalides', e.errors)
81
- if (e instanceof NotFoundError) console.error('Introuvable')
82
- if (e instanceof QuotaError) console.error('Quota dépassé')
83
- if (e instanceof RateLimitError) console.error('Trop de requêtes, réessayez dans quelques instants')
84
- if (e instanceof NetworkError) console.error('Hors ligne')
85
- if (e instanceof ServerError) console.error('Erreur interne du serveur')
159
+ if (e instanceof ValidationError) {
160
+ // Données invalides (schéma) OU rejet par webhook
161
+ // e.errors string[] (erreurs de schéma)
162
+ // e.message message du webhook si rejet webhook (e.errors sera vide)
163
+ console.error(e.message, e.errors)
164
+ }
165
+ else if (e instanceof AuthError) console.error('Non connecté ou session expirée')
166
+ else if (e instanceof NotFoundError) console.error('Document ou collection introuvable')
167
+ else if (e instanceof QuotaError) console.error('Quota dépassé :', e.message)
168
+ else if (e instanceof RateLimitError) console.error('Trop de requêtes, réessayez dans quelques instants')
169
+ else if (e instanceof NetworkError) console.error('Impossible de joindre le serveur')
170
+ else if (e instanceof ServerError) console.error('Erreur interne du serveur')
171
+ else if (e instanceof FrenchBaasError) console.error('Erreur FrenchBaas :', e.message)
86
172
  }
87
173
  ```
88
174
 
175
+ Toutes les erreurs héritent de `FrenchBaasError` et exposent :
176
+ - `e.message` — description lisible
177
+ - `e.status` — code HTTP (401, 404, 422, 429, 5xx…)
178
+
179
+ `ValidationError` expose en plus :
180
+ - `e.errors` — tableau de messages de validation (vide si rejet webhook)
181
+
182
+ ---
183
+
89
184
  ## Options
90
185
 
91
186
  ```js
92
- // Persister la session dans localStorage (rechargement de page)
93
187
  const client = new FrenchBaas({
94
- url: 'https://app.frenchbaas.com',
188
+ url: 'https://api.frenchbaas.fr',
95
189
  apiKey: 'votre-clé-api',
96
- storage: 'localStorage', // défaut : 'memory'
190
+ storage: 'localStorage', // 'memory' (défaut) | 'localStorage'
97
191
  })
98
192
  ```
99
193
 
194
+ | Option | Type | Défaut | Description |
195
+ |--------|------|--------|-------------|
196
+ | `url` | `string` | — | URL de votre instance FrenchBaas |
197
+ | `apiKey` | `string` | — | Clé API du projet (Dashboard → Projet) |
198
+ | `storage` | `'memory'` \| `'localStorage'` | `'memory'` | Persistance de la session |
199
+
200
+ Utilisez `localStorage` pour que la session survive au rechargement de page
201
+ (applications web). Utilisez `memory` pour les environnements serveur (Node.js).
202
+
203
+ ---
204
+
100
205
  ## Fonctionnalités automatiques
101
206
 
102
207
  - **Refresh token transparent** — access token rafraîchi automatiquement avant expiration
@@ -104,9 +209,10 @@ const client = new FrenchBaas({
104
209
  - **Déduplication** — plusieurs requêtes simultanées ne déclenchent qu'un seul refresh
105
210
  - **Erreurs typées** — chaque erreur HTTP a sa classe TypeScript dédiée
106
211
  - **Zero dépendance** — aucune dépendance runtime
107
- - **TypeScript** — types inclus
212
+ - **TypeScript natif** — types `.d.ts` inclus, autocomplétion complète
213
+
214
+ ---
108
215
 
109
216
  ## License
110
217
 
111
218
  MIT
112
- # frenchbaas-js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frenchbaas/js",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "SDK JavaScript officiel pour FrenchBaas",
5
5
  "author": "FrenchBaas",
6
6
  "license": "MIT",