Web Development Basics
HTTP Server Creation
Creating a Basic Server with Deno.serve
Deno 1.28+ introduced the simpler Deno.serve API, streamlining HTTP server creation:
// basic_server.ts
Deno.serve((req) => {
return new Response("Hello from Deno!", {
headers: { "Content-Type": "text/plain" }
});
});
// Run: deno run --allow-net basic_server.tsBasic Server with Routing
// router_server.ts
Deno.serve((req) => {
const url = new URL(req.url);
if (url.pathname === "/") {
return new Response("Home Page");
} else if (url.pathname === "/about") {
return new Response("About Page");
}
return new Response("404 Not Found", { status: 404 });
});
// Run: deno run --allow-net router_server.tsRouting and Request Handling
Middleware Mechanism Implementation
// middleware_server.ts
type Middleware = (req: Request, next: () => Promise<Response>) => Promise<Response>;
function createServer(middlewares: Middleware[]) {
return async (req: Request) => {
let index = -1;
async function dispatch(i: number): Promise<Response> {
if (i <= index) throw new Error("next() called multiple times");
index = i;
if (i >= middlewares.length) return new Response("Not Found", { status: 404 });
return middlewares[i](req, () => dispatch(i + 1));
}
return dispatch(0);
};
}
// Example middleware
async function loggerMiddleware(req: Request, next: () => Promise<Response>) {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
return next();
}
async function authMiddleware(req: Request, next: () => Promise<Response>) {
const authHeader = req.headers.get("Authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return new Response("Unauthorized", { status: 401 });
}
return next();
}
// Create server
const server = createServer([loggerMiddleware, authMiddleware]);
Deno.serve(server);
// Run: deno run --allow-net middleware_server.tsStatic File Serving
Configuring Static File Serving
// static_server.ts
Deno.serve({
handler: (req) => {
const url = new URL(req.url);
const filePath = `./static${url.pathname}`;
// Check if file exists
try {
const file = await Deno.open(filePath, { read: true });
file.close();
return new Response(Deno.readFile(filePath), {
headers: { "Content-Type": getContentType(filePath) }
});
} catch {
return new Response("404 Not Found", { status: 404 });
}
}
});
function getContentType(filePath: string): string {
const ext = filePath.split(".").pop();
switch (ext) {
case "html": return "text/html";
case "css": return "text/css";
case "js": return "application/javascript";
case "json": return "application/json";
default: return "text/plain";
}
}
// Run: deno run --allow-net --allow-read static_server.tsUsing Oak Framework’s Static File Middleware
// oak_static_server.ts
import { Application, oakStatic } from "https://deno.land/x/oak@v12.6.1/mod.ts";
const app = new Application();
// Static file middleware
app.use(oakStatic("./static", {
extensions: ["html"],
index: "index.html"
}));
app.use((ctx) => {
if (ctx.request.url.pathname === "/api") {
ctx.response.body = { message: "API Response" };
}
});
console.log("Server running on http://localhost:8000");
await app.listen({ port: 8000 });
// Run: deno run --allow-net --allow-read oak_static_server.tsTemplate Engine Integration
EJS Template Integration
// ejs_server.ts
import { Application } from "https://deno.land/x/oak@v12.6.1/mod.ts";
import { renderFile } from "https://deno.land/x/dejs@0.10.3/mod.ts";
const app = new Application();
app.use(async (ctx) => {
if (ctx.request.url.pathname === "/") {
const data = { title: "Deno EJS Demo", items: ["Item 1", "Item 2"] };
ctx.response.body = await renderFile("./views/index.ejs", data);
ctx.response.type = "text/html";
}
});
console.log("Server running on http://localhost:8000");
await app.listen({ port: 8000 });
// Run: deno run --allow-net ejs_server.tsView File Example (views/index.ejs)
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<ul>
<% items.forEach(item => { %>
<li><%= item %></li>
<% }) %>
</ul>
</body>
</html>RESTful API Design and Implementation
Complete RESTful API Example
// rest_api_server.ts
import { Application, Router } from "https://deno.land/x/oak@v12.6.1/mod.ts";
interface User {
id: number;
name: string;
email: string;
}
const users: User[] = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" }
];
const router = new Router();
// Get all users
router.get("/users", (ctx) => {
ctx.response.body = users;
});
// Get single user
router.get("/users/:id", (ctx) => {
const id = parseInt(ctx.params.id);
const user = users.find(u => u.id === id);
if (!user) {
ctx.response.status = 404;
ctx.response.body = { error: "User not found" };
return;
}
ctx.response.body = user;
});
// Create user
router.post("/users", async (ctx) => {
const body = await ctx.request.body({ type: "json" }).value;
if (!body.name || !body.email) {
ctx.response.status = 400;
ctx.response.body = { error: "Name and email are required" };
return;
}
const newUser: User = {
id: users.length + 1,
name: body.name,
email: body.email
};
users.push(newUser);
ctx.response.status = 201;
ctx.response.body = newUser;
});
// Update user
router.put("/users/:id", async (ctx) => {
const id = parseInt(ctx.params.id);
const userIndex = users.findIndex(u => u.id === id);
if (userIndex === -1) {
ctx.response.status = 404;
ctx.response.body = { error: "User not found" };
return;
}
const body = await ctx.request.body({ type: "json" }).value;
if (!body.name || !body.email) {
ctx.response.status = 400;
ctx.response.body = { error: "Name and email are required" };
return;
}
users[userIndex] = {
...users[userIndex],
name: body.name,
email: body.email
};
ctx.response.body = users[userIndex];
});
// Delete user
router.delete("/users/:id", (ctx) => {
const id = parseInt(ctx.params.id);
const userIndex = users.findIndex(u => u.id === id);
if (userIndex === -1) {
ctx.response.status = 404;
ctx.response.body = { error: "User not found" };
return;
}
users.splice(userIndex, 1);
ctx.response.status = 204;
});
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
console.log("REST API server running on http://localhost:8000");
await app.listen({ port: 8000 });
// Run: deno run --allow-net rest_api_server.tsDatabase Interaction
MySQL Database Connection and Queries
Using mysql2 Module
// mysql_example.ts
import mysql from "https://deno.land/x/mysql2@v3.6.0/mod.ts";
// Create connection
const conn = await mysql.connect({
hostname: "127.0.0.1",
username: "root",
password: "password",
db: "testdb",
port: 3306,
});
// Execute query
const result = await conn.query("SELECT * FROM users");
console.log(result);
// Insert data
const insertResult = await conn.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
["Alice", "alice@example.com"]
);
console.log(insertResult);
// Close connection
await conn.close();
// Run: deno run --allow-net mysql_example.tsPostgreSQL Database Operations
Using pg Module
// postgres_example.ts
import { Client } from "https://deno.land/x/postgres@v0.17.0/mod.ts";
// Create client
const client = new Client({
user: "postgres",
password: "password",
database: "testdb",
hostname: "127.0.0.1",
port: 5432,
});
// Connect to database
await client.connect();
// Execute query
const result = await client.queryObject("SELECT * FROM users");
console.log(result.rows);
// Insert data
const insertResult = await client.queryObject(
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
["Bob", "bob@example.com"]
);
console.log(insertResult.rows);
// Close connection
await client.close();
// Run: deno run --allow-net postgres_example.tsSQLite Database Operations
Using better-sqlite3 Module
// sqlite_example.ts
import Database from "https://deno.land/x/better_sqlite3@7.6.0/mod.ts";
// Create database connection
const db = new Database("test.db");
// Create table
db.query(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
)
`);
// Insert data
const insertStmt = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
insertStmt.run("Charlie", "charlie@example.com");
// Query data
const result = db.query("SELECT * FROM users");
for (const row of result) {
console.log(row);
}
// Close database
db.close();
// Run: deno run --allow-write sqlite_example.tsDatabase Connection Pooling and Performance Optimization
MySQL Connection Pool Example
// mysql_pool_example.ts
import mysql from "https://deno.land/x/mysql2@v3.6.0/mod.ts";
// Create connection pool
const pool = mysql.createPool({
hostname: "127.0.0.1",
username: "root",
password: "password",
db: "testdb",
port: 3306,
poolSize: 10, // Connection pool size
});
// Get connection from pool
const conn = await pool.getConnection();
try {
// Execute query
const result = await conn.query("SELECT * FROM users");
console.log(result);
} finally {
// Release connection back to pool
conn.release();
}
// Close pool
await pool.end();
// Run: deno run --allow-net mysql_pool_example.tsORM and ODM Selection and Comparison
Prisma Client Example
// prisma_example.ts
import { PrismaClient } from "https://esm.sh/prisma@5.0.0/client";
// Create Prisma client
const prisma = new PrismaClient();
// Query users
const users = await prisma.user.findMany();
console.log(users);
// Create user
const newUser = await prisma.user.create({
data: {
name: "David",
email: "david@example.com"
}
});
console.log(newUser);
// Close client
await prisma.$disconnect();
// Run: deno run --allow-net prisma_example.tsTypeORM Integration with Deno
// typeorm_example.ts
import "https://deno.land/x/typeorm@0.3.11/mod.ts";
import { User } from "./entities/user.ts";
// Create connection
const connection = await createConnection({
type: "mysql",
host: "127.0.0.1",
port: 3306,
username: "root",
password: "password",
database: "testdb",
entities: [User],
synchronize: true,
});
// Get Repository
const userRepository = connection.getRepository(User);
// Create user
const user = new User();
user.name = "Eve";
user.email = "eve@example.com";
await userRepository.save(user);
// Query users
const users = await userRepository.find();
console.log(users);
// Close connection
await connection.close();
// Run: deno run --allow-net typeorm_example.tsCommand-Line Tool Development
Command-Line Argument Parsing
Using flags Library for Argument Parsing
// cli_flags.ts
import { parse } from "https://deno.land/std@0.140.0/flags/mod.ts";
const args = parse(Deno.args);
if (args._.length === 0) {
console.log("Usage: cli_flags.ts <command> [options]");
Deno.exit(1);
}
const command = args._[0];
console.log("Command:", command);
if (args.help) {
console.log("Help message");
Deno.exit(0);
}
if (args.verbose) {
console.log("Verbose mode enabled");
}
// Run: deno run --allow-read cli_flags.ts build --verbose --helpBuilding Complex CLI with yargs
// cli_yargs.ts
import yargs from "https://deno.land/x/yargs@17.6.2/deno.ts";
yargs(Deno.args)
.scriptName("mycli")
.command({
command: "build",
describe: "Build the project",
handler: () => {
console.log("Building project...");
}
})
.option("verbose", {
alias: "v",
type: "boolean",
description: "Run with verbose logging"
})
.help()
.parse();
// Run: deno run --allow-read cli_yargs.ts build --verboseFile System Operations and Interaction
File Processing CLI Example
// cli_file_processor.ts
import { parse } from "https://deno.land/std@0.140.0/flags/mod.ts";
import { ensureFile, writeJson } from "https://deno.land/std@0.140.0/fs/mod.ts";
const args = parse(Deno.args);
if (args._.length === 0) {
console.log("Usage: cli_file_processor.ts <file> [--json]");
Deno.exit(1);
}
const filePath = args._[0];
const useJson = args.json || false;
try {
// Check if file exists
await Deno.stat(filePath);
// Read file content
const content = await Deno.readTextFile(filePath);
if (useJson) {
// Process as JSON
try {
const jsonData = JSON.parse(content);
await ensureFile(`${filePath}.processed.json`);
await writeJson(`${filePath}.processed.json`, jsonData);
console.log("JSON file processed successfully");
} catch {
console.error("File is not valid JSON");
Deno.exit(1);
}
} else {
// Simple processing
const processedContent = content.toUpperCase();
await ensureFile(`${filePath}.processed.txt`);
await Deno.writeTextFile(`${filePath}.processed.txt`, processedContent);
console.log("Text file processed successfully");
}
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
console.error("File not found");
} else {
console.error("Error:", error);
}
Deno.exit(1);
}
// Run: deno run --allow-read --allow-write cli_file_processor.ts example.txt --jsonColored Output and Progress Bars
Using chalk and ora for Aesthetic Output
// cli_ui.ts
import chalk from "https://deno.land/x/chalk@v4.1.2/mod.ts";
import ora from "https://deno.land/x/ora@v5.1.0/mod.ts";
// Colored output example
console.log(chalk.blue("This is blue text"));
console.log(chalk.red.bold("This is red bold text"));
console.log(chalk.green("Success message"));
// Progress bar example
const spinner = ora("Loading...").start();
// Simulate async operation
setTimeout(() => {
spinner.succeed("Loaded successfully!");
}, 2000);
// Run: deno run --allow-read cli_ui.tsScaffolding Tool Development
Simple Yeoman-Style Scaffolding
// scaffold_cli.ts
import { prompt } from "https://deno.land/x/cliffy@v0.25.0/prompt/mod.ts";
import { ensureDir, writeJson } from "https://deno.land/std@0.140.0/fs/mod.ts";
import chalk from "https://deno.land/x/chalk@v4.1.2/mod.ts";
interface ProjectConfig {
name: string;
description: string;
author: string;
useTypeScript: boolean;
}
async function createProject() {
// Collect user input
const config: ProjectConfig = await prompt([
{
type: "input",
name: "name",
message: "Project name:",
},
{
type: "input",
name: "description",
message: "Project description:",
},
{
type: "input",
name: "author",
message: "Author name:",
},
{
type: "confirm",
name: "useTypeScript",
message: "Use TypeScript?",
initial: true,
},
]);
// Create project directory
await ensureDir(config.name);
// Create package.json
const packageJson = {
name: config.name,
version: "1.0.0",
description: config.description,
author: config.author,
scripts: {
start: config.useTypeScript
? "deno run --allow-net src/index.ts"
: "deno run --allow-net index.js",
},
dependencies: {
deno: "latest",
},
};
await writeJson(`${config.name}/package.json`, packageJson);
// Create example file
if (config.useTypeScript) {
await ensureDir(`${config.name}/src`);
await Deno.writeTextFile(
`${config.name}/src/index.ts`,
`console.log("Hello from ${config.name}!");`
);
} else {
await Deno.writeTextFile(
`${config.name}/index.js`,
`console.log("Hello from ${config.name}!");`
);
}
console.log(chalk.green(`Project ${config.name} created successfully!`));
}
createProject().catch(console.error);
// Run: deno run --allow-read --allow-write scaffold_cli.tsGlobal vs. Local Installation
Global CLI Tool Installation
# Global installation (requires deno install)
deno install --allow-read --allow-write --allow-net -n mycli https://example.com/cli.ts
# Use globally installed tool
mycli build --verboseLocal CLI Tool Installation
# Install as dependency in project
deno cache --import-map=import_map.json cli.ts
# Add bin field in package.json (if using bundler)
{
"bin": {
"mycli": "cli.ts"
}
}
# Local usage (via npx or project scripts)
deno run --allow-read --allow-write --allow-net cli.ts build --verboseKey Differences
- Permission Scope: Global installation requires broader permissions.
- Environment Variables: Global tools need PATH environment configuration.
- Dependency Management: Local tools allow precise version control.
- Portability: Local tools are easier to migrate with projects.
- Update Mechanism: Global tools require manual updates.



