initial commit

This commit is contained in:
2026-02-10 19:40:51 +01:00
commit 759e336956
62 changed files with 9682 additions and 0 deletions

34
packages/auth/.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules
# output
out
dist
*.tgz
# code coverage
coverage
*.lcov
# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# caches
.eslintcache
.cache
*.tsbuildinfo
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store

View File

@@ -0,0 +1,24 @@
{
"name": "@zendegi/auth",
"type": "module",
"exports": {
".": {
"default": "./src/index.ts"
},
"./*": {
"default": "./src/*.ts"
}
},
"scripts": {},
"dependencies": {
"@zendegi/db": "workspace:*",
"@zendegi/env": "workspace:*",
"better-auth": "catalog:",
"dotenv": "catalog:",
"zod": "catalog:"
},
"devDependencies": {
"@zendegi/config": "workspace:*",
"typescript": "catalog:"
}
}

View File

@@ -0,0 +1,19 @@
import { db } from "@zendegi/db";
import * as schema from "@zendegi/db/schema/auth";
import { env } from "@zendegi/env/server";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { tanstackStartCookies } from "better-auth/tanstack-start";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
schema: schema,
}),
trustedOrigins: [env.CORS_ORIGIN],
emailAndPassword: {
enabled: true,
},
plugins: [tanstackStartCookies()],
});

View File

@@ -0,0 +1,11 @@
{
"extends": "@zendegi/config/tsconfig.base.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist",
"composite": true,
"strictNullChecks": true
}
}

View File

@@ -0,0 +1,5 @@
{
"name": "@zendegi/config",
"version": "0.0.0",
"private": true
}

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ESNext"],
"verbatimModuleSyntax": true,
"strict": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["node"]
}
}

35
packages/db/.gitignore vendored Normal file
View File

@@ -0,0 +1,35 @@
# dependencies (bun install)
node_modules
# output
out
dist
*.tgz
/prisma/generated
# code coverage
coverage
*.lcov
# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# caches
.eslintcache
.cache
*.tsbuildinfo
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store

View File

@@ -0,0 +1,23 @@
name: zendegi
services:
postgres:
image: postgres
container_name: zendegi-postgres
environment:
POSTGRES_DB: zendegi
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
volumes:
- zendegi_postgres_data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
zendegi_postgres_data:

View File

@@ -0,0 +1,15 @@
import dotenv from "dotenv";
import { defineConfig } from "drizzle-kit";
dotenv.config({
path: "../../apps/web/.env",
});
export default defineConfig({
schema: "./src/schema",
out: "./src/migrations",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL || "",
},
});

35
packages/db/package.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "@zendegi/db",
"type": "module",
"exports": {
".": {
"default": "./src/index.ts"
},
"./*": {
"default": "./src/*.ts"
}
},
"scripts": {
"db:push": "drizzle-kit push",
"db:generate": "drizzle-kit generate",
"db:studio": "drizzle-kit studio",
"db:migrate": "drizzle-kit migrate",
"db:start": "docker compose up -d",
"db:watch": "docker compose up",
"db:stop": "docker compose stop",
"db:down": "docker compose down"
},
"dependencies": {
"@zendegi/env": "workspace:*",
"dotenv": "catalog:",
"drizzle-orm": "^0.45.1",
"pg": "^8.17.1",
"zod": "catalog:"
},
"devDependencies": {
"@types/pg": "^8.16.0",
"@zendegi/config": "workspace:*",
"drizzle-kit": "^0.31.8",
"typescript": "catalog:"
}
}

6
packages/db/src/index.ts Normal file
View File

@@ -0,0 +1,6 @@
import { env } from "@zendegi/env/server";
import { drizzle } from "drizzle-orm/node-postgres";
import * as schema from "./schema";
export const db = drizzle(env.DATABASE_URL, { schema });

View File

@@ -0,0 +1,93 @@
import { relations } from "drizzle-orm";
import { pgTable, text, timestamp, boolean, index } from "drizzle-orm/pg-core";
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified").default(false).notNull(),
image: text("image"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const session = pgTable(
"session",
{
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
},
(table) => [index("session_userId_idx").on(table.userId)],
);
export const account = pgTable(
"account",
{
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
},
(table) => [index("account_userId_idx").on(table.userId)],
);
export const verification = pgTable(
"verification",
{
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
},
(table) => [index("verification_identifier_idx").on(table.identifier)],
);
export const userRelations = relations(user, ({ many }) => ({
sessions: many(session),
accounts: many(account),
}));
export const sessionRelations = relations(session, ({ one }) => ({
user: one(user, {
fields: [session.userId],
references: [user.id],
}),
}));
export const accountRelations = relations(account, ({ one }) => ({
user: one(user, {
fields: [account.userId],
references: [user.id],
}),
}));

View File

@@ -0,0 +1,2 @@
export * from "./auth";
export {};

11
packages/db/tsconfig.json Normal file
View File

@@ -0,0 +1,11 @@
{
"extends": "@zendegi/config/tsconfig.base.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist",
"composite": true,
"strictNullChecks": true
}
}

20
packages/env/package.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "@zendegi/env",
"version": "0.0.0",
"private": true,
"type": "module",
"exports": {
"./server": "./src/server.ts",
"./web": "./src/web.ts"
},
"dependencies": {
"@t3-oss/env-core": "^0.13.1",
"dotenv": "catalog:",
"zod": "catalog:"
},
"devDependencies": {
"@types/node": "catalog:",
"@zendegi/config": "workspace:*",
"typescript": "catalog:"
}
}

15
packages/env/src/server.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
import "dotenv/config";
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";
export const env = createEnv({
server: {
DATABASE_URL: z.string().min(1),
BETTER_AUTH_SECRET: z.string().min(32),
BETTER_AUTH_URL: z.url(),
CORS_ORIGIN: z.url(),
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
},
runtimeEnv: process.env,
emptyStringAsUndefined: true,
});

9
packages/env/src/web.ts vendored Normal file
View File

@@ -0,0 +1,9 @@
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";
export const env = createEnv({
clientPrefix: "VITE_",
client: {},
runtimeEnv: (import.meta as any).env,
emptyStringAsUndefined: true,
});

6
packages/env/tsconfig.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "@zendegi/config/tsconfig.base.json",
"compilerOptions": {
"strictNullChecks": true
}
}