Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions api/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { dev } from '$app/environment';
import type { Handle } from '@sveltejs/kit';
import { APP_DOMAIN, DASHBOARD_DOMAIN } from '../../shared/config';
import { APP_BASE, DASHBOARD_BASE } from '$lib/server/config';

const domainsWithAccessToAPI = [APP_DOMAIN, DASHBOARD_DOMAIN, 'https://checkout.stripe.com'];
const domainsWithAccessToAPI = [APP_BASE, DASHBOARD_BASE, 'https://checkout.stripe.com'];
const publicEndpoints = ['/', '/checkout/success'];

const appendHeaders = (response: Response, origin: string | null) => {
Expand All @@ -21,7 +20,7 @@ export const handle: Handle = async ({ resolve, event }) => {
return response;
}

if ((origin === null || !domainsWithAccessToAPI.includes(origin)) && !dev) {
if (!origin || !domainsWithAccessToAPI.includes(origin)) {
console.error(`Unauthorized access attempt from origin: ${origin}`);
return new Response('Unauthorised', { status: 401 });
}
Expand Down
10 changes: 10 additions & 0 deletions api/src/lib/server/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { dev } from '$app/environment';
import {
APP_DOMAIN,
APP_LOCAL_PORT,
DASHBOARD_DOMAIN,
DASHBOARD_LOCAL_PORT
} from '../../../../shared/config';

export const APP_BASE = dev ? `http://localhost:${APP_LOCAL_PORT}` : APP_DOMAIN;
export const DASHBOARD_BASE = dev ? `http://localhost:${DASHBOARD_LOCAL_PORT}` : DASHBOARD_DOMAIN;
8 changes: 7 additions & 1 deletion app/src/lib/global/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { dev } from '$app/environment';
import { API_DOMAIN, API_LOCAL_PORT } from '../../../../shared/config';
import { API_DOMAIN, API_LOCAL_PORT, APP_DOMAIN, APP_LOCAL_PORT } from '../../../../shared/config';

export const PUBLIC_SUPABASE_URL = import.meta.env.VITE_SUPABASE_URL;
export const PUBLIC_SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_ANON_KEY;

export const PUBLIC_PATH_ROOTS = ['/login', '/auth', '/about', '/contact', '/privacy', '/terms'];

export const API_BASE = dev ? `http://localhost:${API_LOCAL_PORT}` : API_DOMAIN;
const APP_BASE = dev ? `http://localhost:${APP_LOCAL_PORT}` : APP_DOMAIN;

export const REQUEST_HEADER_BOILERPLATE = {
'Content-Type': 'application/json',
origin: APP_BASE
};
24 changes: 5 additions & 19 deletions app/src/lib/remote-functions/collections.remote.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { form, query } from '$app/server';
import { API_BASE } from '$lib/global/config';
import { form } from '$app/server';
import { API_BASE, REQUEST_HEADER_BOILERPLATE } from '$lib/global/config';
import * as z from 'zod';
import { requireAuth } from './auth-check';
import { redirect } from '@sveltejs/kit';

const MakeCollectionForm = z.object({
name: z.string().min(3).max(100),
Expand All @@ -23,9 +22,7 @@ export const makeCollection = form(MakeCollectionForm, async ({ name, descriptio
const userId = requireAuth().id;
await fetch(`${API_BASE}/collections`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ userId, name, description })
});
});
Expand All @@ -34,9 +31,7 @@ export const deleteCollection = form(DeleteCollectionForm, async ({ collectionId
const userId = requireAuth().id;
await fetch(`${API_BASE}/collections/${collectionId}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ userId })
});
});
Expand All @@ -46,17 +41,8 @@ export const addOrRemoveReleaseFromCollection = form(
async ({ collectionId, releaseId, addOrRemove }) => {
await fetch(`${API_BASE}/collections/${collectionId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ releaseId, addOrRemove })
});
}
);

export const getCollection = query(z.string(), async (collectionId: string) => {
const response = await fetch(`${API_BASE}/collections/${collectionId}`);
if (!response.ok) throw redirect(302, '/me/collections');
const collection = await response.json();
return collection;
});
25 changes: 5 additions & 20 deletions app/src/lib/remote-functions/mixtapes.remote.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { form, query } from '$app/server';
import { API_BASE } from '$lib/global/config';
import { form } from '$app/server';
import { API_BASE, REQUEST_HEADER_BOILERPLATE } from '$lib/global/config';
import * as z from 'zod';
import { requireAuth } from './auth-check';
import type { MixtapeHydrated } from '../../../../shared/types/hydrated';
import { redirect } from '@sveltejs/kit';

const MakeMixtapeForm = z.object({
name: z.string().min(3).max(100),
Expand All @@ -15,20 +13,11 @@ const AddTrackToMixtape = z.object({
trackId: z.string()
});

export const getMixtape = query(z.string(), async (mixtapeId: string) => {
const response = await fetch(`${API_BASE}/mixtapes/${mixtapeId}`);
if (!response.ok) throw redirect(302, '/me/mixtapes');
const mixtape: MixtapeHydrated = await response.json();
return mixtape;
});

export const makeMixtape = form(MakeMixtapeForm, async ({ name, description }) => {
const userId = requireAuth().id;
await fetch(`${API_BASE}/mixtapes`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ userId, name, description })
});
});
Expand All @@ -37,19 +26,15 @@ export const deleteMixtape = form(z.object({ mixtapeId: z.string() }), async ({
const userId = requireAuth().id;
await fetch(`${API_BASE}/mixtapes/${mixtapeId}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ userId })
});
});

export const addTrackToMixtape = form(AddTrackToMixtape, async ({ mixtapeId, trackId }) => {
await fetch(`${API_BASE}/mixtapes/${mixtapeId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ trackId })
});
});
7 changes: 5 additions & 2 deletions app/src/lib/remote-functions/releases.remote.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { query } from '$app/server';
import { API_BASE } from '$lib/global/config';
import { API_BASE, REQUEST_HEADER_BOILERPLATE } from '$lib/global/config';
import * as z from 'zod';
import type { ReleaseHydrated } from '../../../../shared/types/hydrated';

