Skip to content

Commit

Permalink
Merge pull request #49 from magitools/feature/conditional-env
Browse files Browse the repository at this point in the history
Feature/conditional env
  • Loading branch information
matfire authored Jan 20, 2024
2 parents b21bf14 + b6f02a1 commit b6401f6
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 70 deletions.
25 changes: 17 additions & 8 deletions src/lib/server/r2.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import {
CLOUDFLARE_ACCOUNT_ID,
CLOUDFLARE_ACCESS_KEY_ID,
CLOUDFLARE_SECRET_ACCESS_KEY,
CLOUDFLARE_BUCKET_NAME,
CLOUDFLARE_BUCKET_URL
} from '$env/static/private';
import { env } from '$env/dynamic/private';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

export async function saveToBucket(data: Buffer, key: string) {
console.log('+ base64 generated and buffer initialize');
const {
CLOUDFLARE_ACCOUNT_ID,
CLOUDFLARE_ACCESS_KEY_ID,
CLOUDFLARE_SECRET_ACCESS_KEY,
CLOUDFLARE_BUCKET_NAME,
CLOUDFLARE_BUCKET_URL
} = env;
if (
!CLOUDFLARE_ACCOUNT_ID ||
!CLOUDFLARE_ACCESS_KEY_ID ||
!CLOUDFLARE_SECRET_ACCESS_KEY ||
!CLOUDFLARE_BUCKET_NAME ||
!CLOUDFLARE_BUCKET_URL
) {
throw new Error('Could not find Cloudflare configuration data');
}
const S3 = new S3Client({
region: 'auto',
endpoint: `https://${CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
Expand Down
6 changes: 4 additions & 2 deletions src/routes/(auth)/profile/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { db } from '$lib/server/db';
import { user, userImages } from '$lib/server/drizzle';
import { eq } from 'drizzle-orm';

export const load: PageServerLoad = async ({ locals }) => {
export const load: PageServerLoad = async ({ locals, parent }) => {
const session = await locals.auth.validate();
if (!session) throw redirect(302, '/login');
const parentData = await parent();

const savedImages = await db
.select()
.from(userImages)
Expand All @@ -18,7 +20,7 @@ export const load: PageServerLoad = async ({ locals }) => {
username: session.user.username,
email: session.user.email,
aiCredits: session.user.aiCredits,
savedImages
savedImages: parentData.enabledOptions?.storage ? savedImages : []
};
};

Expand Down
26 changes: 15 additions & 11 deletions src/routes/(auth)/profile/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@
<p>User id: {data.userId}</p>
<p>username: {data.username}</p>
<p>email: {data.email}</p>
<div class="flex items-center gap-4">
<p>AI Credits: {data.aiCredits}</p>
<Button href="/profile/recharge" class="btn variant-filled">Recharge</Button>
</div>
{#if data.enabledOptions.ai}
<div class="flex items-center gap-4">
<p>AI Credits: {data.aiCredits}</p>
<Button href="/profile/recharge" class="btn variant-filled">Recharge</Button>
</div>
{/if}
<form method="post" action="?/logout" use:enhance>
<Button variant="destructive" type="submit">Sign Out</Button>
</form>

<div class="">
<p>you have saved these images</p>
<div class="w-full flex flex-wrap gap-4 items-center">
{#each data.savedImages as image}
<img class="h-96 w-auto" src={image.url} alt="generated by an ai" />
{/each}
{#if data.enabledOptions.storage}
<div class="">
<p>you have saved these images</p>
<div class="w-full flex flex-wrap gap-4 items-center">
{#each data.savedImages as image}
<img class="h-96 w-auto" src={image.url} alt="generated by an ai" />
{/each}
</div>
</div>
</div>
{/if}
17 changes: 11 additions & 6 deletions src/routes/(auth)/profile/recharge/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { STRIPE_KEY, STRIPE_PRODUCT_ID } from '$env/static/private';
import type { ServerLoad } from '@sveltejs/kit';
import { env } from '$env/dynamic/private';
import { redirect, type ServerLoad } from '@sveltejs/kit';
import Stripe from 'stripe';
const stripe = new Stripe(STRIPE_KEY, {
apiVersion: '2023-08-16'
});
export const load: ServerLoad = async () => {
export const load: ServerLoad = async ({ parent }) => {
const data = await parent();
if (!data.enabledOptions.stripe) {
redirect(301, '/app');
}
const { STRIPE_KEY, STRIPE_PRODUCT_ID } = env;
const stripe = new Stripe(STRIPE_KEY, {
apiVersion: '2023-08-16'
});
const product = await stripe.products.retrieve(STRIPE_PRODUCT_ID);
let price;
if (product.default_price) {
Expand Down
26 changes: 25 additions & 1 deletion src/routes/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { env } from '$env/dynamic/private';
import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ locals }) => {
Expand All @@ -7,10 +8,33 @@ export const load: LayoutServerLoad = async ({ locals }) => {
authed: false
};
}
const enabledOptions = {
ai: typeof (env.OPENAI_ORG && env.OPENAI_TOKEN) === 'string',
stripe:
typeof (
env.STRIPE_KEY &&
env.STRIPE_CANCEL_URL &&
env.STRIPE_CHECKOUT_HOOK_SIGNATURE &&
env.STRIPE_PRICE_ID &&
env.STRIPE_PRODUCT_ID &&
env.STRIPE_SUCCESS_URL
) === 'string',
storage:
typeof (
env.CLOUDFLARE_ACCOUNT_ID &&
env.CLOUDFLARE_ACCESS_KEY_ID &&
env.CLOUDFLARE_BUCKET_URL &&
env.CLOUDFLARE_BUCKET_NAME &&
env.CLOUDFLARE_BUCKET_URL
) === 'string',
unsplash: typeof env.UNSPLASH_TOKEN === 'string',
giphy: typeof env.GIPHY_TOKEN === 'string'
};
return {
authed: session ? true : false,
userId: session.user.userId,
username: session.user.username,
email: session.user.email
email: session.user.email,
enabledOptions
};
};
11 changes: 7 additions & 4 deletions src/routes/api/giphy/+server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { GIPHY_TOKEN } from '$env/static/private';
import { env } from '$env/dynamic/private';
import { GiphyFetch } from '@giphy/js-fetch-api';
import { json, type RequestHandler } from '@sveltejs/kit';

const client = new GiphyFetch(GIPHY_TOKEN);
import { fail, json, type RequestHandler } from '@sveltejs/kit';

export const GET: RequestHandler = async ({ url }) => {
const { GIPHY_TOKEN } = env;
if (!GIPHY_TOKEN) {
throw fail(500, { message: 'could not find giphy configuration' });
}
const client = new GiphyFetch(GIPHY_TOKEN);
const query = url.searchParams.get('query');
const pageParam = url.searchParams.get('page');
const page = pageParam ? parseInt(pageParam) : 0;
Expand Down
9 changes: 6 additions & 3 deletions src/routes/api/openai/image/+server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { OPENAI_TOKEN, OPENAI_ORG } from '$env/static/private';
import { error, json, type RequestHandler } from '@sveltejs/kit';
import OpenAI from 'openai';
import { v4 as uuidv4 } from 'uuid';
import { db } from '$lib/server/db';
import { user, userImages } from '$lib/server/drizzle';
import { eq } from 'drizzle-orm';
import { saveToBucket } from '$lib/server/r2';
import { env } from '$env/dynamic/private';

export const GET: RequestHandler = async ({ locals, url }) => {
const session = await locals.auth.validate();
Expand All @@ -15,9 +15,12 @@ export const GET: RequestHandler = async ({ locals, url }) => {
if (session?.user?.aiCredits < 1) {
throw error(401, { message: 'not enough credits' });
}
if (!env.OPENAI_TOKEN || !env.OPENAI_ORG) {
throw error(500, { message: 'OpenAI configuration not found' });
}
const openai = new OpenAI({
organization: OPENAI_ORG,
apiKey: OPENAI_TOKEN
organization: env.OPENAI_ORG,
apiKey: env.OPENAI_TOKEN
});
const query = url.searchParams.get('query');
const amount = +(url.searchParams.get('amount') || 1);
Expand Down
6 changes: 5 additions & 1 deletion src/routes/api/openai/summary/+server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { OPENAI_ORG, OPENAI_TOKEN } from '$env/static/private';
import { user } from '$lib/server/drizzle';
import { db } from '$lib/server/db';
import { fail, type RequestHandler, json } from '@sveltejs/kit';
import { eq } from 'drizzle-orm';
import { decode } from 'gpt-tokenizer';
import { OpenAI } from 'openai';
import { env } from '$env/dynamic/private';

export const POST: RequestHandler = async ({ locals, request }) => {
const session = await locals.auth.validate();
Expand All @@ -15,6 +15,10 @@ export const POST: RequestHandler = async ({ locals, request }) => {
if (!content) {
throw fail(500, { message: 'invalid request' });
}
const { OPENAI_ORG, OPENAI_TOKEN } = env;
if (!OPENAI_ORG || !OPENAI_TOKEN) {
throw fail(500, { message: 'OpenAI configuration not found' });
}
const text = decode(content);
const openai = new OpenAI({
organization: OPENAI_ORG,
Expand Down
28 changes: 15 additions & 13 deletions src/routes/api/stripe/recharge/+server.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import {
STRIPE_CANCEL_URL,
STRIPE_KEY,
STRIPE_PRICE_ID,
STRIPE_SUCCESS_URL
} from '$env/static/private';
import { env } from '$env/dynamic/private';
import { error, json, type RequestHandler } from '@sveltejs/kit';
import Stripe from 'stripe';

const stripe = new Stripe(STRIPE_KEY, {
apiVersion: '2023-08-16'
});

export const POST: RequestHandler = async ({ locals, request }) => {
const session = await locals.auth.validate();
if (!session) {
Expand All @@ -20,10 +11,21 @@ export const POST: RequestHandler = async ({ locals, request }) => {
if (!quantity) {
throw error(500, { message: 'invalid data' });
}
if (
!env.STRIPE_CANCEL_URL ||
!env.STRIPE_KEY ||
!env.STRIPE_PRICE_ID ||
!env.STRIPE_SUCCESS_URL
) {
throw error(500, { message: 'stripe integration data not found' });
}
const stripe = new Stripe(env.STRIPE_KEY, {
apiVersion: '2023-08-16'
});
const paySession = await stripe.checkout.sessions.create({
line_items: [{ price: STRIPE_PRICE_ID, quantity }],
success_url: STRIPE_SUCCESS_URL,
cancel_url: STRIPE_CANCEL_URL,
line_items: [{ price: env.STRIPE_PRICE_ID, quantity }],
success_url: env.STRIPE_SUCCESS_URL,
cancel_url: env.STRIPE_CANCEL_URL,
client_reference_id: session.user.userId,
mode: 'payment'
});
Expand Down
10 changes: 7 additions & 3 deletions src/routes/api/unsplash/+server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { UNSPLASH_TOKEN } from '$env/static/private';
import { json, type RequestHandler } from '@sveltejs/kit';
import { env } from '$env/dynamic/private';
import { fail, json, type RequestHandler } from '@sveltejs/kit';
import { createApi } from 'unsplash-js';
const client = createApi({ accessKey: UNSPLASH_TOKEN });

export const GET: RequestHandler = async ({ url }) => {
const { UNSPLASH_TOKEN } = env;
if (!UNSPLASH_TOKEN) {
throw fail(500, { message: 'could not find unsplash configuration' });
}
const client = createApi({ accessKey: UNSPLASH_TOKEN });
const query = url.searchParams.get('query');
const page = url.searchParams.has('page') ? parseInt(url.searchParams.get('page')) : 1;
if (query) {
Expand Down
43 changes: 25 additions & 18 deletions src/routes/app/write/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -171,29 +171,36 @@
<Command.List>
<Command.Empty>No results found.</Command.Empty>
<Command.Group heading="Images">
<Command.Item
onSelect={() => {
giphyDialogOpen = !giphyDialogOpen;
commandDialogOpen = false;
}}
>Giphy
</Command.Item>
<Command.Item
onSelect={() => {
unsplashDialogOpen = !unsplashDialogOpen;
commandDialogOpen = false;
}}
>
Unsplash
</Command.Item>
{#if data.enabledOptions.giphy}
<Command.Item
onSelect={() => {
giphyDialogOpen = !giphyDialogOpen;
commandDialogOpen = false;
}}
>Giphy
</Command.Item>
{/if}
{#if data.enabledOptions.unsplash}
<Command.Item
onSelect={() => {
unsplashDialogOpen = !unsplashDialogOpen;
commandDialogOpen = false;
}}
>
Unsplash
</Command.Item>
{/if}
</Command.Group>
<Command.Separator />
</Command.List>
</Command.Dialog>

<Giphy on:addToDoc={addToDoc} bind:open={giphyDialogOpen} />
<Unsplash on:addToDoc={addToDoc} bind:open={unsplashDialogOpen} />

{#if data.enabledOptions.giphy}
<Giphy on:addToDoc={addToDoc} bind:open={giphyDialogOpen} />
{/if}
{#if data.enabledOptions.unsplash}
<Unsplash on:addToDoc={addToDoc} bind:open={unsplashDialogOpen} />
{/if}
<div class="flex h-full w-full flex-col relative p-4">
{#if loading}
<LoadingOverlay text={loadingText} />
Expand Down

0 comments on commit b6401f6

Please sign in to comment.