SDK Go et JavaScript PocketBase : Manipulation avancée des données 2026

SDK Go et JavaScript PocketBase : Manipulation avancée des données 2026

Introduction

Dans PocketBase, l'API REST couvre la plupart des besoins quotidiens pour interagir avec vos données. Mais pour des cas plus complexes, comme des hooks personnalisés ou une logique métier avancée, les SDK Go et JavaScript côté serveur entrent en jeu. Ces SDK permettent un accès direct à la base de données SQLite, sans passer par les endpoints HTTP. Vous pouvez exécuter des requêtes SQL brutes, gérer des transactions atomiques, ou manipuler des collections et records de manière programmatique.

Ces outils sont particulièrement utiles pour les startups et PME qui construisent des applications scalables sans équipe backend dédiée. Go offre des performances natives pour des projets gourmands, tandis que JavaScript permet un prototypage rapide sans compilation. Dans cet article, nous explorons l'accès programmatique depuis Go et JS, les méthodes clés comme dao.FindRecordsByFilter(), les transactions, les requêtes SQL, et une comparaison des deux langages. Tout est expliqué pour les débutants, avec des exemples concrets tirés de la documentation officielle.

Accès programmatique depuis Go et JavaScript

Pour utiliser ces SDK, vous devez étendre PocketBase via des hooks ou une application personnalisée. En Go, cela se fait en important le package github.com/pocketbase/pocketbase/core. En JavaScript, c'est via le dossier pb_hooks et la machine virtuelle JSVM.

En Go : Configuration de base

Commencez par créer une application PocketBase personnalisée. Voici un exemple minimal pour accéder à la base de données :

package main

import (
    "log"
    "github.com/pocketbase/pocketbase"
    "github.com/pocketbase/pocketbase/core"
)

func main() {
    app := pocketbase.New()

    // Hook pour accéder à la DB avant le démarrage
    app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
        // Exemple : Accès à une collection
        collection, err := app.FindCollectionByNameOrId("users")
        if err != nil {
            log.Printf("Erreur : %v", err)
            return err
        }
        log.Printf("Collection trouvée : %s", collection.Name)
        return nil
    })

    if err := app.Start(); err != nil {
        log.Fatal(err)
    }
}

Ici, app est l'instance centrale. app.DB() donne accès au builder de requêtes dbx.Builder pour des opérations SQL. Pour les collections et records, utilisez app.FindCollectionByNameOrId() ou app.FindRecordById().

En JavaScript : Via les hooks JSVM

En JS, placez vos scripts dans pb_hooks/. Les globals comme $app et $db sont disponibles. Exemple de hook pour accéder à une collection :

// pb_hooks/onBeforeServe.js
let collection = $app.findCollectionByNameOrId("users");
if (collection) {
    console.log("Collection trouvée : " + collection.name);
}

$app est l'équivalent de app en Go. $app.db() retourne le builder pour SQL. Ces accès sont sécurisés et intègrent les règles d'authentification de PocketBase.

Pour un débutant, commencez par Go si votre projet est en backend pur ; JS si vous préférez la flexibilité sans rebuild.

Gestion des collections avec les SDK

Les collections sont les "tables" de PocketBase. Les SDK permettent de les créer, lire, mettre à jour et supprimer (CRUD) programmatiquement, souvent lors de migrations.

En Go : Opérations sur les collections

Utilisez core.App pour les méthodes principales. Importez github.com/pocketbase/pocketbase/core et github.com/pocketbase/dbx.

  • Récupérer une collection : app.FindCollectionByNameOrId("nom") retourne *core.Collection ou nil avec erreur si non trouvée.

Exemple :

collection, err := app.FindCollectionByNameOrId("users")
if err != nil {
    log.Fatal(err)
}
fmt.Println(collection.Name) // "users"
  • Récupérer plusieurs collections : app.FindAllCollections(types...) filtre par type (e.g., "auth", "view").

Exemple :

collections, err := app.FindAllCollections(core.CollectionTypeAuth)
  • Requête custom : app.CollectionQuery() pour un builder SELECT.

Exemple :

import "github.com/pocketbase/dbx"

collections := []*core.Collection{}
err := app.CollectionQuery().
    AndWhere(dbx.HashExp{"system": true}).
    OrderBy("created DESC").
    All(&collections)
  • Créer une collection : Utilisez core.NewBaseCollection("nom"), ajoutez champs et règles, puis app.Save(collection).

