This commit is contained in:
2026-02-16 19:34:35 +00:00
commit 9ab0940ca4
784 changed files with 41710 additions and 0 deletions
@@ -0,0 +1,13 @@
import { config } from 'dotenv';
config({ path: '../../../.env' });
const { POSTGRES_URL } = process.env;
export default {
schema: './src/schema/index.ts',
out: './migrations',
dialect: 'postgresql',
dbCredentials: {
url: POSTGRES_URL,
},
};
@@ -0,0 +1,38 @@
CREATE TYPE "public"."user_roles" AS ENUM('Member', 'Admin', 'Owner', 'Super Admin');--> statement-breakpoint
CREATE TYPE "public"."user_status" AS ENUM('Unverified', 'Active', 'Prospect', 'Invited', 'Blocked', 'Banned', 'Deleted');--> statement-breakpoint
CREATE TABLE "users" (
"id" bigserial PRIMARY KEY NOT NULL,
"email" varchar(256) NOT NULL,
"password" varchar(256),
"role" "user_roles" DEFAULT 'Member',
"status" "user_status" DEFAULT 'Unverified',
"name" varchar(128),
"avatar" varchar(512000),
"password_changed_at" bigint,
CONSTRAINT "users_email_unique" UNIQUE("email")
);
--> statement-breakpoint
CREATE TABLE "passkeys" (
"id" bigserial PRIMARY KEY NOT NULL,
"email" varchar(256) NOT NULL,
"origin" varchar(256),
"credential_id" text,
"public_key" text,
"counter" integer DEFAULT 0 NOT NULL
);
--> statement-breakpoint
CREATE TABLE "passkey_challenges" (
"email" varchar(255) NOT NULL,
"origin" varchar(512) NOT NULL,
"challenge" varchar(512) NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "passkey_challenges_email_origin_pk" PRIMARY KEY("email","origin")
);
--> statement-breakpoint
CREATE TABLE "token_blacklist" (
"jti" varchar(64) PRIMARY KEY NOT NULL,
"expires_at" bigint NOT NULL
);
--> statement-breakpoint
CREATE INDEX "idx_passkey_challenges_created_at" ON "passkey_challenges" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "idx_token_blacklist_expires_at" ON "token_blacklist" USING btree ("expires_at");
@@ -0,0 +1,269 @@
{
"id": "b9130f42-0743-4c4b-aaf1-dce52e708e22",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(256)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"role": {
"name": "role",
"type": "user_roles",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'Member'"
},
"status": {
"name": "status",
"type": "user_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'Unverified'"
},
"name": {
"name": "name",
"type": "varchar(128)",
"primaryKey": false,
"notNull": false
},
"avatar": {
"name": "avatar",
"type": "varchar(512000)",
"primaryKey": false,
"notNull": false
},
"password_changed_at": {
"name": "password_changed_at",
"type": "bigint",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"users_email_unique": {
"name": "users_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.passkeys": {
"name": "passkeys",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(256)",
"primaryKey": false,
"notNull": true
},
"origin": {
"name": "origin",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"credential_id": {
"name": "credential_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"public_key": {
"name": "public_key",
"type": "text",
"primaryKey": false,
"notNull": false
},
"counter": {
"name": "counter",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.passkey_challenges": {
"name": "passkey_challenges",
"schema": "",
"columns": {
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"origin": {
"name": "origin",
"type": "varchar(512)",
"primaryKey": false,
"notNull": true
},
"challenge": {
"name": "challenge",
"type": "varchar(512)",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"idx_passkey_challenges_created_at": {
"name": "idx_passkey_challenges_created_at",
"columns": [
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"passkey_challenges_email_origin_pk": {
"name": "passkey_challenges_email_origin_pk",
"columns": [
"email",
"origin"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.token_blacklist": {
"name": "token_blacklist",
"schema": "",
"columns": {
"jti": {
"name": "jti",
"type": "varchar(64)",
"primaryKey": true,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "bigint",
"primaryKey": false,
"notNull": true
}
},
"indexes": {
"idx_token_blacklist_expires_at": {
"name": "idx_token_blacklist_expires_at",
"columns": [
{
"expression": "expires_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.user_roles": {
"name": "user_roles",
"schema": "public",
"values": [
"Member",
"Admin",
"Owner",
"Super Admin"
]
},
"public.user_status": {
"name": "user_status",
"schema": "public",
"values": [
"Unverified",
"Active",
"Prospect",
"Invited",
"Blocked",
"Banned",
"Deleted"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1770915839349,
"tag": "0000_broken_gauntlet",
"breakpoints": true
}
]
}
+25
View File
@@ -0,0 +1,25 @@
{
"name": "officerdb",
"version": "0.0.1",
"main": "src/index.ts",
"type": "module",
"exports": {
".": "./src/index.ts",
"./types": "./src/types.ts"
},
"license": "MIT",
"scripts": {
"generate": "bun x drizzle-kit generate",
"push": "bun x drizzle-kit push && bun run sps",
"studio": "bun x drizzle-kit studio",
"sps": "./run_migrations_sp.sh"
},
"dependencies": {
"definitions": "workspace:*",
"drizzle-orm": "^0.45.1",
"postgres": "^3.4.5"
},
"devDependencies": {
"drizzle-kit": "^0.31.8"
}
}
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
# Run all stored procedure migrations in order
# This script applies SQL files from the stored-procedures directory to the statistics database
# It parses the POSTGRES_URL from the root .env file
set -e
# Find the root .env file
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../../../.env"
MIGRATIONS_DIR="$SCRIPT_DIR/src/stored-procedures"
if [ ! -f "$ENV_FILE" ]; then
echo "Error: .env file not found at $ENV_FILE"
exit 1
fi
# Parse POSTGRES_URL from .env and strip quotes and carriage returns
POSTGRES_URL=$(grep "^POSTGRES_URL=" "$ENV_FILE" | cut -d'=' -f2- | sed 's/^"//;s/"$//' | tr -d '\r\n')
if [ -z "$POSTGRES_URL" ]; then
echo "Error: POSTGRES_URL not found in .env file"
exit 1
fi
# Parse PostgreSQL connection string
# Format: postgres://user:password@host:port/database
DB_USER=$(printf '%s' "$POSTGRES_URL" | sed -E 's|postgres://([^:]+):.*|\1|')
DB_PASSWORD=$(printf '%s' "$POSTGRES_URL" | sed -E 's|.*://[^:]+:([^@]+)@.*|\1|')
DB_HOST=$(printf '%s' "$POSTGRES_URL" | sed -E 's|.*@([^:]+):.*|\1|')
DB_PORT=$(printf '%s' "$POSTGRES_URL" | sed -E 's|.*@[^:]+:([0-9]+)/.*|\1|')
DB_NAME=$(printf '%s' "$POSTGRES_URL" | sed -E 's|.*:[0-9]+/([^?]+).*|\1|')
echo "Running stored procedure migrations from: $MIGRATIONS_DIR"
echo "Database: postgres://$DB_USER@$DB_HOST:$DB_PORT/$DB_NAME"
# Get all .sql files sorted by name
MIGRATIONS=$(find "$MIGRATIONS_DIR" -name "*.sql" -type f | sort)
if [ -z "$MIGRATIONS" ]; then
echo "No migrations found in $MIGRATIONS_DIR"
exit 0
fi
for migration_file in $MIGRATIONS; do
migration_name=$(basename "$migration_file")
echo "Applying migration: $migration_name"
# Execute the migration file with password from environment
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -p "$DB_PORT" -f "$migration_file"
if [ $? -eq 0 ]; then
echo "✓ Successfully applied: $migration_name"
else
echo "✗ Failed to apply: $migration_name"
exit 1
fi
done
echo "All stored procedure migrations completed successfully!"
+15
View File
@@ -0,0 +1,15 @@
import { config } from 'dotenv';
config({ path: '../../../../.env' });
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as Schema from './schema';
export * from './schema';
export * from 'drizzle-orm';
const { POSTGRES_URL } = process.env;
console.log('POSTGRES_URL', POSTGRES_URL);
const pgClient = postgres(POSTGRES_URL!);
const officerdb = drizzle(pgClient, { schema: Schema });
export { officerdb, pgClient };
@@ -0,0 +1,4 @@
export * from './users';
export * from './passkeys';
export * from './passkey-challenges';
export * from './token-blacklist';
@@ -0,0 +1,15 @@
import { pgTable, varchar, timestamp, index, primaryKey } from 'drizzle-orm/pg-core';
export const PasskeyChallenges = pgTable(
'passkey_challenges',
{
email: varchar('email', { length: 255 }).notNull(),
origin: varchar('origin', { length: 512 }).notNull(),
challenge: varchar('challenge', { length: 512 }).notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
},
(table) => [
primaryKey({ columns: [table.email, table.origin] }),
index('idx_passkey_challenges_created_at').on(table.createdAt),
],
);
@@ -0,0 +1,20 @@
import { pgTable, varchar, text, integer } from 'drizzle-orm/pg-core';
import { bigserial } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
import { Users } from './users';
export const Passkeys = pgTable('passkeys', {
id: bigserial('id', { mode: 'number' }).primaryKey(),
email: varchar('email', { length: 256 }).notNull(),
origin: varchar('origin', { length: 256 }),
credentialId: text('credential_id'),
publicKey: text('public_key'),
counter: integer('counter').notNull().default(0),
});
export const PasskeysRelations = relations(Passkeys, ({ one }) => ({
user: one(Users, {
fields: [Passkeys.email],
references: [Users.email],
}),
}));
@@ -0,0 +1,10 @@
import { pgTable, varchar, bigint, index } from 'drizzle-orm/pg-core';
export const TokenBlacklist = pgTable(
'token_blacklist',
{
jti: varchar('jti', { length: 64 }).primaryKey(),
expiresAt: bigint('expires_at', { mode: 'number' }).notNull(),
},
(table) => [index('idx_token_blacklist_expires_at').on(table.expiresAt)],
);
@@ -0,0 +1,23 @@
import { pgTable, pgEnum, varchar } from 'drizzle-orm/pg-core';
import { bigint, bigserial } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
import { Passkeys } from './passkeys';
import { USER_STATUSES, USER_ROLES } from 'definitions';
export const userStatusEnum = pgEnum('user_status', USER_STATUSES);
export const userRolesEnum = pgEnum('user_roles', USER_ROLES);
export const Users = pgTable('users', {
id: bigserial('id', { mode: 'number' }).primaryKey(),
email: varchar('email', { length: 256 }).unique().notNull(),
password: varchar('password', { length: 256 }),
role: userRolesEnum('role').default(USER_ROLES[0]),
status: userStatusEnum('status').default(USER_STATUSES[0]),
name: varchar('name', { length: 128 }),
avatar: varchar('avatar', { length: 512000 }),
passwordChangedAt: bigint('password_changed_at', { mode: 'number' }),
});
export const UsersRelations = relations(Users, ({ many }) => ({
passkeys: many(Passkeys),
}));
@@ -0,0 +1,27 @@
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_class
WHERE relname = 'passkey_challenges'
AND relpersistence = 'p'
) THEN
ALTER TABLE passkey_challenges SET UNLOGGED;
RAISE NOTICE 'passkey_challenges set to UNLOGGED';
ELSE
RAISE NOTICE 'passkey_challenges already UNLOGGED or does not exist';
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_class
WHERE relname = 'token_blacklist'
AND relpersistence = 'p'
) THEN
ALTER TABLE token_blacklist SET UNLOGGED;
RAISE NOTICE 'token_blacklist set to UNLOGGED';
ELSE
RAISE NOTICE 'token_blacklist already UNLOGGED or does not exist';
END IF;
END $$;
+21
View File
@@ -0,0 +1,21 @@
import * as Schema from './schema';
// Auth
export type PasskeySelect = typeof Schema.Passkeys.$inferSelect;
export type PasskeyInsert = typeof Schema.Passkeys.$inferInsert;
export type Passkey = PasskeySelect & {
user: User;
};
export type UserSelect = typeof Schema.Users.$inferSelect;
export type UserInsert = typeof Schema.Users.$inferInsert;
export type User = UserSelect & {
passkeys: Passkey[];
};
// Security
export type PasskeyChallenge = typeof Schema.PasskeyChallenges.$inferSelect;
export type PasskeyChallengeInsert = typeof Schema.PasskeyChallenges.$inferInsert;
export type TokenBlacklist = typeof Schema.TokenBlacklist.$inferSelect;
export type TokenBlacklistInsert = typeof Schema.TokenBlacklist.$inferInsert;