Skip to content

Commit

Permalink
feat(database): add db schema
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfriesen committed Dec 25, 2024
1 parent aec20db commit 9e0044c
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 0 deletions.
10 changes: 10 additions & 0 deletions apps/timer/server/database/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { timestamp } from 'drizzle-orm/pg-core';

export const timestampColumns = () => ({
createdAt: timestamp('created_at', { mode: 'date', withTimezone: true })
.notNull()
.defaultNow(),
updatedAt: timestamp('updated_at', { mode: 'date', withTimezone: true })
.notNull()
.$onUpdate(() => new Date()),
});
24 changes: 24 additions & 0 deletions apps/timer/server/database/organisation-member.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { pgTable, primaryKey, uuid, varchar } from 'drizzle-orm/pg-core';
import { timestampColumns } from './common';
import { organisations } from './organisation';
import { users } from './user';

export const organisationMembers = pgTable(
'organisationMember',
{
userId: uuid('user_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
organisationId: uuid('organisation_id')
.notNull()
.references(() => organisations.id, { onDelete: 'cascade' }),

role: varchar('role', { length: 10 }).notNull(),

...timestampColumns(),
},
(table) => [primaryKey({ columns: [table.userId, table.organisationId] })]
);

export type OrganisationMember = typeof organisationMembers.$inferSelect; // return type when queried
export type NewOrganisationMember = typeof organisationMembers.$inferInsert; // insert type
16 changes: 16 additions & 0 deletions apps/timer/server/database/organisation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { index, pgTable, uuid, varchar } from 'drizzle-orm/pg-core';
import { timestampColumns } from './common';

export const organisations = pgTable(
'organisation',
{
id: uuid('id').defaultRandom().notNull().primaryKey(),
name: varchar('name', { length: 150 }).notNull(),

...timestampColumns(),
},
(table) => [index().on(table.name)]
);

export type Organisation = typeof organisations.$inferSelect; // return type when queried
export type NewOrganisation = typeof organisations.$inferInsert; // insert type
27 changes: 27 additions & 0 deletions apps/timer/server/database/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { index, pgTable, text, uuid, varchar } from 'drizzle-orm/pg-core';
import { timestampColumns } from './common';
import { users } from './user';
import { organisations } from './organisation';

export const projects = pgTable(
'project',
{
id: uuid('id').defaultRandom().notNull().primaryKey(),

name: varchar('name', { length: 150 }).notNull(),
notes: text('notes').notNull().default(''),

organisationId: uuid('organisation_id')
.notNull()
.references(() => organisations.id, { onDelete: 'cascade' }),
userId: uuid('user_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),

...timestampColumns(),
},
(table) => [index('name_idx').on(table.name)]
);

export type Project = typeof projects.$inferSelect; // return type when queried
export type NewProject = typeof projects.$inferInsert; // insert type
8 changes: 8 additions & 0 deletions apps/timer/server/database/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export { sessions } from './session';
export { users } from './user';

export { times } from './time';
export { projects } from './project';

export { organisations } from './organisation';
export { organisationMembers } from './organisation-member';
21 changes: 21 additions & 0 deletions apps/timer/server/database/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { pgTable, timestamp, uuid, varchar } from 'drizzle-orm/pg-core';
import { timestampColumns } from './common';
import { users } from './user';

export const sessions = pgTable('session', {
id: varchar('id').primaryKey(),
expiresAt: timestamp('expires_at', {
withTimezone: true,
mode: 'date',
}).notNull(),
browser: varchar('browser', { length: 150 }),

userId: uuid('user_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),

createdAt: timestampColumns().createdAt,
});

export type Session = typeof sessions.$inferSelect; // return type when queried
export type NewSession = typeof sessions.$inferInsert; // insert type
48 changes: 48 additions & 0 deletions apps/timer/server/database/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
index,
integer,
pgTable,
serial,
text,
timestamp,
uuid,
} from 'drizzle-orm/pg-core';
import { timestampColumns } from './common';
import { projects } from './project';
import { users } from './user';
import { organisations } from './organisation';

export const times = pgTable(
'time',
{
id: serial('id').primaryKey(),

start: timestamp('start', {
withTimezone: true,
mode: 'date',
}).notNull(),
end: timestamp('end', {
withTimezone: true,
mode: 'date',
}).notNull(),
duration: integer('duration').notNull(),
notes: text('notes').notNull().default(''),

projectId: uuid('project_id').references(() => projects.id, {
onDelete: 'cascade',
}),

organisationId: uuid('organisation_id')
.notNull()
.references(() => organisations.id, { onDelete: 'cascade' }),
userId: uuid('user_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),

...timestampColumns(),
},
(table) => [index().on(table.start), index().on(table.end)]
);

export type Time = typeof times.$inferSelect; // return type when queried
export type NewTime = typeof times.$inferInsert; // insert type
31 changes: 31 additions & 0 deletions apps/timer/server/database/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
text,
pgTable,
uuid,
varchar,
boolean,
uniqueIndex,
} from 'drizzle-orm/pg-core';
import { timestampColumns } from './common';

export const users = pgTable(
'user',
{
id: uuid('id').defaultRandom().notNull().primaryKey(),

name: varchar('name', { length: 150 }).notNull(),
description: text('description').notNull().default(''),

email: text('email').notNull().unique(),
emailVerified: boolean('email_verified').notNull().default(false),

passwordHash: text('password_hash').notNull(),
passwordSalt: text('password_salt').notNull(),

...timestampColumns(),
},
(table) => [uniqueIndex().on(table.email)]
);

export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;

0 comments on commit 9e0044c

Please sign in to comment.