Exemple complet :

import (
    "github.com/pocketbase/pocketbase/core"
    "github.com/pocketbase/pocketbase/tools/types"
)

collection := core.NewBaseCollection("articles")
collection.ViewRule = types.Pointer("@request.auth.id != ''")
collection.Fields.Add(&core.TextField{Name: "title", Required: true})
collection.Fields.Add(&core.RelationField{Name: "user", Required: true, CollectionId: usersCollection.Id})
err := app.Save(collection)
  • Mettre à jour : Chargez, modifiez, sauvegardez.

Exemple :

collection, _ = app.FindCollectionByNameOrId("articles")
collection.DeleteRule = types.Pointer("@request.auth.id != ''")
collection.Fields.Add(&core.EditorField{Name: "description"})
app.Save(collection)
  • Supprimer : app.Delete(collection).

Note : Utilisez app.SaveNoValidate() pour sauter la validation.

En JavaScript : Opérations sur les collections

Similaire, mais avec des classes JS. $app expose les méthodes.

  • Récupérer une collection : $app.findCollectionByNameOrId("nom") jette une erreur si non trouvée.

Exemple :

let collection = $app.findCollectionByNameOrId("users");
console.log(collection.name);
  • Récupérer plusieurs : $app.findAllCollections(...types).

Exemple :

let authCollections = $app.findAllCollections("auth");
  • Requête custom : $app.collectionQuery().

Exemple :

let collections = arrayOf(new Collection);
$app.collectionQuery()
  .andWhere($dbx.hashExp({ "viewRule": null }))
  .orderBy("created DESC")
  .all(collections);
  • Créer : new Collection({ ... }), puis $app.save(collection).

Exemple :

let collection = new Collection({
  type: "base",
  name: "articles",
  viewRule: "@request.auth.id != ''",
  fields: [
    { name: "title", type: "text", required: true, max: 10 },
    { name: "user", type: "relation", required: true, collectionId: "users_id" }
  ]
});
$app.save(collection);
  • Mettre à jour et supprimer : Analogues à Go.

Ces opérations sont idéales pour automatiser la création de schémas lors du bootstrap d'une app startup.

Gestion des records avec les SDK

Les records sont les lignes de vos collections. Les SDK offrent des getters/setters typés et des requêtes filtrées.

En Go : Opérations sur les records

Importez core. Les méthodes sont sur app et *core.Record.

  • Récupérer un record : app.FindRecordById(collection, id) ou app.FindFirstRecordByFilter(collection, filter, params).

Exemple pour FindRecordsByFilter (équivalent à dao.FindRecordsByFilter) :

records, err := app.FindRecordsByFilter(
    "articles",
    "status = 'public' && category = {:category}",
    "-published", // tri
    10, 0, // limit, offset
    dbx.Params{"category": "news"},
)
  • Set/Get : record.Set("champ", valeur) ; record.GetString("champ").

Exemple :

record.Set("title", "Mon article")
title := record.GetString("title")
  • Créer : core.NewRecord(collection), set champs, app.Save(record).

Exemple avec fichiers :

import "github.com/pocketbase/pocketbase/tools/filesystem"

record := core.NewRecord(collection)
record.Set("title", "Article")
f1, _ := filesystem.NewFileFromPath("/path/file.txt")
record.Set("files", []*filesystem.File{f1})
app.Save(record)
  • Mettre à jour : Chargez, set, save. Pour append/supprimer : record.Set("files+", [...]) ou record.Set("files-", ["nom"]).
  • Supprimer : app.Delete(record).
  • Expansion de relations : app.ExpandRecord(record, []string{"relation"}).

En JavaScript : Opérations sur les records

Similaire, avec Record class.

  • Récupérer : $app.findRecordById("collection", "id") ou $app.findRecordsByFilter(...).

Exemple :

let records = $app.findRecordsByFilter(
  "articles",
  "status = 'public' && category = {:category}",
  "-published",
  10,
  0,
  { category: "news" }
);
  • Set/Get : record.set("champ", valeur) ; record.getString("champ").
  • Créer/Mettre à jour/Supprimer : Analogues, avec $app.save(record) et modificateurs comme "files+".

Exemple création :

