Files
core/src/modules/posts/db.js
T
2026-04-12 12:50:14 -04:00

141 lines
4.5 KiB
JavaScript

/**
* Posts Module - Database
* Creates zen_posts and zen_posts_category tables.
*/
import { query } from '@hykocx/zen/database';
import { getPostsConfig } from './config.js';
async function tableExists(tableName) {
const result = await query(
`SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = $1
)`,
[tableName]
);
return result.rows[0].exists;
}
async function createPostsCategoryTable() {
const tableName = 'zen_posts_category';
const exists = await tableExists(tableName);
if (exists) {
console.log(`- Table already exists: ${tableName}`);
return { created: false, tableName };
}
await query(`
CREATE TABLE zen_posts_category (
id SERIAL PRIMARY KEY,
post_type VARCHAR(100) NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
)
`);
await query(`CREATE INDEX idx_zen_posts_category_post_type ON zen_posts_category(post_type)`);
await query(`CREATE INDEX idx_zen_posts_category_is_active ON zen_posts_category(is_active)`);
console.log(`✓ Created table: ${tableName}`);
return { created: true, tableName };
}
async function createPostsTable() {
const tableName = 'zen_posts';
const exists = await tableExists(tableName);
if (exists) {
console.log(`- Table already exists: ${tableName}`);
return { created: false, tableName };
}
await query(`
CREATE TABLE zen_posts (
id SERIAL PRIMARY KEY,
post_type VARCHAR(100) NOT NULL,
slug VARCHAR(500) NOT NULL,
data JSONB NOT NULL DEFAULT '{}',
category_id INTEGER REFERENCES zen_posts_category(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
UNIQUE(post_type, slug)
)
`);
await query(`CREATE INDEX idx_zen_posts_post_type ON zen_posts(post_type)`);
await query(`CREATE INDEX idx_zen_posts_post_type_slug ON zen_posts(post_type, slug)`);
await query(`CREATE INDEX idx_zen_posts_category_id ON zen_posts(category_id)`);
await query(`CREATE INDEX idx_zen_posts_data_gin ON zen_posts USING GIN (data)`);
console.log(`✓ Created table: ${tableName}`);
return { created: true, tableName };
}
async function createPostsRelationsTable() {
const tableName = 'zen_posts_relations';
const exists = await tableExists(tableName);
if (exists) {
console.log(`- Table already exists: ${tableName}`);
return { created: false, tableName };
}
await query(`
CREATE TABLE zen_posts_relations (
id SERIAL PRIMARY KEY,
post_id INTEGER NOT NULL REFERENCES zen_posts(id) ON DELETE CASCADE,
field_name VARCHAR(100) NOT NULL,
related_post_id INTEGER NOT NULL REFERENCES zen_posts(id) ON DELETE CASCADE,
sort_order INTEGER DEFAULT 0,
UNIQUE(post_id, field_name, related_post_id)
)
`);
await query(`CREATE INDEX idx_zen_posts_relations_post_id ON zen_posts_relations(post_id)`);
await query(`CREATE INDEX idx_zen_posts_relations_related ON zen_posts_relations(related_post_id)`);
console.log(`✓ Created table: ${tableName}`);
return { created: true, tableName };
}
/**
* Create all posts-related tables.
* zen_posts_category is only created if at least one type uses the 'category' field.
* zen_posts_relations is only created if at least one type uses the 'relation' field.
* @returns {Promise<Object>}
*/
export async function createTables() {
const created = [];
const skipped = [];
const config = getPostsConfig();
const needsRelations = Object.values(config.types).some(t => t.hasRelations);
// zen_posts_category must always be created before zen_posts
// because zen_posts has a FK reference to it
console.log('\n--- Posts Categories ---');
const catResult = await createPostsCategoryTable();
if (catResult.created) created.push(catResult.tableName);
else skipped.push(catResult.tableName);
console.log('\n--- Posts ---');
const postResult = await createPostsTable();
if (postResult.created) created.push(postResult.tableName);
else skipped.push(postResult.tableName);
if (needsRelations) {
console.log('\n--- Posts Relations ---');
const relResult = await createPostsRelationsTable();
if (relResult.created) created.push(relResult.tableName);
else skipped.push(relResult.tableName);
}
return { created, skipped };
}