feat: add @polar-sh/sveltekit (#539)

* feat add @polar-sh/sveltekit

* remove all lemonsqueezy text
This commit is contained in:
Rotimi Best
2025-01-09 01:30:01 +01:00
committed by GitHub
parent 4d4b1f12e2
commit 13fb58176f
46 changed files with 12475 additions and 10197 deletions
@@ -9,24 +9,10 @@ const CACHE_DURATION = 60 * 5; // 5 minutes
export async function POST({ setHeaders, request }) {
const { orgId } = await request.json();
const accessToken = request.headers.get('Authorization');
if (!orgId || !accessToken) {
if (!orgId) {
return json({ success: false, message: 'Request is missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
setHeaders({
'cache-control': `max-age=${CACHE_DURATION}`,
'content-type': 'application/json'
@@ -15,24 +15,10 @@ const CACHE_DURATION = 60 * 5; // 5 minutes
export async function POST({ setHeaders, request }) {
const { userId, courseId, orgId } = await request.json();
const accessToken = request.headers.get('Authorization');
if (!userId || !accessToken) {
if (!userId) {
return json({ success: false, message: 'Request is missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
setHeaders({
'cache-control': `max-age=${CACHE_DURATION}`,
'content-type': 'application/json'
@@ -1,19 +1,15 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import {
getConfigResponse,
addDomainToVercel,
getConfigResponse,
removeDomainFromVercelProject
} from '$lib/utils/services/org/domain';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { params } = await request.json();
const accessToken = request.headers.get('Authorization');
console.log('/GET api/domain', params);
if (!params?.key || !accessToken) {
if (!params?.key) {
return json({ success: false, message: 'Missing fields' }, { status: 400 });
}
@@ -21,18 +17,6 @@ export async function POST({ request }) {
return json({ success: false, message: 'Domain cannot contain classroomio' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
try {
switch (params.key) {
case 'verify_domain': {
@@ -1,29 +1,13 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, content, orgName, exerciseTitle } = await request.json();
const accessToken = request.headers.get('Authorization') || '';
if (!to || !content || !orgName) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const emailData = [
{
from: `"${orgName} (via ClassroomIO.com)" <[email protected]>`,
@@ -1,7 +1,7 @@
import { json } from '@sveltejs/kit';
import { getServerSupabase } from '$lib/utils/functions/supabase.server';
import { getFeedForNotification } from '$lib/utils/services/newsfeed/index';
import sendEmail from '$mail/sendEmail';
import { json } from '@sveltejs/kit';
const supabase = getServerSupabase();
@@ -67,25 +67,12 @@ const sendEmailNotification = async (feedId: string, authorId: string, comment?:
export async function POST({ request }) {
const { authorId, feedId, comment } = await request.json();
const accessToken = request.headers.get('Authorization') || '';
console.log('/POST api/email/course/newsfeed');
if (!authorId || !feedId || !accessToken) {
if (!authorId || !feedId) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
await sendEmailNotification(feedId, authorId, comment);
// TODO: Support sending to other platforms like telegram and discord
// sendDiscordNotification(); sendTelegramNotification();
@@ -1,31 +1,15 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
// Sends email to student when they successfully join a course
export async function POST({ request }) {
const { to, orgName, courseName } = await request.json();
const accessToken = request.headers.get('Authorization') || '';
console.log('/POST api/email/course/student_welcome', to, orgName);
if (!to || !orgName || !courseName) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const emailData = [
{
from: `"${orgName} (via ClassroomIO.com)" <[email protected]>`,
@@ -1,29 +1,13 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, content, orgName } = await request.json();
const accessToken = request.headers.get('Authorization') || '';
if (!to || !content || !orgName) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const emailData = [
{
from: `"${orgName} (via ClassroomIO.com)" <[email protected]>`,
@@ -1,12 +1,8 @@
import { json } from '@sveltejs/kit';
// import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
// const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, courseName, studentEmail, studentFullname } = await request.json();
// const accessToken = request.headers.get('Authorization') || '';
console.log(
'/POST api/email/course/teacher_student_buycourse',
to,
@@ -19,18 +15,6 @@ export async function POST({ request }) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
// let user;
// try {
// const { data } = await supabase.auth.getUser(accessToken);
// user = data.user;
// } catch (error) {
// console.error(error);
// }
// if (!user) {
// return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
// }
const emailData = [
{
from: `"ClassroomIO" <[email protected]>`,
@@ -1,30 +1,14 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, courseName, studentName, studentEmail } = await request.json();
const accessToken = request.headers.get('Authorization') || '';
console.log('/POST api/email/course/teacher_student_joined', to, courseName);
if (!to || !courseName || !studentName || !studentEmail) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const emailData = [
{
from: `"ClassroomIO" <[email protected]>`,
@@ -1,30 +1,14 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, name, orgName, courseName, orgSiteName } = await request.json();
const accessToken = request.headers.get('Authorization') || '';
console.log('/POST api/email/course/teacher_welcome', to, name, orgName);
if (!to || !name || !orgName || !courseName || !orgSiteName) {
return json({ success: false, message: 'Missing required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const origin = request.headers.get('origin');
const inviteLink = `${origin}/org/${orgSiteName}/courses`;
@@ -1,36 +1,20 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
// API to send invite to teacher
export async function POST({ request }) {
const body = await request.json();
const { org, email } = body;
const accessToken = request.headers.get('Authorization');
console.log('/POST api/email/invite', body);
if (!org || !Object.keys(org).length || !email || !accessToken) {
if (!org || !Object.keys(org).length || !email) {
return json(
{ success: false, message: 'Org data and Teacher name are required' },
{ status: 400 }
);
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const { id, name, siteName } = org;
const origin = request.headers.get('origin');
@@ -1,30 +1,14 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, profileId, orgSiteName, fullname } = await request.json();
const accessToken = request.headers.get('Authorization');
console.log('/POST api/email/verify_email', to, profileId);
if (!to || !profileId || !accessToken) {
if (!to || !profileId) {
return json({ success: false, message: 'Name and To are required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const origin = request.headers.get('origin');
const verificationData = JSON.stringify({
profileId,
@@ -1,30 +1,14 @@
import { json } from '@sveltejs/kit';
import { getSupabase } from '$lib/utils/functions/supabase';
import sendEmail from '$mail/sendEmail';
const supabase = getSupabase();
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
const { to, name } = await request.json();
const accessToken = request.headers.get('Authorization');
console.log('/POST api/email/welcome', to, name);
if (!to || !name || !accessToken) {
if (!to || !name) {
return json({ success: false, message: 'Name and To are required fields' }, { status: 400 });
}
let user;
try {
const { data } = await supabase.auth.getUser(accessToken);
user = data.user;
} catch (error) {
console.error(error);
}
if (!user) {
return json({ success: false, message: 'Unauthenticated user' }, { status: 401 });
}
const emailData = [
{
from: `"Best from ClassroomIO" <[email protected]>`,
@@ -1,13 +0,0 @@
import { selectedLocale } from '$lib/utils/functions/translations';
import { json, type RequestHandler } from '@sveltejs/kit';
export const POST = (async ({ request }) => {
try {
const body = await request.json();
selectedLocale.set(body.locale);
} catch (e) {
selectedLocale.set('en');
}
return json({ status: 200 });
}) satisfies RequestHandler;
@@ -1,38 +0,0 @@
import { json } from '@sveltejs/kit';
import { createCheckout } from '@lemonsqueezy/lemonsqueezy.js';
import { env } from '$env/dynamic/private';
import { configureLemonSqueezy } from '$lib/utils/services/lemonsqueezy';
export async function POST({ request }) {
const { email, name, orgId, productId, triggeredBy } = await request.json();
await configureLemonSqueezy();
if (!productId) {
return json({ success: false, message: 'Product Id is required' }, { status: 400 });
}
const checkoutData = {
email: email,
name: name,
custom: {
org_id: orgId,
triggered_by: `${triggeredBy}`
}
};
console.log({ checkoutData });
const { data } = await createCheckout(env.LEMON_SQUEEZY_STORE_ID, productId, {
checkoutData
});
const checkoutURL = data?.data.attributes.url;
console.log({ checkoutURL });
return json({
success: true,
checkoutURL
});
}
@@ -1,23 +0,0 @@
import { json } from '@sveltejs/kit';
import { getSubscription } from '@lemonsqueezy/lemonsqueezy.js';
import { configureLemonSqueezy } from '$lib/utils/services/lemonsqueezy';
export async function GET({ url }) {
const subscriptionId = url.searchParams.get('subscriptionId');
await configureLemonSqueezy();
if (!subscriptionId) {
return json({ success: false, message: 'Subscription id is required' }, { status: 400 });
}
const response = await getSubscription(subscriptionId);
const customerPortal = response?.data?.data?.attributes?.urls?.customer_portal;
console.log({ customerPortal });
return json({
success: true,
customerPortal
});
}
@@ -1,83 +0,0 @@
import { env } from '$env/dynamic/private';
import { getServerSupabase } from '$lib/utils/functions/supabase.server';
import { cancelOrgPlan, createOrgPlan } from '$lib/utils/services/org';
import { json } from '@sveltejs/kit';
import crypto from 'crypto';
import { PLAN } from 'shared/src/plans/constants';
export async function POST({ request }) {
try {
const supabase = getServerSupabase();
// Catch the event type
const clonedReq = request.clone();
const eventType = request.headers.get('X-Event-Name');
const body = await request.json();
// Check signature
const secret = env.LEMON_SQUEEZY_WEBHOOK_SECRET;
const hmac = crypto.createHmac('sha256', secret);
const digest = Buffer.from(hmac.update(await clonedReq.text()).digest('hex'), 'utf8');
const signature = Buffer.from(request.headers.get('X-Signature') || '', 'utf8');
if (!crypto.timingSafeEqual(digest, signature)) {
throw new Error('Invalid signature.');
}
console.log(body);
// Logic according to event
if (eventType === 'subscription_created' || eventType === 'subscription_resumed') {
const orgId = body.meta.custom_data.org_id;
const triggeredBy = body.meta.custom_data.triggered_by;
const subscriptionId = body.data.id;
const isSuccessful = body.data.attributes.status === 'active';
console.log({
subscriptionId,
triggeredBy,
isSuccessful
});
if (isSuccessful && orgId) {
const { data, error } = await createOrgPlan({
supabase,
subscriptionId,
orgId,
triggeredBy: parseInt(triggeredBy),
planName: PLAN.EARLY_ADOPTER,
data: body.data
});
if (error) console.error('Error creating org plan', error);
console.log('Create plan', data);
}
}
if (
['subscription_cancelled', 'subscription_expired', 'subscription_payment_refunded'].includes(
`${eventType}`
)
) {
const subscriptionId = body.data.id;
const { data, error } = await cancelOrgPlan({
subscriptionId,
data: body.data
});
if (error) console.error('Error canceling org plan', error);
console.log('Cancel plan', data);
}
return json({ message: 'Webhook received' });
} catch (err) {
console.error(err);
return json({ message: 'Server error' }, { status: 500 });
}
}
export function GET() {
return json({
success: true
});
}
@@ -1,24 +0,0 @@
import { json } from '@sveltejs/kit';
const downloadTranscript = async () => {};
const uploadTranscriptToS3 = async () => {};
export async function GET({ url }) {
const museFid = url.searchParams.get('museFid');
console.log('museFid');
// check the transcript table and see if we find a record
// if we find one
// check if downloaded = true
// if true
// return the transcript
// if false
// download the transcript from muse
// upload it to S3
// return the transcript
// if we dont
return json({ success: true, museFid });
}
@@ -0,0 +1,9 @@
import { dev } from '$app/environment';
import { env } from '$env/dynamic/private';
import { CustomerPortal } from '@polar-sh/sveltekit';
export const GET = CustomerPortal({
accessToken: env.POLAR_ACCESS_TOKEN,
getCustomerId: async (e) => e.url.searchParams.get('customerId')!,
server: dev ? 'sandbox' : 'production'
});
@@ -1,5 +1,6 @@
import { dev } from '$app/environment';
import { env } from '$env/dynamic/private';
import { Checkout } from 'polar-sveltekit';
import { Checkout } from '@polar-sh/sveltekit';
export const GET = ({ ...params }) => {
const metadata = JSON.parse(params.url.searchParams.get('metadata') ?? '{}');
@@ -7,7 +8,8 @@ export const GET = ({ ...params }) => {
const request = Checkout({
accessToken: env.POLAR_ACCESS_TOKEN,
successUrl
successUrl,
server: dev ? 'sandbox' : 'production'
});
return request(params);
@@ -2,7 +2,7 @@ import { env } from '$env/dynamic/private';
import { getServerSupabase } from '$lib/utils/functions/supabase.server';
import { cancelOrgPlan, createOrgPlan, updateOrgPlan } from '$lib/utils/services/org';
import type { PolarWebhookPayload } from '$lib/utils/types/polar';
import { Webhooks } from 'polar-sveltekit';
import { Webhooks } from '@polar-sh/sveltekit';
import { PLAN } from 'shared/src/plans/constants';
export const POST = Webhooks({
@@ -1,57 +0,0 @@
import { json } from '@sveltejs/kit';
export async function POST({ request }) {
try {
// Catch the event type
// const clonedReq = request.clone();
// const eventType = request.headers.get('X-Event-Name');
const body = await request.json();
// // Check signature
// const secret = LEMON_SQUEEZY_WEBHOOK_SECRET;
// const hmac = crypto.createHmac('sha256', secret);
// const digest = Buffer.from(hmac.update(await clonedReq.text()).digest('hex'), 'utf8');
// const signature = Buffer.from(request.headers.get('X-Signature') || '', 'utf8');
// if (!crypto.timingSafeEqual(digest, signature)) {
// throw new Error('Invalid signature.');
// }
console.log(body);
// Logic according to event
// if (eventType === 'order_created') {
// const orgId = body.meta.custom_data.org_id;
// const triggeredBy = body.meta.custom_data.triggered_by;
// const isSuccessful = body.data.attributes.status === 'paid';
// console.log({
// orgId,
// triggeredBy,
// isSuccessful
// });
// if (isSuccessful) {
// const { error } = await createOrgPlan({
// orgId,
// triggeredBy,
// planName: PLAN.EARLY_ADOPTER,
// data: body.data
// });
// if (error) console.error('Error creating org plan', error);
// }
// }
return json({ message: 'Webhook received' });
} catch (err) {
console.error(err);
return json({ message: 'Server error' }, { status: 500 });
}
}
export function GET() {
return json({
success: true
});
}