let record = new Record(collection);
record.set("title", "Article");
let f1 = $filesystem.fileFromPath("/path/file.txt");
record.set("files", [f1]);
$app.save(record);

Pour les PME, ces méthodes simplifient l'ajout de logique comme l'auto-génération de slugs (record.Set("slug:autogenerate", "prefix-")).

Transactions

Les transactions assurent l'atomicité : tout réussit ou rien. Utiles pour des opérations multiples, comme créer un user et un post lié.

En Go

app.RunInTransaction(func(txApp core.App) error { ... }). Utilisez txApp à l'intérieur.

Exemple :

err := app.RunInTransaction(func(txApp core.App) error {
    record, _ := txApp.FindRecordById("users", "id")
    record.Set("status", "active")
    txApp.Save(record)

    // Raw delete
    _, err := txApp.DB().NewQuery("DELETE FROM drafts WHERE user = {:id}").Bind(dbx.Params{"id": "id"}).Execute()
    return err
})
if err != nil {
    log.Fatal(err)
}

Évitez les tâches longues (e-mails) dedans pour ne pas bloquer la DB.

En JavaScript

$app.runInTransaction((txApp) => { ... }).

Exemple :

$app.runInTransaction((txApp) => {
  let record = txApp.findRecordById("users", "id");
  record.set("status", "active");
  txApp.save(record);

  txApp.db().newQuery("DELETE FROM drafts WHERE user = {:id}")
    .bind({ id: "id" })
    .execute();
});

Les transactions supportent l'imbrication, mais gardez-les courtes pour les startups à fort trafic.

Requêtes SQL brutes

Quand les helpers ne suffisent pas, utilisez le builder dbx pour du SQL pur, avec protection contre les injections via params.

En Go

app.DB() retourne dbx.Builder.

Exemple simple SELECT :

type User struct {
    Id string `db:"id"`
    Email string `db:"email"`
}

user := User{}
err := app.DB().NewQuery("SELECT id, email FROM users WHERE id = {:id}").
    Bind(dbx.Params{"id": "123"}).
    One(&user)

Builder pour jointures :

users := []User{}
app.DB().
    Select("users.id", "users.email").
    From("users").
    LeftJoin("profiles", dbx.NewExp("profiles.user_id = users.id")).
    Where(dbx.HashExp{"users.status": "active"}).
    Limit(10).
    All(&users)

Expressions : dbx.HashExp{"status": true} génère status = true. dbx.Like("name", "john") pour %john%.

En JavaScript

$app.db().

Exemple :

const user = new DynamicModel({ id: "", email: "" });
$app.db()
  .newQuery("SELECT id, email FROM users WHERE id = {:id}")
  .bind({ id: "123" })
  .one(user);
console.log(user.email);

Builder :

const users = arrayOf(new DynamicModel({ id: "", email: "" }));
$app.db()
  .select("users.id", "users.email")
  .from("users")
  .leftJoin("profiles", $dbx.exp("profiles.user_id = users.id"))
  .where($dbx.hashExp({ status: "active" }))
  .limit(10)
  .all(users);

Pour les débutants, commencez par hashExp pour des filtres simples ; passez à exp pour du custom.

Comparaison Go vs JavaScript

Aspect Go JavaScript (JSVM)
Performance Native, rapide pour gros volumes. Interprété, suffisant pour hooks légers.
Syntaxe Typé statique, structs pour modèles. Dynamique, objets/arrays simples.
Requêtes dbx.Builder avec imports explicites. $dbx global, plus concis.
Transactions RunInTransaction, imbricable. runInTransaction, même logique.
Utilisation App custom complète, builds binaires. Hooks sans rebuild, idéal prototypage.
Complexité Plus verbeux, mais robuste. Plus rapide à écrire, moins d'erreurs runtime.

Go convient aux startups scalant vers des microservices ; JS pour des itérations rapides en SMB. Les deux intègrent les hooks PocketBase (e.g., OnRecordCreateRequest).

Conclusion

Les SDK Go et JS de PocketBase élèvent votre backend au-delà de l'API REST, avec un contrôle fin sur données et DB. Pour une startup, commencez par JS pour valider des idées ; migrez vers Go pour la prod. Testez ces exemples dans un projet local – vous verrez la puissance pour des apps sécurisées et efficaces. Si vous avez des questions, la doc officielle reste la référence.

Lire la suite