From e418d00553cbea9af02c9ab70f1e9e3f7dbf09b2 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sat, 18 Apr 2026 04:27:05 +0800 Subject: [PATCH] feat(db): add multitenant profile, posts, timeline, and rss tables Made-with: Cursor --- .../drizzle-pkg/database/sqlite/schema/auth.ts | 7 + .../drizzle-pkg/database/sqlite/schema/content.ts | 46 ++ packages/drizzle-pkg/database/sqlite/schema/rss.ts | 50 ++ packages/drizzle-pkg/lib/schema/content.ts | 1 + packages/drizzle-pkg/lib/schema/rss.ts | 1 + .../0001_add-multitenant-content-rss.sql | 73 ++ .../drizzle-pkg/migrations/meta/0001_snapshot.json | 793 +++++++++++++++++++++ packages/drizzle-pkg/migrations/meta/_journal.json | 7 + 8 files changed, 978 insertions(+) create mode 100644 packages/drizzle-pkg/database/sqlite/schema/content.ts create mode 100644 packages/drizzle-pkg/database/sqlite/schema/rss.ts create mode 100644 packages/drizzle-pkg/lib/schema/content.ts create mode 100644 packages/drizzle-pkg/lib/schema/rss.ts create mode 100644 packages/drizzle-pkg/migrations/0001_add-multitenant-content-rss.sql create mode 100644 packages/drizzle-pkg/migrations/meta/0001_snapshot.json diff --git a/packages/drizzle-pkg/database/sqlite/schema/auth.ts b/packages/drizzle-pkg/database/sqlite/schema/auth.ts index 1292cc5..df390d9 100644 --- a/packages/drizzle-pkg/database/sqlite/schema/auth.ts +++ b/packages/drizzle-pkg/database/sqlite/schema/auth.ts @@ -7,6 +7,13 @@ export const users = sqliteTable("users", { nickname: text(), password: text().notNull(), avatar: text(), + role: text().notNull().default("user"), + status: text().notNull().default("active"), + publicSlug: text("public_slug").unique(), + bioMarkdown: text("bio_markdown"), + bioVisibility: text("bio_visibility").notNull().default("private"), + socialLinksJson: text("social_links_json").notNull().default("[]"), + avatarVisibility: text("avatar_visibility").notNull().default("private"), createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(), updatedAt: integer("updated_at", { mode: "timestamp_ms" }) .defaultNow() diff --git a/packages/drizzle-pkg/database/sqlite/schema/content.ts b/packages/drizzle-pkg/database/sqlite/schema/content.ts new file mode 100644 index 0000000..de68be8 --- /dev/null +++ b/packages/drizzle-pkg/database/sqlite/schema/content.ts @@ -0,0 +1,46 @@ +import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core"; + +import { users } from "./auth"; + +export const posts = sqliteTable( + "posts", + { + id: integer().primaryKey(), + userId: integer("user_id") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + title: text().notNull(), + slug: text().notNull(), + bodyMarkdown: text("body_markdown").notNull(), + excerpt: text().notNull(), + coverUrl: text("cover_url"), + tagsJson: text("tags_json").notNull().default("[]"), + publishedAt: integer("published_at", { mode: "timestamp_ms" }), + visibility: text().notNull().default("private"), + shareToken: text("share_token"), + createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(), + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .defaultNow() + .$onUpdate(() => new Date()) + .notNull(), + }, + (table) => [uniqueIndex("posts_user_id_slug_unique").on(table.userId, table.slug)], +); + +export const timelineEvents = sqliteTable("timeline_events", { + id: integer().primaryKey(), + userId: integer("user_id") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + occurredOn: integer("occurred_on", { mode: "timestamp_ms" }).notNull(), + title: text().notNull(), + bodyMarkdown: text("body_markdown"), + linkUrl: text("link_url"), + visibility: text().notNull().default("private"), + shareToken: text("share_token"), + createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(), + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .defaultNow() + .$onUpdate(() => new Date()) + .notNull(), +}); diff --git a/packages/drizzle-pkg/database/sqlite/schema/rss.ts b/packages/drizzle-pkg/database/sqlite/schema/rss.ts new file mode 100644 index 0000000..6ace0a1 --- /dev/null +++ b/packages/drizzle-pkg/database/sqlite/schema/rss.ts @@ -0,0 +1,50 @@ +import { sql } from "drizzle-orm"; +import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core"; + +import { users } from "./auth"; + +export const rssFeeds = sqliteTable( + "rss_feeds", + { + id: integer().primaryKey(), + userId: integer("user_id") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + feedUrl: text("feed_url").notNull(), + title: text(), + siteUrl: text("site_url"), + lastFetchedAt: integer("last_fetched_at", { mode: "timestamp_ms" }), + lastError: text("last_error"), + pollIntervalMinutes: integer("poll_interval_minutes"), + createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(), + }, + (table) => [uniqueIndex("rss_feeds_user_id_feed_url_unique").on(table.userId, table.feedUrl)], +); + +export const rssItems = sqliteTable( + "rss_items", + { + id: integer().primaryKey(), + userId: integer("user_id") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + feedId: integer("feed_id") + .notNull() + .references(() => rssFeeds.id, { onDelete: "cascade" }), + guid: text(), + canonicalUrl: text("canonical_url").notNull(), + title: text(), + summary: text(), + contentSnippet: text("content_snippet"), + author: text(), + publishedAt: integer("published_at", { mode: "timestamp_ms" }), + visibility: text().notNull().default("private"), + shareToken: text("share_token"), + createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(), + }, + (table) => [ + uniqueIndex("rss_items_feed_id_guid_unique") + .on(table.feedId, table.guid) + .where(sql`${table.guid} IS NOT NULL`), + ], +); diff --git a/packages/drizzle-pkg/lib/schema/content.ts b/packages/drizzle-pkg/lib/schema/content.ts new file mode 100644 index 0000000..cd8a262 --- /dev/null +++ b/packages/drizzle-pkg/lib/schema/content.ts @@ -0,0 +1 @@ +export { posts, timelineEvents } from "../../database/sqlite/schema/content"; diff --git a/packages/drizzle-pkg/lib/schema/rss.ts b/packages/drizzle-pkg/lib/schema/rss.ts new file mode 100644 index 0000000..e93d208 --- /dev/null +++ b/packages/drizzle-pkg/lib/schema/rss.ts @@ -0,0 +1 @@ +export { rssFeeds, rssItems } from "../../database/sqlite/schema/rss"; diff --git a/packages/drizzle-pkg/migrations/0001_add-multitenant-content-rss.sql b/packages/drizzle-pkg/migrations/0001_add-multitenant-content-rss.sql new file mode 100644 index 0000000..78ae371 --- /dev/null +++ b/packages/drizzle-pkg/migrations/0001_add-multitenant-content-rss.sql @@ -0,0 +1,73 @@ +CREATE TABLE `posts` ( + `id` integer PRIMARY KEY NOT NULL, + `user_id` integer NOT NULL, + `title` text NOT NULL, + `slug` text NOT NULL, + `body_markdown` text NOT NULL, + `excerpt` text NOT NULL, + `cover_url` text, + `tags_json` text DEFAULT '[]' NOT NULL, + `published_at` integer, + `visibility` text DEFAULT 'private' NOT NULL, + `share_token` text, + `created_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL, + `updated_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `posts_user_id_slug_unique` ON `posts` (`user_id`,`slug`);--> statement-breakpoint +CREATE TABLE `timeline_events` ( + `id` integer PRIMARY KEY NOT NULL, + `user_id` integer NOT NULL, + `occurred_on` integer NOT NULL, + `title` text NOT NULL, + `body_markdown` text, + `link_url` text, + `visibility` text DEFAULT 'private' NOT NULL, + `share_token` text, + `created_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL, + `updated_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `rss_feeds` ( + `id` integer PRIMARY KEY NOT NULL, + `user_id` integer NOT NULL, + `feed_url` text NOT NULL, + `title` text, + `site_url` text, + `last_fetched_at` integer, + `last_error` text, + `poll_interval_minutes` integer, + `created_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `rss_feeds_user_id_feed_url_unique` ON `rss_feeds` (`user_id`,`feed_url`);--> statement-breakpoint +CREATE TABLE `rss_items` ( + `id` integer PRIMARY KEY NOT NULL, + `user_id` integer NOT NULL, + `feed_id` integer NOT NULL, + `guid` text, + `canonical_url` text NOT NULL, + `title` text, + `summary` text, + `content_snippet` text, + `author` text, + `published_at` integer, + `visibility` text DEFAULT 'private' NOT NULL, + `share_token` text, + `created_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade, + FOREIGN KEY (`feed_id`) REFERENCES `rss_feeds`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `rss_items_feed_id_guid_unique` ON `rss_items` (`feed_id`,`guid`) WHERE "rss_items"."guid" IS NOT NULL;--> statement-breakpoint +ALTER TABLE `users` ADD `role` text DEFAULT 'user' NOT NULL;--> statement-breakpoint +ALTER TABLE `users` ADD `status` text DEFAULT 'active' NOT NULL;--> statement-breakpoint +ALTER TABLE `users` ADD `public_slug` text;--> statement-breakpoint +ALTER TABLE `users` ADD `bio_markdown` text;--> statement-breakpoint +ALTER TABLE `users` ADD `bio_visibility` text DEFAULT 'private' NOT NULL;--> statement-breakpoint +ALTER TABLE `users` ADD `social_links_json` text DEFAULT '[]' NOT NULL;--> statement-breakpoint +ALTER TABLE `users` ADD `avatar_visibility` text DEFAULT 'private' NOT NULL;--> statement-breakpoint +CREATE UNIQUE INDEX `users_public_slug_unique` ON `users` (`public_slug`); \ No newline at end of file diff --git a/packages/drizzle-pkg/migrations/meta/0001_snapshot.json b/packages/drizzle-pkg/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..f8540b6 --- /dev/null +++ b/packages/drizzle-pkg/migrations/meta/0001_snapshot.json @@ -0,0 +1,793 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "66f33657-5926-4ac6-a196-2d142081b192", + "prevId": "0c82e00e-7d76-4479-a196-ceb6eb02ad3f", + "tables": { + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": { + "sessions_user_id_idx": { + "name": "sessions_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "nickname": { + "name": "nickname", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'user'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "public_slug": { + "name": "public_slug", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "bio_markdown": { + "name": "bio_markdown", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "bio_visibility": { + "name": "bio_visibility", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "social_links_json": { + "name": "social_links_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'[]'" + }, + "avatar_visibility": { + "name": "avatar_visibility", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": { + "users_username_unique": { + "name": "users_username_unique", + "columns": [ + "username" + ], + "isUnique": true + }, + "users_public_slug_unique": { + "name": "users_public_slug_unique", + "columns": [ + "public_slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "app_configs": { + "name": "app_configs", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value_type": { + "name": "value_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_configs": { + "name": "user_configs", + "columns": { + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value_type": { + "name": "value_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": { + "user_configs_user_id_idx": { + "name": "user_configs_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_configs_user_id_users_id_fk": { + "name": "user_configs_user_id_users_id_fk", + "tableFrom": "user_configs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_configs_user_id_key_pk": { + "columns": [ + "user_id", + "key" + ], + "name": "user_configs_user_id_key_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "posts": { + "name": "posts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "body_markdown": { + "name": "body_markdown", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "excerpt": { + "name": "excerpt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "cover_url": { + "name": "cover_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags_json": { + "name": "tags_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'[]'" + }, + "published_at": { + "name": "published_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "share_token": { + "name": "share_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": { + "posts_user_id_slug_unique": { + "name": "posts_user_id_slug_unique", + "columns": [ + "user_id", + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": { + "posts_user_id_users_id_fk": { + "name": "posts_user_id_users_id_fk", + "tableFrom": "posts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "timeline_events": { + "name": "timeline_events", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "occurred_on": { + "name": "occurred_on", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "body_markdown": { + "name": "body_markdown", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "link_url": { + "name": "link_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "share_token": { + "name": "share_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": {}, + "foreignKeys": { + "timeline_events_user_id_users_id_fk": { + "name": "timeline_events_user_id_users_id_fk", + "tableFrom": "timeline_events", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "rss_feeds": { + "name": "rss_feeds", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "feed_url": { + "name": "feed_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "site_url": { + "name": "site_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_fetched_at": { + "name": "last_fetched_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "poll_interval_minutes": { + "name": "poll_interval_minutes", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": { + "rss_feeds_user_id_feed_url_unique": { + "name": "rss_feeds_user_id_feed_url_unique", + "columns": [ + "user_id", + "feed_url" + ], + "isUnique": true + } + }, + "foreignKeys": { + "rss_feeds_user_id_users_id_fk": { + "name": "rss_feeds_user_id_users_id_fk", + "tableFrom": "rss_feeds", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "rss_items": { + "name": "rss_items", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "feed_id": { + "name": "feed_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "guid": { + "name": "guid", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "canonical_url": { + "name": "canonical_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "content_snippet": { + "name": "content_snippet", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "author": { + "name": "author", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "published_at": { + "name": "published_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "share_token": { + "name": "share_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + } + }, + "indexes": { + "rss_items_feed_id_guid_unique": { + "name": "rss_items_feed_id_guid_unique", + "columns": [ + "feed_id", + "guid" + ], + "isUnique": true, + "where": "\"rss_items\".\"guid\" IS NOT NULL" + } + }, + "foreignKeys": { + "rss_items_user_id_users_id_fk": { + "name": "rss_items_user_id_users_id_fk", + "tableFrom": "rss_items", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rss_items_feed_id_rss_feeds_id_fk": { + "name": "rss_items_feed_id_rss_feeds_id_fk", + "tableFrom": "rss_items", + "tableTo": "rss_feeds", + "columnsFrom": [ + "feed_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/packages/drizzle-pkg/migrations/meta/_journal.json b/packages/drizzle-pkg/migrations/meta/_journal.json index 0637341..4802fd2 100644 --- a/packages/drizzle-pkg/migrations/meta/_journal.json +++ b/packages/drizzle-pkg/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1776386788654, "tag": "0000_init", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1776457621565, + "tag": "0001_add-multitenant-content-rss", + "breakpoints": true } ] } \ No newline at end of file