Skip to main content

Server Actions

File Structure

Server Actions Folder Structure

Sample Actions

Below are example server actions that demonstrate the proper implementation of return types. All server actions should follow this pattern to ensure consistency and predictability.

'use server';
import { createClient } from '@/utils/supabase/server';
import { checkUserRoleEnough, getUserId } from './User';
import { ContentEntity, ServerActionResponse } from '../types/types';

export async function getEntities(): Promise<
ServerActionResponse<ContentEntity[]>
> {
try {
const supabase = createClient();
const userResponse = await getUserId();
const isEnoughRole = await checkUserRoleEnough([1, 2]);

if (!userResponse.status || !isEnoughRole) {
return {
error: 'Unauthorized',
status: 401,
message: 'Unauthorized access to entities',
};
}

const { data, error } = await supabase.from('content_entities').select('*');

if (error) {
console.error('Error getting entities => ', error);

return {
error: 'Unexpected error getting entities',
status: 500,
message: 'Unexpected error',
};
}

if (data === null) {
return {
status: 200,
message: 'No entities found',
};
}

return {
data: data,
status: 200,
message: 'Entities retrieved successfully',
};
} catch (error) {
console.log('Error getting entities => ', error);

return {
error: 'Unexpected error getting entities',
status: 500,
message: 'Unexpected error',
};
}
}

export async function getEntityById(
entityId: string
): Promise<ServerActionResponse<ContentEntity>> {
try {
const supabase = createClient();
const userResponse = await getUserId();
const isEnoughRole = await checkUserRoleEnough([1, 2]);

if (!userResponse.status || !isEnoughRole) {
return {
error: 'Unauthorized',
status: 401,
message: 'Unauthorized access to entities',
};
}

const { data, error } = await supabase
.from('content_entities')
.select('*')
.eq('id', entityId)
.single();

if (error) {
console.error('Error getting entity => ', error);

return {
error: 'Unexpected error getting entity',
status: 500,
message: 'Unexpected error',
};
}

if (data === null) {
return {
status: 200,
message: 'No entity found',
};
}

return {
data: data as ContentEntity,
status: 200,
message: 'Entity retrieved successfully',
};
} catch (error) {
console.log('Error getting entity => ', error);

return {
error: 'Unexpected error getting entity',
status: 500,
message: 'Unexpected error',
};
}
}

export async function createEntity(
newEntity: ContentEntity
): Promise<ServerActionResponse<ContentEntity>> {
try {
const supabase = createClient();
const userResponse = await getUserId();
const isEnoughRole = await checkUserRoleEnough([1, 2]);

// Check for authorization
if (!userResponse.status || !isEnoughRole) {
return {
error: 'Unauthorized',
status: 401,
message: 'Unauthorized access to create entity',
};
}

// Insert the new entity
const { data, error } = await supabase
.from('content_entities')
.insert(newEntity)
.single();

// Handle error
if (error) {
console.error('Error creating entity => ', error);

return {
error: 'Unexpected error creating entity',
status: 500,
message: 'Unexpected error',
};
}

// Success response
return {
data: data,
status: 201,
message: 'Entity created successfully',
};
} catch (error) {
console.log('Error creating entity => ', error);

return {
error: 'Unexpected error creating entity',
status: 500,
message: 'Unexpected error',
};
}
}

export async function updateEntity({
entityId,
updatedEntity,
}: {
entityId: string;
updatedEntity: ContentEntity;
}): Promise<ServerActionResponse<ContentEntity>> {
try {
const supabase = createClient();
const userResponse = await getUserId();
const isEnoughRole = await checkUserRoleEnough([1, 2]);

// Check for authorization
if (!userResponse.status || !isEnoughRole) {
return {
error: 'Unauthorized',
status: 401,
message: 'Unauthorized access to update entity',
};
}

// Update the entity
const { data, error } = await supabase
.from('content_entities')
.update(updatedEntity)
.eq('id', entityId)
.single();

// Handle error
if (error) {
console.error('Error updating entity => ', error);

return {
error: 'Unexpected error updating entity',
status: 500,
message: 'Unexpected error',
};
}

// Success response
return {
data: data,
status: 200,
message: 'Entity updated successfully',
};
} catch (error) {
console.log('Error updating entity => ', error);

return {
error: 'Unexpected error updating entity',
status: 500,
message: 'Unexpected error',
};
}
}

export async function deleteEntity(
entityId: string
): Promise<ServerActionResponse<ContentEntity>> {
try {
const supabase = createClient();
const userResponse = await getUserId();
const isEnoughRole = await checkUserRoleEnough([1, 2]);

// Check for authorization
if (!userResponse.status || !isEnoughRole) {
return {
error: 'Unauthorized',
status: 401,
message: 'Unauthorized access to delete entity',
};
}

// Delete the entity
const { data, error } = await supabase
.from('content_entities')
.delete()
.eq('id', entityId)
.single();

// Handle error
if (error) {
console.error('Error deleting entity => ', error);

return {
error: 'Unexpected error deleting entity',
status: 500,
message: 'Unexpected error',
};
}

// Success response
return {
data: data,
status: 200,
message: 'Entity deleted successfully',
};
} catch (error) {
console.log('Error deleting entity => ', error);

return {
error: 'Unexpected error deleting entity',
status: 500,
message: 'Unexpected error',
};
}
}