feat(04-01): add tags schema with case-insensitive unique index
- Add tags table with nanoid PK and case-insensitive unique index on name - Add entry_tags junction table with composite PK and cascade deletes - Export lower() helper function for case-insensitive queries - Export Tag, NewTag, EntryTag types for TypeScript inference
This commit is contained in:
@@ -1,4 +1,11 @@
|
|||||||
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
|
import { sqliteTable, text, integer, uniqueIndex, primaryKey } from 'drizzle-orm/sqlite-core';
|
||||||
|
import { sql, type SQL } from 'drizzle-orm';
|
||||||
|
import type { AnySQLiteColumn } from 'drizzle-orm/sqlite-core';
|
||||||
|
|
||||||
|
// Helper function for case-insensitive indexing
|
||||||
|
export function lower(column: AnySQLiteColumn): SQL {
|
||||||
|
return sql`lower(${column})`;
|
||||||
|
}
|
||||||
|
|
||||||
// Entry types: 'task' (actionable) or 'thought' (reference)
|
// Entry types: 'task' (actionable) or 'thought' (reference)
|
||||||
export const entries = sqliteTable('entries', {
|
export const entries = sqliteTable('entries', {
|
||||||
@@ -36,3 +43,35 @@ export const images = sqliteTable('images', {
|
|||||||
|
|
||||||
export type Image = typeof images.$inferSelect;
|
export type Image = typeof images.$inferSelect;
|
||||||
export type NewImage = typeof images.$inferInsert;
|
export type NewImage = typeof images.$inferInsert;
|
||||||
|
|
||||||
|
// Tags table: reusable tags for organizing entries
|
||||||
|
export const tags = sqliteTable(
|
||||||
|
'tags',
|
||||||
|
{
|
||||||
|
id: text('id').primaryKey(), // nanoid
|
||||||
|
name: text('name').notNull(),
|
||||||
|
createdAt: text('created_at')
|
||||||
|
.notNull()
|
||||||
|
.$defaultFn(() => new Date().toISOString())
|
||||||
|
},
|
||||||
|
(table) => [uniqueIndex('tagNameUniqueIndex').on(lower(table.name))]
|
||||||
|
);
|
||||||
|
|
||||||
|
export type Tag = typeof tags.$inferSelect;
|
||||||
|
export type NewTag = typeof tags.$inferInsert;
|
||||||
|
|
||||||
|
// Junction table for many-to-many entry-tag relationship
|
||||||
|
export const entryTags = sqliteTable(
|
||||||
|
'entry_tags',
|
||||||
|
{
|
||||||
|
entryId: text('entry_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => entries.id, { onDelete: 'cascade' }),
|
||||||
|
tagId: text('tag_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => tags.id, { onDelete: 'cascade' })
|
||||||
|
},
|
||||||
|
(t) => [primaryKey({ columns: [t.entryId, t.tagId] })]
|
||||||
|
);
|
||||||
|
|
||||||
|
export type EntryTag = typeof entryTags.$inferSelect;
|
||||||
|
|||||||
Reference in New Issue
Block a user