New API + API Token Updates
This commit is contained in:
327
src/db/schema.ts
327
src/db/schema.ts
@@ -1,135 +1,222 @@
|
||||
import { sqliteTable, text, integer, primaryKey, foreignKey } from 'drizzle-orm/sqlite-core';
|
||||
import { nanoid } from 'nanoid';
|
||||
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 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 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]
|
||||
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],
|
||||
}),
|
||||
}),
|
||||
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]
|
||||
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],
|
||||
}),
|
||||
}),
|
||||
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],
|
||||
}),
|
||||
}),
|
||||
clientFk: foreignKey({
|
||||
columns: [table.clientId],
|
||||
foreignColumns: [clients.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],
|
||||
}),
|
||||
}),
|
||||
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]
|
||||
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],
|
||||
}),
|
||||
}),
|
||||
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 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 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()),
|
||||
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(),
|
||||
),
|
||||
});
|
||||
|
||||
export const apiTokens = sqliteTable(
|
||||
"api_tokens",
|
||||
{
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
userId: text("user_id").notNull(),
|
||||
name: text("name").notNull(),
|
||||
token: text("token").notNull().unique(),
|
||||
scopes: text("scopes").notNull().default("*"),
|
||||
lastUsedAt: integer("last_used_at", { mode: "timestamp" }),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
|
||||
() => new Date(),
|
||||
),
|
||||
},
|
||||
(table: any) => ({
|
||||
userFk: foreignKey({
|
||||
columns: [table.userId],
|
||||
foreignColumns: [users.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user