First pass
This commit is contained in:
135
src/db/schema.ts
Normal file
135
src/db/schema.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { sqliteTable, text, integer, primaryKey, foreignKey } from 'drizzle-orm/sqlite-core';
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
export const users = sqliteTable('users', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
email: text('email').notNull().unique(),
|
||||
passwordHash: text('password_hash').notNull(),
|
||||
name: text('name').notNull(),
|
||||
isSiteAdmin: integer('is_site_admin', { mode: 'boolean' }).default(false),
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export const organizations = sqliteTable('organizations', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
name: text('name').notNull(),
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export const members = sqliteTable('members', {
|
||||
userId: text('user_id').notNull(),
|
||||
organizationId: text('organization_id').notNull(),
|
||||
role: text('role').notNull().default('member'), // 'owner', 'admin', 'member'
|
||||
joinedAt: integer('joined_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
}, (table: any) => ({
|
||||
pk: primaryKey({ columns: [table.userId, table.organizationId] }),
|
||||
userFk: foreignKey({
|
||||
columns: [table.userId],
|
||||
foreignColumns: [users.id]
|
||||
}),
|
||||
orgFk: foreignKey({
|
||||
columns: [table.organizationId],
|
||||
foreignColumns: [organizations.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const clients = sqliteTable('clients', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
organizationId: text('organization_id').notNull(),
|
||||
name: text('name').notNull(),
|
||||
email: text('email'),
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
}, (table: any) => ({
|
||||
orgFk: foreignKey({
|
||||
columns: [table.organizationId],
|
||||
foreignColumns: [organizations.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const categories = sqliteTable('categories', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
organizationId: text('organization_id').notNull(),
|
||||
name: text('name').notNull(),
|
||||
color: text('color'),
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
}, (table: any) => ({
|
||||
orgFk: foreignKey({
|
||||
columns: [table.organizationId],
|
||||
foreignColumns: [organizations.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const timeEntries = sqliteTable('time_entries', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
userId: text('user_id').notNull(),
|
||||
organizationId: text('organization_id').notNull(),
|
||||
clientId: text('client_id').notNull(),
|
||||
categoryId: text('category_id').notNull(),
|
||||
startTime: integer('start_time', { mode: 'timestamp' }).notNull(),
|
||||
endTime: integer('end_time', { mode: 'timestamp' }),
|
||||
description: text('description'),
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
}, (table: any) => ({
|
||||
userFk: foreignKey({
|
||||
columns: [table.userId],
|
||||
foreignColumns: [users.id]
|
||||
}),
|
||||
orgFk: foreignKey({
|
||||
columns: [table.organizationId],
|
||||
foreignColumns: [organizations.id]
|
||||
}),
|
||||
clientFk: foreignKey({
|
||||
columns: [table.clientId],
|
||||
foreignColumns: [clients.id]
|
||||
}),
|
||||
categoryFk: foreignKey({
|
||||
columns: [table.categoryId],
|
||||
foreignColumns: [categories.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const tags = sqliteTable('tags', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
organizationId: text('organization_id').notNull(),
|
||||
name: text('name').notNull(),
|
||||
color: text('color'),
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
}, (table: any) => ({
|
||||
orgFk: foreignKey({
|
||||
columns: [table.organizationId],
|
||||
foreignColumns: [organizations.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const timeEntryTags = sqliteTable('time_entry_tags', {
|
||||
timeEntryId: text('time_entry_id').notNull(),
|
||||
tagId: text('tag_id').notNull(),
|
||||
}, (table: any) => ({
|
||||
pk: primaryKey({ columns: [table.timeEntryId, table.tagId] }),
|
||||
timeEntryFk: foreignKey({
|
||||
columns: [table.timeEntryId],
|
||||
foreignColumns: [timeEntries.id]
|
||||
}),
|
||||
tagFk: foreignKey({
|
||||
columns: [table.tagId],
|
||||
foreignColumns: [tags.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const sessions = sqliteTable('sessions', {
|
||||
id: text('id').primaryKey(),
|
||||
userId: text('user_id').notNull(),
|
||||
expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull(),
|
||||
}, (table: any) => ({
|
||||
userFk: foreignKey({
|
||||
columns: [table.userId],
|
||||
foreignColumns: [users.id]
|
||||
})
|
||||
}));
|
||||
|
||||
export const siteSettings = sqliteTable('site_settings', {
|
||||
id: text('id').primaryKey().$defaultFn(() => nanoid()),
|
||||
key: text('key').notNull().unique(),
|
||||
value: text('value').notNull(),
|
||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
|
||||
});
|
||||
Reference in New Issue
Block a user