إنشاء تطبيق CRUD متكامل باستخدام SvelteKit و Supabase: دليل المبتدئين
مقدمة
سيرشدك هذا الدليل خلال إنشاء تطبيق بسيط لقائمة المهام باستخدام SvelteKit للواجهة الأمامية ومسارات API الخلفية، و Supabase لقاعدة البيانات والمصادقة. سنغطي عمليات CRUD الأساسية: إنشاء وقراءة وتحديث وحذف عناصر قائمة المهام.
المتطلبات الأساسية
- Node.js (أحدث إصدار LTS)
- npm أو pnpm
- حساب Supabase (الخطة المجانية كافية)
الإعداد
-
إنشاء مشروع SvelteKit:
npm create svelte@latest my-todo-app cd my-todo-app npm installاختر المشروع الهيكلي. سنضيف Typescript لضمان كتابة البيانات بشكل صحيح.
-
تهيئة Supabase:
أنشئ مشروعًا جديدًا على Supabase. بمجرد إنشائه، احصل على عنوان URL الخاص بـ Supabase ومفتاح anon من إعدادات API.
-
تثبيت عميل JavaScript الخاص بـ Supabase:
npm install @supabase/supabase-js npm install -D @sveltejs/adapter-autoأيضًا، قم بتثبيت حزم Typescript التي ستساعد في التطوير
npm install -D typescript svelte-check svelte-preprocess
إنشاء عميل Supabase
أنشئ ملف src/lib/supabaseClient.js:
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
هام: قم بتخزين عنوان URL الخاص بـ Supabase ومفتاح anon في ملفات .env وارجع إليهما باستخدام import.meta.env. لا تقم أبدًا بتضمين هذه المفاتيح مباشرةً في مستودعك!
أنشئ ملفات .env و .env.development:
VITE_SUPABASE_URL="your_supabase_url"
VITE_SUPABASE_ANON_KEY="your_supabase_anon_key"
قد تحتاج إلى تحديث svelte.config.js إذا واجهت مشاكل مع المتغيرات البيئية. فيما يلي نموذج تكوين
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter(),
vite: {
define: {
'process.env': process.env
}
}
}
};
export default config;
بناء واجهة المستخدم (src/routes/+page.svelte)
<script>
import { supabase } from '$lib/supabaseClient';
import { onMount } from 'svelte';
let todos = [];
let newTodo = '';
onMount(async () => {
await fetchTodos();
});
async function fetchTodos() {
const { data, error } = await supabase
.from('todos')
.select('*')
.order('created_at', { ascending: false });
if (error) {
console.error('Error fetching todos:', error);
return;
}
todos = data;
}
async function addTodo() {
if (!newTodo.trim()) return;
const { data, error } = await supabase
.from('todos')
.insert([{ task: newTodo }])
.single();
if (error) {
console.error('Error adding todo:', error);
return;
}
todos = [data, ...todos];
newTodo = '';
}
async function deleteTodo(id) {
const { error } = await supabase
.from('todos')
.delete()
.eq('id', id);
if (error) {
console.error('Error deleting todo:', error);
return;
}
todos = todos.filter(todo => todo.id !== id);
}
async function toggleComplete(todo) {
const { error } = await supabase
.from('todos')
.update({ completed: !todo.completed })
.eq('id', todo.id)
.single();
if (error) {
console.error('Error updating todo:', error);
return;
}
todo.completed = !todo.completed;
todos = [...todos]; // Trigger reactivity
}
</script>
<input type="text" bind:value={newTodo} placeholder="أضف مهمة جديدة" />
<button on:click={addTodo}>إضافة</button>
<ul>
{#each todos as todo (todo.id)}
<li>
<input type="checkbox" checked={todo.completed} on:change={() => toggleComplete(todo)} />
<span class:completed={todo.completed}>{todo.task}</span>
<button on:click={() => deleteTodo(todo.id)}>حذف</button>
</li>
{/each}
</ul>
<style>
.completed {
text-decoration: line-through;
color: gray;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
align-items: center;
margin-bottom: 5px;
}
li > * {
margin-right: 10px;
}
</style>
إنشاء جدول 'todos' في Supabase
في لوحة معلومات Supabase الخاصة بك، انتقل إلى محرر SQL وقم بتشغيل SQL التالي:
CREATE TABLE todos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()),
task TEXT NOT NULL,
completed BOOLEAN NOT NULL DEFAULT FALSE
);
قم بتمكين أمان مستوى الصف (RLS) وإنشاء سياسات بناءً على معرف المستخدم. في هذا البرنامج التعليمي، نفترض عدم وجود مصادقة وتعطيل RLS. تحذير: هذا غير آمن للغاية للاستخدام في الإنتاج
شرح
src/lib/supabaseClient.js: يقوم بتهيئة عميل Supabase.src/routes/+page.svelte:- يجلب المهام عند التحميل.
addTodoينشئ مهمة جديدة في Supabase.deleteTodoيحذف مهمة من Supabase.toggleCompleteيقوم بتحديث حالة الإكمال في Supabase.- تستخدم واجهة المستخدم تفاعل Svelte لعرض المهام.
تشغيل التطبيق
npm run dev -- --open
سيعمل تطبيقك على http://localhost:5173/.
الخطوات التالية
- تنفيذ مصادقة المستخدم باستخدام Supabase Auth.
- إضافة ميزات أكثر تقدمًا مثل تعديل المهام وتحديد المواعيد النهائية وما إلى ذلك.
- تحسين واجهة المستخدم باستخدام أطر عمل CSS مثل Tailwind CSS.