mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
fix(presi): wire up db:push for presi schema via @mana/api
The presi module's schema was defined inline in routes.ts but had no working db:push mechanism — the old references to @presi/server and @presi/backend no longer exist after consolidation. Extracts schema into its own file, adds a dedicated drizzle config, and updates the setup script so tables are actually created. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
474ba93d70
commit
a9c51517eb
7 changed files with 104 additions and 75 deletions
11
apps/api/drizzle.presi.config.ts
Normal file
11
apps/api/drizzle.presi.config.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { defineConfig } from 'drizzle-kit';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: './src/modules/presi/schema.ts',
|
||||||
|
out: './drizzle/presi',
|
||||||
|
dialect: 'postgresql',
|
||||||
|
dbCredentials: {
|
||||||
|
url: process.env.DATABASE_URL || 'postgresql://mana:devpassword@localhost:5432/mana_platform',
|
||||||
|
},
|
||||||
|
schemaFilter: ['presi'],
|
||||||
|
});
|
||||||
|
|
@ -9,7 +9,8 @@
|
||||||
"start": "bun run dist/index.js",
|
"start": "bun run dist/index.js",
|
||||||
"type-check": "tsc --noEmit",
|
"type-check": "tsc --noEmit",
|
||||||
"db:generate": "drizzle-kit generate",
|
"db:generate": "drizzle-kit generate",
|
||||||
"db:push": "drizzle-kit push"
|
"db:push": "drizzle-kit push",
|
||||||
|
"db:push:presi": "drizzle-kit push --config=drizzle.presi.config.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/openai-compatible": "^2.0.41",
|
"@ai-sdk/openai-compatible": "^2.0.41",
|
||||||
|
|
|
||||||
|
|
@ -14,80 +14,20 @@ import type { AuthVariables } from '@mana/shared-hono';
|
||||||
import { drizzle } from 'drizzle-orm/postgres-js';
|
import { drizzle } from 'drizzle-orm/postgres-js';
|
||||||
import postgres from 'postgres';
|
import postgres from 'postgres';
|
||||||
import {
|
import {
|
||||||
pgSchema,
|
decks,
|
||||||
uuid,
|
slides,
|
||||||
text,
|
themes,
|
||||||
boolean,
|
sharedDecks,
|
||||||
timestamp,
|
decksRelations,
|
||||||
integer,
|
slidesRelations,
|
||||||
jsonb,
|
sharedDecksRelations,
|
||||||
index,
|
} from './schema.js';
|
||||||
} from 'drizzle-orm/pg-core';
|
|
||||||
import { relations } from 'drizzle-orm';
|
|
||||||
|
|
||||||
// ─── DB Schema (read-only for share lookups) ────────────────
|
// ─── DB Connection ─────────────────────────────────────────
|
||||||
|
|
||||||
const DATABASE_URL =
|
const DATABASE_URL =
|
||||||
process.env.DATABASE_URL ?? 'postgresql://mana:devpassword@localhost:5432/mana_platform';
|
process.env.DATABASE_URL ?? 'postgresql://mana:devpassword@localhost:5432/mana_platform';
|
||||||
|
|
||||||
const presiSchema = pgSchema('presi');
|
|
||||||
|
|
||||||
const decks = presiSchema.table('decks', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
userId: text('user_id').notNull(),
|
|
||||||
title: text('title').notNull(),
|
|
||||||
description: text('description'),
|
|
||||||
themeId: uuid('theme_id'),
|
|
||||||
isPublic: boolean('is_public').default(false).notNull(),
|
|
||||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
|
||||||
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const slides = presiSchema.table(
|
|
||||||
'slides',
|
|
||||||
{
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
deckId: uuid('deck_id').notNull(),
|
|
||||||
order: integer('order').default(0).notNull(),
|
|
||||||
content: jsonb('content'),
|
|
||||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
|
||||||
},
|
|
||||||
(table) => [index('slides_deck_order_api_idx').on(table.deckId, table.order)]
|
|
||||||
);
|
|
||||||
|
|
||||||
const themes = presiSchema.table('themes', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
colors: jsonb('colors'),
|
|
||||||
fonts: jsonb('fonts'),
|
|
||||||
isDefault: boolean('is_default').default(false),
|
|
||||||
});
|
|
||||||
|
|
||||||
const sharedDecks = presiSchema.table(
|
|
||||||
'shared_decks',
|
|
||||||
{
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
deckId: uuid('deck_id').notNull(),
|
|
||||||
shareCode: text('share_code').notNull().unique(),
|
|
||||||
expiresAt: timestamp('expires_at', { withTimezone: true }),
|
|
||||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
|
||||||
},
|
|
||||||
(table) => [index('shared_decks_deck_id_api_idx').on(table.deckId)]
|
|
||||||
);
|
|
||||||
|
|
||||||
const decksRelations = relations(decks, ({ many }) => ({
|
|
||||||
slides: many(slides),
|
|
||||||
sharedDecks: many(sharedDecks),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const slidesRelations = relations(slides, ({ one }) => ({
|
|
||||||
deck: one(decks, { fields: [slides.deckId], references: [decks.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const sharedDecksRelations = relations(sharedDecks, ({ one }) => ({
|
|
||||||
deck: one(decks, { fields: [sharedDecks.deckId], references: [decks.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const connection = postgres(DATABASE_URL, { max: 5, idle_timeout: 20 });
|
const connection = postgres(DATABASE_URL, { max: 5, idle_timeout: 20 });
|
||||||
const db = drizzle(connection, {
|
const db = drizzle(connection, {
|
||||||
schema: {
|
schema: {
|
||||||
|
|
|
||||||
76
apps/api/src/modules/presi/schema.ts
Normal file
76
apps/api/src/modules/presi/schema.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* Presi module — DB schema
|
||||||
|
*
|
||||||
|
* Lives in mana_platform under its own pgSchema('presi').
|
||||||
|
* Shared between routes.ts (runtime) and drizzle-kit (migrations/push).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
pgSchema,
|
||||||
|
uuid,
|
||||||
|
text,
|
||||||
|
boolean,
|
||||||
|
timestamp,
|
||||||
|
integer,
|
||||||
|
jsonb,
|
||||||
|
index,
|
||||||
|
} from 'drizzle-orm/pg-core';
|
||||||
|
import { relations } from 'drizzle-orm';
|
||||||
|
|
||||||
|
export const presiSchema = pgSchema('presi');
|
||||||
|
|
||||||
|
export const decks = presiSchema.table('decks', {
|
||||||
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
userId: text('user_id').notNull(),
|
||||||
|
title: text('title').notNull(),
|
||||||
|
description: text('description'),
|
||||||
|
themeId: uuid('theme_id'),
|
||||||
|
isPublic: boolean('is_public').default(false).notNull(),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||||
|
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const slides = presiSchema.table(
|
||||||
|
'slides',
|
||||||
|
{
|
||||||
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
deckId: uuid('deck_id').notNull(),
|
||||||
|
order: integer('order').default(0).notNull(),
|
||||||
|
content: jsonb('content'),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||||
|
},
|
||||||
|
(table) => [index('slides_deck_order_api_idx').on(table.deckId, table.order)]
|
||||||
|
);
|
||||||
|
|
||||||
|
export const themes = presiSchema.table('themes', {
|
||||||
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
name: text('name').notNull(),
|
||||||
|
colors: jsonb('colors'),
|
||||||
|
fonts: jsonb('fonts'),
|
||||||
|
isDefault: boolean('is_default').default(false),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const sharedDecks = presiSchema.table(
|
||||||
|
'shared_decks',
|
||||||
|
{
|
||||||
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
deckId: uuid('deck_id').notNull(),
|
||||||
|
shareCode: text('share_code').notNull().unique(),
|
||||||
|
expiresAt: timestamp('expires_at', { withTimezone: true }),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||||
|
},
|
||||||
|
(table) => [index('shared_decks_deck_id_api_idx').on(table.deckId)]
|
||||||
|
);
|
||||||
|
|
||||||
|
export const decksRelations = relations(decks, ({ many }) => ({
|
||||||
|
slides: many(slides),
|
||||||
|
sharedDecks: many(sharedDecks),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const slidesRelations = relations(slides, ({ one }) => ({
|
||||||
|
deck: one(decks, { fields: [slides.deckId], references: [decks.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const sharedDecksRelations = relations(sharedDecks, ({ one }) => ({
|
||||||
|
deck: one(decks, { fields: [sharedDecks.deckId], references: [decks.id] }),
|
||||||
|
}));
|
||||||
|
|
@ -10,5 +10,5 @@
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"types": ["bun-types"]
|
"types": ["bun-types"]
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "scripts/**/*.ts"]
|
"include": ["src/**/*.ts", "scripts/**/*.ts", "drizzle.*.config.ts"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm --filter '@presi/*' run dev",
|
"dev": "pnpm --filter '@presi/*' run dev",
|
||||||
"db:push": "pnpm --filter @presi/backend db:push",
|
"db:push": "pnpm --filter @mana/api db:push:presi",
|
||||||
"db:studio": "pnpm --filter @presi/backend db:studio"
|
"db:studio": "drizzle-kit studio --config=../../apps/api/drizzle.presi.config.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,10 @@ create_schema_if_not_exists() {
|
||||||
push_schema() {
|
push_schema() {
|
||||||
local filter=$1
|
local filter=$1
|
||||||
local name=$2
|
local name=$2
|
||||||
|
local script=${3:-db:push}
|
||||||
echo -e "${YELLOW}Pushing schema for ${name}...${NC}"
|
echo -e "${YELLOW}Pushing schema for ${name}...${NC}"
|
||||||
local output
|
local output
|
||||||
output=$(pnpm --filter "$filter" db:push --force 2>&1)
|
output=$(pnpm --filter "$filter" "$script" --force 2>&1)
|
||||||
local exit_code=$?
|
local exit_code=$?
|
||||||
if echo "$output" | grep -q "No projects matched the filters\|None of the selected packages has"; then
|
if echo "$output" | grep -q "No projects matched the filters\|None of the selected packages has"; then
|
||||||
echo -e " ${YELLOW}⊘ Skipped (no db:push script for ${filter})${NC}"
|
echo -e " ${YELLOW}⊘ Skipped (no db:push script for ${filter})${NC}"
|
||||||
|
|
@ -117,7 +118,7 @@ setup_service() {
|
||||||
push_schema "@traces/server" "traces"
|
push_schema "@traces/server" "traces"
|
||||||
;;
|
;;
|
||||||
presi)
|
presi)
|
||||||
push_schema "@presi/server" "presi"
|
push_schema "@mana/api" "presi" "db:push:presi"
|
||||||
;;
|
;;
|
||||||
uload)
|
uload)
|
||||||
push_schema "@mana/uload-database" "uload"
|
push_schema "@mana/uload-database" "uload"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue