# Example with database

This example shows you how to use the FTP server with the built-in SQLite database and Argon2 password hashing.

Database Support

Version 2.0+ uses SQLite exclusively via @db/sqlite for better performance and simpler deployment.

# Import

Add the package to your project:

deno add @dftp/server

Import the server, database utilities and Argon2:

import { createDb, Server, Users } from "@dftp/server";
import { hash, verify } from "@node-rs/argon2";

# Initialize database

SQLite is the only supported database connector:

// Initialize SQLite database
createDb({ connector: "SQLite", filepath: "./users.db" });

# Create users

Use Argon2id for secure password hashing:

// Create a user with hashed password
Users.create({
  username: "admin",
  password: await hash("secret"),
  root: "/srv/ftp",
  uid: 1000,
  gid: 1000,
});

# Handle connections

Authenticate users against the database:

const server = new Server({ port: 21 });

for await (const conn of server) {
  conn.on("login", async ({ username, password }, resolve, reject) => {
    const user = Users.findByUsername(username);
    if (user && await verify(user.password, password)) {
      resolve({ root: user.root, uid: user.uid, gid: user.gid });
    } else {
      reject();
    }
  });
}

# Full example

import { createDb, Server, Users } from "@dftp/server";
import { hash, verify } from "@node-rs/argon2";

// Initialize database
createDb({ connector: "SQLite", filepath: "./users.db" });

// Create a user (run once)
Users.create({
  username: "admin",
  password: await hash("secret"),
  root: "/srv/ftp",
  uid: 1000,
  gid: 1000,
});

// Start server
const server = new Server({ port: 21 });
console.log("FTP server listening on port 21");

for await (const conn of server) {
  conn.on("login", async ({ username, password }, resolve, reject) => {
    const user = Users.findByUsername(username);
    if (user && await verify(user.password, password)) {
      resolve({ root: user.root, uid: user.uid, gid: user.gid });
    } else {
      reject();
    }
  });
}