SPB Git

spb/autoscholar

Public
5.8 KB · 174 lines typescript
1import { sql } from "drizzle-orm";2import {3  boolean,4  customType,5  index,6  integer,7  jsonb,8  pgTable,9  primaryKey,10  text,11  timestamp,12  uniqueIndex,13  uuid,14} from "drizzle-orm/pg-core";1516export const tsvector = customType<{ data: string }>({17  dataType() {18    return "tsvector";19  },20});2122export const series = pgTable("series", {23  id: uuid("id").primaryKey().defaultRandom(),24  slug: text("slug").notNull().unique(),25  name: text("name").notNull(),26  description: text("description").notNull().default(""),27  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),28});2930export const topics = pgTable("topics", {31  id: uuid("id").primaryKey().defaultRandom(),32  slug: text("slug").notNull().unique(),33  name: text("name").notNull(),34  description: text("description").notNull().default(""),35  parentId: uuid("parent_id"),36  sortOrder: integer("sort_order").notNull().default(0),37});3839export const papers = pgTable(40  "papers",41  {42    id: uuid("id").primaryKey().defaultRandom(),43    publicId: text("public_id").notNull().unique(), // AS-WP-2026-000144    slug: text("slug").notNull().unique(),45    title: text("title").notNull(),46    status: text("status").notNull().default("published"),47    discipline: text("discipline").notNull(),48    researchMode: text("research_mode").notNull(),49    currentVersionId: uuid("current_version_id"),50    seriesId: uuid("series_id").references(() => series.id),51    firstPublishedAt: timestamp("first_published_at", { withTimezone: true }).notNull().defaultNow(),52    updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),53    retractedAt: timestamp("retracted_at", { withTimezone: true }),54    synthetic: boolean("synthetic").notNull().default(false),55  },56  (t) => [57    index("papers_status_idx").on(t.status, t.firstPublishedAt),58    index("papers_discipline_idx").on(t.discipline),59  ],60);6162export const paperVersions = pgTable(63  "paper_versions",64  {65    id: uuid("id").primaryKey().defaultRandom(),66    paperId: uuid("paper_id")67      .notNull()68      .references(() => papers.id, { onDelete: "cascade" }),69    versionNo: integer("version_no").notNull(),70    runId: uuid("run_id").notNull(),71    title: text("title").notNull(),72    abstract: text("abstract").notNull(),73    keywords: text("keywords").array().notNull().default([]),74    metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),75    artifactSet: jsonb("artifact_set")76      .$type<77        Array<{78          path: string;79          kind: string;80          sha256: string;81          bytes: number;82          contentType: string;83          publicPath: string;84        }>85      >()86      .notNull()87      .default([]),88    pdfPublicPath: text("pdf_public_path").notNull(),89    qaSummary: jsonb("qa_summary").$type<Record<string, unknown>>().notNull().default({}),90    provenance: jsonb("provenance").$type<Record<string, unknown>>().notNull().default({}),91    changelog: text("changelog").notNull().default(""),92    publishedAt: timestamp("published_at", { withTimezone: true }).notNull().defaultNow(),93    search: tsvector("search")94      .notNull()95      .generatedAlwaysAs(96        sql`setweight(to_tsvector('english', coalesce(title, '')), 'A') || setweight(to_tsvector('english', coalesce(abstract, '')), 'B') || setweight(to_tsvector('english', as_immutable_array_to_string(keywords)), 'A')`,97      ),98  },99  (t) => [100    uniqueIndex("paper_versions_uq").on(t.paperId, t.versionNo),101    uniqueIndex("paper_versions_run_uq").on(t.runId),102    index("paper_versions_search_idx").using("gin", t.search),103  ],104);105106export const paperTopics = pgTable(107  "paper_topics",108  {109    paperId: uuid("paper_id")110      .notNull()111      .references(() => papers.id, { onDelete: "cascade" }),112    topicId: uuid("topic_id")113      .notNull()114      .references(() => topics.id, { onDelete: "cascade" }),115  },116  (t) => [primaryKey({ columns: [t.paperId, t.topicId] })],117);118119export const paperSeries = pgTable(120  "paper_series",121  {122    paperId: uuid("paper_id")123      .notNull()124      .references(() => papers.id, { onDelete: "cascade" }),125    seriesId: uuid("series_id")126      .notNull()127      .references(() => series.id, { onDelete: "cascade" }),128  },129  (t) => [primaryKey({ columns: [t.paperId, t.seriesId] })],130);131132export const publicationEvents = pgTable(133  "publication_events",134  {135    id: uuid("id").primaryKey().defaultRandom(),136    paperId: uuid("paper_id")137      .notNull()138      .references(() => papers.id, { onDelete: "cascade" }),139    versionId: uuid("version_id"),140    kind: text("kind").notNull(), // published | corrected | retracted | metadata_updated | unpublished141    actor: text("actor").notNull(),142    detail: jsonb("detail").$type<Record<string, unknown>>().notNull().default({}),143    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),144  },145  (t) => [index("publication_events_paper_idx").on(t.paperId, t.createdAt)],146);147148export const corrections = pgTable("corrections", {149  id: uuid("id").primaryKey().defaultRandom(),150  paperId: uuid("paper_id")151    .notNull()152    .references(() => papers.id, { onDelete: "cascade" }),153  fromVersionNo: integer("from_version_no").notNull(),154  toVersionNo: integer("to_version_no").notNull(),155  notice: text("notice").notNull(),156  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),157});158159export const retractions = pgTable("retractions", {160  id: uuid("id").primaryKey().defaultRandom(),161  paperId: uuid("paper_id")162    .notNull()163    .references(() => papers.id, { onDelete: "cascade" }),164  reason: text("reason").notNull(),165  notice: text("notice").notNull(),166  retractedBy: text("retracted_by").notNull(),167  retractedAt: timestamp("retracted_at", { withTimezone: true }).notNull().defaultNow(),168});169170export const paperSequences = pgTable("paper_sequences", {171  year: integer("year").primaryKey(),172  last: integer("last").notNull().default(0),173});174
Files · a78adfcb2b7368f5bc22c4935584f39e3929aa9a
Menu

Theme