mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-07 04:23:29 +00:00
[ENG-454] Spacedrive account stuff (#860)
* remove `"type": "module"` bs * Auth.js * plz build * get session endpoint
This commit is contained in:
parent
ea46e7736a
commit
14c3580f28
|
@ -1,8 +1,12 @@
|
|||
import 'dotenv/config';
|
||||
import { Config } from 'drizzle-kit';
|
||||
import { env } from './src/env';
|
||||
|
||||
// TODO: Using t3 env is too damn hard, thanks JS bs
|
||||
if (!process.env.DATABASE_URL) {
|
||||
throw new Error('DATABASE_URL is not set');
|
||||
}
|
||||
|
||||
export default {
|
||||
schema: ['./src/server/db.ts'],
|
||||
connectionString: env.DATABASE_URL
|
||||
connectionString: process.env.DATABASE_URL
|
||||
} satisfies Config;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { withContentlayer } from 'next-contentlayer';
|
||||
// Validate env on build
|
||||
import './src/env.js';
|
||||
const { withContentlayer } = require('next-contentlayer');
|
||||
|
||||
// Validate env on build // TODO: I wish we could do this so Vercel can warn us when we are wrong but it's too hard.
|
||||
// import './src/env.mjs';
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
|
@ -39,4 +40,4 @@ const nextConfig = {
|
|||
}
|
||||
};
|
||||
|
||||
export default withContentlayer(nextConfig);
|
||||
module.exports = withContentlayer(nextConfig);
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"name": "@sd/landing",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "contentlayer build && next build",
|
||||
|
@ -11,6 +10,7 @@
|
|||
"push": "drizzle-kit push:mysql"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/core": "^0.7.1",
|
||||
"@aws-sdk/client-ses": "^3.337.0",
|
||||
"@icons-pack/react-simple-icons": "^7.2.0",
|
||||
"@planetscale/database": "^1.7.0",
|
||||
|
@ -23,6 +23,7 @@
|
|||
"contentlayer": "^0.3.2",
|
||||
"drizzle-orm": "^0.26.0",
|
||||
"markdown-to-jsx": "^7.2.0",
|
||||
"md5": "^2.3.0",
|
||||
"next": "13.4.3",
|
||||
"next-contentlayer": "^0.3.2",
|
||||
"phosphor-react": "^1.4.1",
|
||||
|
@ -41,6 +42,7 @@
|
|||
"remark-math": "^5.1.1",
|
||||
"sharp": "^0.32.1",
|
||||
"tsparticles": "^2.9.3",
|
||||
"uuid": "^9.0.0",
|
||||
"zod": "^3.21.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
102
apps/landing/src/app/api/[...auth]/auth.ts
Normal file
102
apps/landing/src/app/api/[...auth]/auth.ts
Normal file
|
@ -0,0 +1,102 @@
|
|||
import { Auth, AuthConfig } from '@auth/core';
|
||||
import GitHubProvider from '@auth/core/providers/github';
|
||||
import { Session } from '@auth/core/types';
|
||||
// @ts-expect-error // TODO: No types cringe
|
||||
import md5 from 'md5';
|
||||
import { NextRequest } from 'next/server';
|
||||
import { env } from '~/env';
|
||||
import { accountsTable, db, sessionsTable, usersTable, verificationTokens } from '~/server/db';
|
||||
import { DrizzleAdapterMySQL } from './authjs-adapter-drizzle-mysql';
|
||||
|
||||
export type TSession = {
|
||||
user: {
|
||||
id: string;
|
||||
name?: string;
|
||||
email: string;
|
||||
image: string;
|
||||
};
|
||||
expires: Session['expires'];
|
||||
};
|
||||
|
||||
// function EmailProvider2(): EmailConfig {
|
||||
// return {
|
||||
// id: 'email',
|
||||
// type: 'email',
|
||||
// name: 'Email',
|
||||
// server: { host: 'localhost', port: 25, auth: { user: '', pass: '' } },
|
||||
// from: '',
|
||||
// maxAge: 24 * 60 * 60,
|
||||
// async sendVerificationRequest({ identifier: to, url: verificationLink }) {
|
||||
// await sendEmail(
|
||||
// to,
|
||||
// 'Sign in',
|
||||
// {
|
||||
// verification_link: verificationLink
|
||||
// },
|
||||
// loginEmailTemplate
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
function gravatarUrl(email: string) {
|
||||
return `https://www.gravatar.com/avatar/${md5(email.trim().toLowerCase())}?d=404&r=pg`;
|
||||
}
|
||||
|
||||
export const authOptions: AuthConfig = {
|
||||
trustHost: true,
|
||||
secret: env.AUTH_SECRET,
|
||||
adapter: DrizzleAdapterMySQL(
|
||||
db as any,
|
||||
{
|
||||
users: usersTable,
|
||||
sessions: sessionsTable,
|
||||
verificationTokens,
|
||||
accounts: accountsTable
|
||||
} as any
|
||||
) as any,
|
||||
providers: [
|
||||
GitHubProvider({
|
||||
clientId: env.GITHUB_CLIENT_ID!,
|
||||
clientSecret: env.GITHUB_SECRET!
|
||||
}) as any
|
||||
// EmailProvider2()
|
||||
],
|
||||
callbacks: {
|
||||
session: async ({ session, user }) => {
|
||||
const s: TSession = {
|
||||
expires: session.expires,
|
||||
user: {
|
||||
id: user.id,
|
||||
name: user.name ?? undefined,
|
||||
email: user.email!,
|
||||
image: user.image ?? gravatarUrl(user.email!)
|
||||
}
|
||||
};
|
||||
return s;
|
||||
}
|
||||
}
|
||||
// events: {
|
||||
// async createUser({ user }) {
|
||||
// await sendEmail(
|
||||
// user.email!,
|
||||
// 'Welcome to Fonedex!',
|
||||
// {
|
||||
// name: user.name
|
||||
// },
|
||||
// welcomeEmailHtml
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
export async function getServerSession(req: Request) {
|
||||
const newURL = new URL(req.url);
|
||||
newURL.pathname = '/api/auth/session';
|
||||
const sessionReq = new Request(newURL);
|
||||
|
||||
const cookieHeader = req.headers.get('cookie');
|
||||
if (cookieHeader) sessionReq.headers.set('cookie', cookieHeader);
|
||||
|
||||
return await (await Auth(sessionReq, authOptions)).json();
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
/**
|
||||
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: 16}}>
|
||||
* <p style={{fontWeight: "normal"}}>Official <a href="https://github.com/drizzle-team/drizzle-orm">Drizzle ORM</a> adapter for Auth.js / NextAuth.js.</p>
|
||||
* <a href="https://github.com/drizzle-team/drizzle-orm">
|
||||
* <img style={{display: "block"}} src="https://pbs.twimg.com/profile_images/1598308842391179266/CtXrfLnk_400x400.jpg" width="38" />
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ## Installation
|
||||
*
|
||||
* ```bash npm2yarn2pnpm
|
||||
* npm install next-auth drizzle-orm @next-auth/drizzle-adapter
|
||||
* npm install drizzle-kit --save-dev
|
||||
* ```
|
||||
*
|
||||
* @module @next-auth/drizzle-adapter
|
||||
*/
|
||||
import type { DbClient, Schema } from "./schema";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import type { Adapter } from "@auth/core/adapters";
|
||||
// @ts-expect-error
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
/**
|
||||
* ## Setup
|
||||
*
|
||||
* Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object:
|
||||
*
|
||||
* ```js title="pages/api/auth/[...nextauth].js"
|
||||
* import NextAuth from "next-auth"
|
||||
* import GoogleProvider from "next-auth/providers/google"
|
||||
* import { DrizzleAdapter } from "@next-auth/drizzle-adapter"
|
||||
* import { db } from "./db-schema"
|
||||
*
|
||||
* export default NextAuth({
|
||||
* adapter: DrizzleAdapter(db),
|
||||
* providers: [
|
||||
* GoogleProvider({
|
||||
* clientId: process.env.GOOGLE_CLIENT_ID,
|
||||
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||
* }),
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ## Advanced usage
|
||||
*
|
||||
* ### Create the Drizzle schema from scratch
|
||||
*
|
||||
* You'll need to create a database schema that includes the minimal schema for a `next-auth` adapter.
|
||||
* Be sure to use the Drizzle driver version that you're using for your project.
|
||||
*
|
||||
* > This schema is adapted for use in Drizzle and based upon our main [schema](https://authjs.dev/reference/adapters#models)
|
||||
*
|
||||
*
|
||||
* ```json title="db-schema.ts"
|
||||
*
|
||||
* import { integer, pgTable, text, primaryKey } from 'drizzle-orm/pg-core';
|
||||
* import { drizzle } from 'drizzle-orm/node-postgres';
|
||||
* import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
||||
* import { Pool } from 'pg'
|
||||
* import { ProviderType } from 'next-auth/providers';
|
||||
*
|
||||
* export const users = pgTable('users', {
|
||||
* id: text('id').notNull().primaryKey(),
|
||||
* name: text('name'),
|
||||
* email: text("email").notNull(),
|
||||
* emailVerified: integer("emailVerified"),
|
||||
* image: text("image"),
|
||||
* });
|
||||
*
|
||||
* export const accounts = pgTable("accounts", {
|
||||
* userId: text("userId").notNull().references(() => users.id, { onDelete: "cascade" }),
|
||||
* type: text("type").$type<ProviderType>().notNull(),
|
||||
* provider: text("provider").notNull(),
|
||||
* providerAccountId: text("providerAccountId").notNull(),
|
||||
* refresh_token: text("refresh_token"),
|
||||
* access_token: text("access_token"),
|
||||
* expires_at: integer("expires_at"),
|
||||
* token_type: text("token_type"),
|
||||
* scope: text("scope"),
|
||||
* id_token: text("id_token"),
|
||||
* session_state: text("session_state"),
|
||||
* }, (account) => ({
|
||||
* _: primaryKey(account.provider, account.providerAccountId)
|
||||
* }))
|
||||
*
|
||||
* export const sessions = pgTable("sessions", {
|
||||
* userId: text("userId").notNull().references(() => users.id, { onDelete: "cascade" }),
|
||||
* sessionToken: text("sessionToken").notNull().primaryKey(),
|
||||
* expires: integer("expires").notNull(),
|
||||
* })
|
||||
*
|
||||
* export const verificationTokens = pgTable("verificationToken", {
|
||||
* identifier: text("identifier").notNull(),
|
||||
* token: text("token").notNull(),
|
||||
* expires: integer("expires").notNull()
|
||||
* }, (vt) => ({
|
||||
* _: primaryKey(vt.identifier, vt.token)
|
||||
* }))
|
||||
*
|
||||
* const pool = new Pool({
|
||||
* connectionString: "YOUR_CONNECTION_STRING"
|
||||
* });
|
||||
*
|
||||
* export const db = drizzle(pool);
|
||||
*
|
||||
* migrate(db, { migrationsFolder: "./drizzle" })
|
||||
*
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
export function DrizzleAdapterMySQL(
|
||||
client: DbClient,
|
||||
{ users, sessions, verificationTokens, accounts }: Schema
|
||||
): Adapter {
|
||||
return {
|
||||
createUser: async (data) => {
|
||||
const id = uuid();
|
||||
|
||||
await client.insert(users).values({ ...data, id });
|
||||
|
||||
return client
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, id))
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
getUser: async (data) => {
|
||||
return (
|
||||
client
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, data))
|
||||
.then((res) => res[0]) ?? null
|
||||
);
|
||||
},
|
||||
getUserByEmail: async (data) => {
|
||||
return (
|
||||
client
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.email, data))
|
||||
.then((res) => res[0]) ?? null
|
||||
);
|
||||
},
|
||||
createSession: async (data) => {
|
||||
await client.insert(sessions).values(data);
|
||||
|
||||
return client
|
||||
.select()
|
||||
.from(sessions)
|
||||
.where(eq(sessions.sessionToken, data.sessionToken))
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
getSessionAndUser: async (data) => {
|
||||
return (
|
||||
client
|
||||
.select({
|
||||
session: sessions,
|
||||
user: users,
|
||||
})
|
||||
.from(sessions)
|
||||
.where(eq(sessions.sessionToken, data))
|
||||
.innerJoin(users, eq(users.id, sessions.userId))
|
||||
.then((res) => res[0]) ?? null
|
||||
);
|
||||
},
|
||||
updateUser: async (data) => {
|
||||
if (!data.id) {
|
||||
throw new Error("No user id.");
|
||||
}
|
||||
|
||||
await client.update(users).set(data).where(eq(users.id, data.id));
|
||||
|
||||
return client
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, data.id))
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
updateSession: async (data) => {
|
||||
await client
|
||||
.update(sessions)
|
||||
.set(data)
|
||||
.where(eq(sessions.sessionToken, data.sessionToken));
|
||||
|
||||
return client
|
||||
.select()
|
||||
.from(sessions)
|
||||
.where(eq(sessions.sessionToken, data.sessionToken))
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
linkAccount: async (rawAccount) => {
|
||||
await client
|
||||
.insert(accounts)
|
||||
.values(rawAccount)
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
getUserByAccount: async (account) => {
|
||||
const user =
|
||||
(await client
|
||||
.select()
|
||||
.from(users)
|
||||
.innerJoin(
|
||||
accounts,
|
||||
and(
|
||||
eq(accounts.providerAccountId, account.providerAccountId),
|
||||
eq(accounts.provider, account.provider)
|
||||
)
|
||||
)
|
||||
.then((res) => res[0])) ?? null;
|
||||
|
||||
return user?.users;
|
||||
},
|
||||
deleteSession: async (sessionToken) => {
|
||||
await client
|
||||
.delete(sessions)
|
||||
.where(eq(sessions.sessionToken, sessionToken));
|
||||
},
|
||||
createVerificationToken: async (token) => {
|
||||
await client.insert(verificationTokens).values(token);
|
||||
|
||||
return client
|
||||
.select()
|
||||
.from(verificationTokens)
|
||||
.where(eq(verificationTokens.identifier, token.identifier))
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
useVerificationToken: async (token) => {
|
||||
try {
|
||||
const deletedToken =
|
||||
(await client
|
||||
.select()
|
||||
.from(verificationTokens)
|
||||
.where(
|
||||
and(
|
||||
eq(verificationTokens.identifier, token.identifier),
|
||||
eq(verificationTokens.token, token.token)
|
||||
)
|
||||
)
|
||||
.then((res) => res[0])) ?? null;
|
||||
|
||||
await client
|
||||
.delete(verificationTokens)
|
||||
.where(
|
||||
and(
|
||||
eq(verificationTokens.identifier, token.identifier),
|
||||
eq(verificationTokens.token, token.token)
|
||||
)
|
||||
);
|
||||
|
||||
return deletedToken;
|
||||
} catch (err) {
|
||||
throw new Error("No verification token found.");
|
||||
}
|
||||
},
|
||||
deleteUser: async (id) => {
|
||||
await client
|
||||
.delete(users)
|
||||
.where(eq(users.id, id))
|
||||
.then((res) => res[0]);
|
||||
},
|
||||
unlinkAccount: async (account) => {
|
||||
await client
|
||||
.delete(accounts)
|
||||
.where(
|
||||
and(
|
||||
eq(accounts.providerAccountId, account.providerAccountId),
|
||||
eq(accounts.provider, account.provider)
|
||||
)
|
||||
);
|
||||
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import { ProviderType } from '@auth/core/providers';
|
||||
import { drizzle } from 'drizzle-orm/mysql2';
|
||||
import { int, mysqlTable, primaryKey, text, timestamp } from 'drizzle-orm/mysql-core';
|
||||
|
||||
// import mysql from "mysql2/promise";
|
||||
|
||||
export const users = mysqlTable('users', {
|
||||
id: text('id').notNull().primaryKey(),
|
||||
name: text('name'),
|
||||
email: text('email').notNull(),
|
||||
emailVerified: timestamp('emailVerified', { mode: 'date' }),
|
||||
image: text('image')
|
||||
});
|
||||
|
||||
export const accounts = mysqlTable(
|
||||
'accounts',
|
||||
{
|
||||
userId: text('userId')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
type: text('type').$type<ProviderType>().notNull(),
|
||||
provider: text('provider').notNull(),
|
||||
providerAccountId: text('providerAccountId').notNull(),
|
||||
refresh_token: text('refresh_token'),
|
||||
access_token: text('access_token'),
|
||||
expires_at: int('expires_at'),
|
||||
token_type: text('token_type'),
|
||||
scope: text('scope'),
|
||||
id_token: text('id_token'),
|
||||
session_state: text('session_state')
|
||||
},
|
||||
(account) => ({
|
||||
compoundKey: primaryKey(account.provider, account.providerAccountId)
|
||||
})
|
||||
);
|
||||
|
||||
export const sessions = mysqlTable('sessions', {
|
||||
sessionToken: text('sessionToken').notNull().primaryKey(),
|
||||
userId: text('userId')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
expires: timestamp('expires', { mode: 'date' }).notNull()
|
||||
});
|
||||
|
||||
export const verificationTokens = mysqlTable(
|
||||
'verificationToken',
|
||||
{
|
||||
identifier: text('identifier').notNull(),
|
||||
token: text('token').notNull(),
|
||||
expires: timestamp('expires', { mode: 'date' }).notNull()
|
||||
},
|
||||
(vt) => ({
|
||||
compoundKey: primaryKey(vt.identifier, vt.token)
|
||||
})
|
||||
);
|
||||
|
||||
export const db = drizzle(undefined as any); // We just want the types
|
||||
|
||||
export type DbClient = typeof db;
|
||||
|
||||
export type Schema = {
|
||||
users: typeof users;
|
||||
accounts: typeof accounts;
|
||||
sessions: typeof sessions;
|
||||
verificationTokens: typeof verificationTokens;
|
||||
};
|
9
apps/landing/src/app/api/[...auth]/route.ts
Normal file
9
apps/landing/src/app/api/[...auth]/route.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Auth } from '@auth/core';
|
||||
import { authOptions } from './auth';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
const handler = (req: Request) => Auth(req, authOptions);
|
||||
|
||||
export const GET = handler;
|
||||
export const POST = handler;
|
9
apps/landing/src/app/api/user/[pk]/route.ts
Normal file
9
apps/landing/src/app/api/user/[pk]/route.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { getServerSession } from '../../[...auth]/auth';
|
||||
|
||||
export async function GET(req: Request) {
|
||||
const session = await getServerSession(req);
|
||||
|
||||
// TODO: Get from Drizzle
|
||||
|
||||
return new Response(JSON.stringify(session));
|
||||
}
|
9
apps/landing/src/app/api/user/me/route.ts
Normal file
9
apps/landing/src/app/api/user/me/route.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { getServerSession } from '../../[...auth]/auth';
|
||||
|
||||
export async function GET(req: Request) {
|
||||
return new Response(JSON.stringify(await getServerSession(req)), {
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,17 +1,12 @@
|
|||
// @ts-check
|
||||
//
|
||||
// Has to be `.mjs` so it can be imported in `next.config.mjs`.
|
||||
// Next.js are so cringe for not having support for Typescript config files.
|
||||
//
|
||||
// Using `.mjs` with Drizzle Kit is seemingly impossible without `.ts` so we resort to `.js`.
|
||||
// Why does JS make this shit so hard, I just wanna import the file.
|
||||
//
|
||||
import { createEnv } from '@t3-oss/env-nextjs';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
DATABASE_URL: z.string().url(),
|
||||
AUTH_SECRET: z.string(),
|
||||
GITHUB_CLIENT_ID: z.string(),
|
||||
GITHUB_SECRET: z.string(),
|
||||
AWS_SES_ACCESS_KEY: z.string(),
|
||||
AWS_SES_SECRET_KEY: z.string(),
|
||||
AWS_SES_REGION: z.string(),
|
||||
|
@ -20,6 +15,9 @@ export const env = createEnv({
|
|||
client: {},
|
||||
runtimeEnv: {
|
||||
DATABASE_URL: process.env.DATABASE_URL,
|
||||
AUTH_SECRET: process.env.AUTH_SECRET,
|
||||
GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
|
||||
GITHUB_SECRET: process.env.GITHUB_SECRET,
|
||||
AWS_SES_ACCESS_KEY: process.env.AWS_SES_ACCESS_KEY,
|
||||
AWS_SES_SECRET_KEY: process.env.AWS_SES_SECRET_KEY,
|
||||
AWS_SES_REGION: process.env.AWS_SES_REGION,
|
|
@ -1,5 +1,6 @@
|
|||
import { ProviderType } from '@auth/core/providers';
|
||||
import { connect } from '@planetscale/database';
|
||||
import { mysqlTable, serial, timestamp, varchar } from 'drizzle-orm/mysql-core';
|
||||
import { int, mysqlTable, primaryKey, serial, timestamp, varchar } from 'drizzle-orm/mysql-core';
|
||||
import { drizzle } from 'drizzle-orm/planetscale-serverless';
|
||||
import { env } from '~/env';
|
||||
|
||||
|
@ -11,6 +12,64 @@ const dbConnection = connect({
|
|||
|
||||
export const db = drizzle(dbConnection);
|
||||
|
||||
// AuthJS Schema
|
||||
|
||||
// Planetscale moment
|
||||
const text = (name: string) =>
|
||||
varchar(name, {
|
||||
length: 255
|
||||
});
|
||||
|
||||
export const usersTable = mysqlTable('users', {
|
||||
id: text('id').notNull().primaryKey(),
|
||||
name: text('name'),
|
||||
email: text('email').notNull(),
|
||||
emailVerified: timestamp('emailVerified', { mode: 'date' }),
|
||||
image: text('image')
|
||||
});
|
||||
|
||||
export const accountsTable = mysqlTable(
|
||||
'accounts',
|
||||
{
|
||||
userId: text('userId').notNull(),
|
||||
// .references(() => users.id, { onDelete: "cascade" }),
|
||||
type: text('type').$type<ProviderType>().notNull(),
|
||||
provider: text('provider').notNull(),
|
||||
providerAccountId: text('providerAccountId').notNull(),
|
||||
refresh_token: text('refresh_token'),
|
||||
access_token: text('access_token'),
|
||||
expires_at: int('expires_at'),
|
||||
token_type: text('token_type'),
|
||||
scope: text('scope'),
|
||||
id_token: text('id_token'),
|
||||
session_state: text('session_state')
|
||||
},
|
||||
(account) => ({
|
||||
compoundKey: primaryKey(account.provider, account.providerAccountId)
|
||||
})
|
||||
);
|
||||
|
||||
export const sessionsTable = mysqlTable('sessions', {
|
||||
sessionToken: text('sessionToken').notNull().primaryKey(),
|
||||
userId: text('userId').notNull(),
|
||||
// .references(() => users.id, { onDelete: "cascade" }),
|
||||
expires: timestamp('expires', { mode: 'date' }).notNull()
|
||||
});
|
||||
|
||||
export const verificationTokens = mysqlTable(
|
||||
'verificationToken',
|
||||
{
|
||||
identifier: text('identifier').notNull(),
|
||||
token: text('token').notNull(),
|
||||
expires: timestamp('expires', { mode: 'date' }).notNull()
|
||||
},
|
||||
(vt) => ({
|
||||
compoundKey: primaryKey(vt.identifier, vt.token)
|
||||
})
|
||||
);
|
||||
|
||||
// Spacedrive Schema
|
||||
|
||||
export const waitlistTable = mysqlTable('waitlist', {
|
||||
id: serial('id').primaryKey(),
|
||||
cuid: varchar('cuid', {
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"src/env.js",
|
||||
"src/drizzle.config.ts",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
|
|
|
@ -125,6 +125,9 @@ importers:
|
|||
|
||||
apps/landing:
|
||||
dependencies:
|
||||
'@auth/core':
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1
|
||||
'@aws-sdk/client-ses':
|
||||
specifier: ^3.337.0
|
||||
version: 3.337.0
|
||||
|
@ -161,6 +164,9 @@ importers:
|
|||
markdown-to-jsx:
|
||||
specifier: ^7.2.0
|
||||
version: 7.2.0(react@18.2.0)
|
||||
md5:
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
next:
|
||||
specifier: 13.4.3
|
||||
version: 13.4.3(@babel/core@7.21.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
|
@ -215,6 +221,9 @@ importers:
|
|||
tsparticles:
|
||||
specifier: ^2.9.3
|
||||
version: 2.9.3
|
||||
uuid:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0
|
||||
zod:
|
||||
specifier: ^3.21.4
|
||||
version: 3.21.4
|
||||
|
@ -988,6 +997,22 @@ packages:
|
|||
'@jridgewell/gen-mapping': 0.3.3
|
||||
'@jridgewell/trace-mapping': 0.3.18
|
||||
|
||||
/@auth/core@0.7.1:
|
||||
resolution: {integrity: sha512-aAgzC/VlfnvxsFYp5Wau1pfIltRUBvfVxECR0imDPUznwXIkD9alvrai60tfImtPfXp1fnJpcKfiONpF5Rg8VQ==}
|
||||
peerDependencies:
|
||||
nodemailer: ^6.8.0
|
||||
peerDependenciesMeta:
|
||||
nodemailer:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@panva/hkdf': 1.1.1
|
||||
cookie: 0.5.0
|
||||
jose: 4.14.4
|
||||
oauth4webapi: 2.3.0
|
||||
preact: 10.11.3
|
||||
preact-render-to-string: 5.2.3(preact@10.11.3)
|
||||
dev: false
|
||||
|
||||
/@aw-web-design/x-default-browser@1.4.88:
|
||||
resolution: {integrity: sha512-AkEmF0wcwYC2QkhK703Y83fxWARttIWXDmQN8+cof8FmFZ5BRhnNXGymeb1S73bOCLfWjYELxtujL56idCN/XA==}
|
||||
hasBin: true
|
||||
|
@ -4439,7 +4464,7 @@ packages:
|
|||
magic-string: 0.27.0
|
||||
react-docgen-typescript: 2.2.2(typescript@4.9.4)
|
||||
typescript: 4.9.4
|
||||
vite: 4.2.0(less@4.1.3)
|
||||
vite: 4.2.0(@types/node@18.15.11)
|
||||
|
||||
/@jridgewell/gen-mapping@0.3.3:
|
||||
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
||||
|
@ -4914,6 +4939,10 @@ packages:
|
|||
engines: {node: '>=14'}
|
||||
dev: false
|
||||
|
||||
/@panva/hkdf@1.1.1:
|
||||
resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==}
|
||||
dev: false
|
||||
|
||||
/@pkgr/utils@2.4.0:
|
||||
resolution: {integrity: sha512-2OCURAmRtdlL8iUDTypMrrxfwe8frXTeXaxGsVOaYtc/wrUyk8Z/0OBetM7cdlsy7ZFWlMX72VogKeh+A4Xcjw==}
|
||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||
|
@ -6797,7 +6826,7 @@ packages:
|
|||
remark-slug: 6.1.0
|
||||
rollup: 3.21.7
|
||||
typescript: 4.9.4
|
||||
vite: 4.2.0(less@4.1.3)
|
||||
vite: 4.2.0(@types/node@18.15.11)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
@ -7258,7 +7287,7 @@ packages:
|
|||
react: 18.2.0
|
||||
react-docgen: 6.0.0-alpha.3
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
vite: 4.2.0(less@4.1.3)
|
||||
vite: 4.2.0(@types/node@18.15.11)
|
||||
transitivePeerDependencies:
|
||||
- '@preact/preset-vite'
|
||||
- supports-color
|
||||
|
@ -14455,6 +14484,10 @@ packages:
|
|||
resolution: {integrity: sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==}
|
||||
dev: false
|
||||
|
||||
/jose@4.14.4:
|
||||
resolution: {integrity: sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==}
|
||||
dev: false
|
||||
|
||||
/js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
|
@ -16900,6 +16933,10 @@ packages:
|
|||
/nullthrows@1.1.1:
|
||||
resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==}
|
||||
|
||||
/oauth4webapi@2.3.0:
|
||||
resolution: {integrity: sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==}
|
||||
dev: false
|
||||
|
||||
/ob1@0.73.7:
|
||||
resolution: {integrity: sha512-DfelfvR843KADhSUATGGhuepVMRcf5VQX+6MQLy5AW0BKDLlO7Usj6YZeAAZP7P86QwsoTxB0RXCFiA7t6S1IQ==}
|
||||
|
||||
|
@ -17690,6 +17727,19 @@ packages:
|
|||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
|
||||
/preact-render-to-string@5.2.3(preact@10.11.3):
|
||||
resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
|
||||
peerDependencies:
|
||||
preact: '>=10'
|
||||
dependencies:
|
||||
preact: 10.11.3
|
||||
pretty-format: 3.8.0
|
||||
dev: false
|
||||
|
||||
/preact@10.11.3:
|
||||
resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
|
||||
dev: false
|
||||
|
||||
/prebuild-install@7.1.1:
|
||||
resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -17828,6 +17878,10 @@ packages:
|
|||
ansi-styles: 5.2.0
|
||||
react-is: 18.2.0
|
||||
|
||||
/pretty-format@3.8.0:
|
||||
resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
|
||||
dev: false
|
||||
|
||||
/pretty-hrtime@1.0.3:
|
||||
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
@ -21573,6 +21627,11 @@ packages:
|
|||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/uuid@9.0.0:
|
||||
resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/uvu@0.5.6:
|
||||
resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -21806,7 +21865,6 @@ packages:
|
|||
rollup: 3.21.7
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/vite@4.2.0(less@4.1.3):
|
||||
resolution: {integrity: sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g==}
|
||||
|
|
Loading…
Reference in a new issue