export const getHydratedRelease = query(z.string(), async (releaseId: string) => {
const response = await fetch(`${API_BASE}/releases/${releaseId}`);
const response = await fetch(`${API_BASE}/releases/${releaseId}`, {
method: 'GET',
headers: REQUEST_HEADER_BOILERPLATE
});
if (!response.ok) throw new Error('Failed to fetch release');
const release: ReleaseHydrated = await response.json();
return release;
Expand Down
10 changes: 3 additions & 7 deletions app/src/lib/remote-functions/user.remote.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { form } from '$app/server';
import { API_BASE } from '$lib/global/config';
import { API_BASE, REQUEST_HEADER_BOILERPLATE } from '$lib/global/config';
import * as z from 'zod';
import { requireAuth } from './auth-check';

Expand All @@ -20,9 +20,7 @@ export const toggleFollowedArtist = form(

await fetch(`${API_BASE}/users/${userId}/following`, {
method: addOrRemove === 'remove' ? 'DELETE' : 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ artistId: artistID })
});
}
Expand All @@ -33,9 +31,7 @@ export const toggleLikedTrack = form(ToggleLikedTrackForm, async ({ trackId, add

await fetch(`${API_BASE}/users/${userId}/likes`, {
method: addOrRemove === 'remove' ? 'DELETE' : 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: REQUEST_HEADER_BOILERPLATE,
body: JSON.stringify({ trackId })
});
});
21 changes: 17 additions & 4 deletions app/src/routes/me/collections/[slug]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
<script lang="ts">
import SectionLink from '$lib/components/layout/SectionLink.svelte';
import ReleaseCardGrid from '$lib/components/ReleaseCardGrid.svelte';
import { deleteCollection, getCollection } from '$lib/remote-functions/collections.remote';
import { deleteCollection } from '$lib/remote-functions/collections.remote';
import type { Mixtape, User } from '../../../../../../shared/types/core';
import type { CollectionHydrated, TrackHydrated } from '../../../../../../shared/types/hydrated';
import type { Session } from '@supabase/supabase-js';

let { params } = $props();
let {
data
}: {
data: {
collection: CollectionHydrated;
session: Session;
profileData: User;
collections: CollectionHydrated[];
likedTracks: TrackHydrated[];
mixtapes: Mixtape[];
};
} = $props();

let collectionPromise = $derived(getCollection(params.slug));
let { id, name, description, releases } = $derived(await collectionPromise);
let { id, name, description, releases } = $derived(data.collection);
</script>

<svelte:head>
Expand Down
16 changes: 16 additions & 0 deletions app/src/routes/me/collections/[slug]/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { API_BASE } from '$lib/global/config';
import type { CollectionHydrated } from '../../../../../../shared/types/hydrated';

export const load = async ({ fetch, params }) => {
const collection: CollectionHydrated = await fetch(`${API_BASE}/collections/${params.slug}`).then(
(res) => res.json()
);
if (!collection)
return {
status: 404,
error: new Error('Not Found')
};
return {
collection
};
};
25 changes: 21 additions & 4 deletions app/src/routes/me/mixtapes/[slug]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
<script lang="ts">
import SectionLink from '$lib/components/layout/SectionLink.svelte';
import TracksTable from '$lib/components/releases/TracksTable.svelte';
import { deleteMixtape, getMixtape } from '$lib/remote-functions/mixtapes.remote';
import { deleteMixtape } from '$lib/remote-functions/mixtapes.remote';
import type { Session } from '@supabase/supabase-js';
import type { Mixtape, User } from '../../../../../../shared/types/core';
import type {
CollectionHydrated,
MixtapeHydrated,
TrackHydrated
} from '../../../../../../shared/types/hydrated';

let { params } = $props();
let {
data
}: {
data: {
mixtape: MixtapeHydrated;
session: Session;
profileData: User;
collections: CollectionHydrated[];
likedTracks: TrackHydrated[];
mixtapes: Mixtape[];
};
} = $props();

let mixtapePromise = $derived(getMixtape(params.slug));
let { id, name, description, tracks } = $derived(await mixtapePromise);
let { id, name, description, tracks } = $derived(data.mixtape);
</script>

<svelte:head>
Expand Down
16 changes: 16 additions & 0 deletions app/src/routes/me/mixtapes/[slug]/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { API_BASE } from '$lib/global/config';
import type { MixtapeHydrated } from '../../../../../../shared/types/hydrated';

export const load = async ({ fetch, params }) => {
const mixtape: MixtapeHydrated = await fetch(`${API_BASE}/mixtapes/${params.slug}`).then((res) =>
res.json()
);
if (!mixtape)
return {
status: 404,
error: new Error('Not Found')
};
return {
mixtape
};
};