Deno TypeScript dengan Claude Code: permissions, deno.json, dan Deno.serve
Panduan Deno dengan Claude Code: permission minimal, deno.json tasks, Deno.serve, serta fmt/lint/test bawaan dengan kode siap salin.
Mulai dari model permission Deno
Deno adalah runtime untuk JavaScript dan TypeScript, yaitu lapisan yang menjalankan kode. Perbedaan pentingnya: Deno aman secara default. Akses file, jaringan, environment variable, dan subprocess tidak terbuka sebelum Anda memberi permission. Rujukan resminya ada di Security and permissions.
Claude Code sangat membantu karena bisa membuat server, test, deno.json, dan checklist review sekaligus. Namun prompt yang terlalu umum sering menghasilkan -A, asumsi Node.js, atau dependency yang tidak perlu. Tuliskan runtime, API yang dipakai, hal yang dilarang, permission, dan command verifikasi secara eksplisit.
Istilah dasar: permission adalah daftar akses yang diizinkan untuk program; deno task adalah command bernama di deno.json; formatter merapikan format; linter mencari pola berisiko; test runner menjalankan Deno.test(). Deno membawa alat ini secara bawaan. Untuk konteks lain, lihat API development, testing strategies, dan TypeScript tips.
Prompt yang jelas untuk Claude Code
Buat API JSON kecil dengan Deno. Gunakan
Deno.serve, bukan Express. Buatdeno.jsondengan taskdev,start,fmt,lint,test, dancheck. Jangan gunakan-A. Izinkan hanya--allow-net=127.0.0.1:8000,--allow-read=./data, dan--allow-write=./data. Tulis test denganDeno.test().
Prompt ini mengikuti konsep resmi configuration, deno task, Deno.serve, dan deno test.
deno.json sebagai kontrak proyek
{
"tasks": {
"dev": "deno run --watch --allow-net=127.0.0.1:8000 --allow-read=./data --allow-write=./data server.ts",
"start": "deno run --allow-net=127.0.0.1:8000 --allow-read=./data --allow-write=./data server.ts",
"fmt": "deno fmt",
"lint": "deno lint",
"test": "deno test",
"check": "deno fmt --check && deno lint && deno test"
},
"fmt": {
"lineWidth": 100,
"semiColons": true
},
"lint": {
"rules": {
"tags": ["recommended"]
}
},
"imports": {
"@std/assert": "jsr:@std/assert"
}
}
check menyatukan format, lint, dan test. Ini memudahkan Claude Code dan CI memakai standar yang sama.
Contoh Deno.serve yang bisa disalin
// app.ts
export type Item = {
id: string;
title: string;
done: boolean;
};
export interface ItemStore {
list(): Promise<Item[]>;
save(items: Item[]): Promise<void>;
}
export class FileItemStore implements ItemStore {
constructor(private readonly path = "./data/items.json") {}
async list(): Promise<Item[]> {
try {
const text = await Deno.readTextFile(this.path);
return JSON.parse(text) as Item[];
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
return [];
}
throw error;
}
}
async save(items: Item[]): Promise<void> {
await Deno.writeTextFile(this.path, JSON.stringify(items, null, 2));
}
}
export function createHandler(store: ItemStore): (request: Request) => Promise<Response> {
return async (request: Request): Promise<Response> => {
const url = new URL(request.url);
if (url.pathname === "/health") {
return Response.json({ ok: true });
}
if (url.pathname === "/api/items" && request.method === "GET") {
return Response.json(await store.list());
}
if (url.pathname === "/api/items" && request.method === "POST") {
const body = await request.json().catch(() => null) as { title?: unknown } | null;
if (!body || typeof body.title !== "string" || body.title.trim() === "") {
return Response.json({ error: "title is required" }, { status: 400 });
}
const items = await store.list();
const item: Item = {
id: crypto.randomUUID(),
title: body.title.trim(),
done: false
};
await store.save([...items, item]);
return Response.json(item, { status: 201 });
}
return new Response("Not Found", { status: 404 });
};
}
// server.ts
import { createHandler, FileItemStore } from "./app.ts";
Deno.serve(
{ hostname: "127.0.0.1", port: 8000 },
createHandler(new FileItemStore())
);
mkdir -p data
printf "[]\n" > data/items.json
deno task dev
curl http://127.0.0.1:8000/health
curl -X POST http://127.0.0.1:8000/api/items \
-H "content-type: application/json" \
-d '{"title":"Deno article draft"}'
curl http://127.0.0.1:8000/api/items
Test tanpa permission tambahan
// app_test.ts
import { assertEquals } from "@std/assert";
import { createHandler, type Item, type ItemStore } from "./app.ts";
class MemoryStore implements ItemStore {
private items: Item[] = [];
async list(): Promise<Item[]> {
return [...this.items];
}
async save(items: Item[]): Promise<void> {
this.items = [...items];
}
}
Deno.test("GET /health returns ok", async () => {
const handler = createHandler(new MemoryStore());
const response = await handler(new Request("http://localhost/health"));
assertEquals(response.status, 200);
assertEquals(await response.json(), { ok: true });
});
Deno.test("POST /api/items creates an item", async () => {
const handler = createHandler(new MemoryStore());
const response = await handler(
new Request("http://localhost/api/items", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ title: "Write article" })
})
);
const created = await response.json() as Item;
assertEquals(response.status, 201);
assertEquals(created.title, "Write article");
assertEquals(created.done, false);
});
Deno.test("POST /api/items rejects an empty title", async () => {
const handler = createHandler(new MemoryStore());
const response = await handler(
new Request("http://localhost/api/items", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ title: "" })
})
);
assertEquals(response.status, 400);
});
Use case konkret
Pertama, prototype API internal seperti admin helper, penerima webhook, atau demo berbasis JSON. Deno.serve cukup sebelum memakai framework besar.
Kedua, otomasi repository. Pemeriksaan konten, validasi konfigurasi, dan snapshot API bisa berjalan lewat deno task.
Ketiga, onboarding tim. Error permission Deno membuat akses network, read, dan write mudah dijelaskan kepada developer baru.
Keempat, service HTTP kecil yang mungkin diarahkan ke edge/deploy environment. Penggunaan Request dan Response standar membuat desain lebih portabel.
Pitfall yang sering terjadi
Jangan biarkan -A ada di task. Itu membuka semua permission.
Jangan langsung menambah Express, Jest, Prettier, dan ESLint sebelum mencoba tool bawaan Deno.
Jangan lupa membuat data/items.json; contoh file-backed membutuhkan file awal.
Jangan buat semua unit test memakai file atau socket nyata. Memory store lebih cepat dan tidak perlu permission.
Jangan menyalin contoh lama tanpa mengecek dokumentasi resmi Deno.
CTA dan verifikasi
Jika workflow ini dipakai berulang, tulis command dan permission policy di CLAUDE.md. Mulai dari free cheatsheet, gunakan products and templates untuk prompt yang bisa dipakai ulang, dan pakai training and consultation bila ingin rollout tim.
Verifikasi praktis: buat data/items.json, jalankan deno task dev, POST satu item dengan curl, lalu jalankan deno task check. Saat review, prioritaskan menghapus -A, mempersempit path, dan menjaga unit test tetap tanpa permission.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Workflow Obsidian ke CLAUDE.md untuk Claude Code
Ubah catatan kerja Obsidian menjadi operating note CLAUDE.md agar konteks tidak dijelaskan ulang.
Claude Code Revenue CTA Routing: dari artikel ke PDF, Gumroad, dan konsultasi
Workflow Claude Code untuk mengarahkan pembaca ke PDF gratis, Gumroad, atau konsultasi sesuai intent.
Aturan handoff tim Claude Code: bukti review, permission, rollback, dan jalur revenue
Format handoff Claude Code untuk tim: bukti, permission rule, rollback, PDF gratis, Gumroad, dan konsultasi.