UNPKG

@bernierllc/content-type-blog-post

Version:

Blog post content type with rich TipTap editor, SEO metadata, database storage, and web publishing

65 lines (63 loc) 2.78 kB
"use strict"; /* Copyright (c) 2025 Bernier LLC This file is licensed to the client under a limited-use license. The client may use and modify this code *only within the scope of the project it was delivered for*. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.BlogPostMetadataSchema = exports.BlogPostStatusSchema = exports.BlogPostAuthorSchema = exports.BlogPostSEOSchema = void 0; const zod_1 = require("zod"); /** * Blog post SEO metadata schema * Note: Allows empty strings for draft posts. Use validateSEOCompleteness() to enforce completeness before publishing. */ exports.BlogPostSEOSchema = zod_1.z.object({ metaTitle: zod_1.z.string().max(60, 'Meta title should be 60 characters or less'), metaDescription: zod_1.z.string().max(160, 'Meta description should be 160 characters or less'), keywords: zod_1.z.array(zod_1.z.string()).max(10, 'Maximum 10 keywords recommended'), ogImage: zod_1.z.string().url().optional(), ogType: zod_1.z.literal('article').default('article'), canonicalUrl: zod_1.z.string().url().optional(), }); /** * Blog post author metadata schema */ exports.BlogPostAuthorSchema = zod_1.z.object({ name: zod_1.z.string().min(1), email: zod_1.z.string().email().optional(), avatar: zod_1.z.string().url().optional(), bio: zod_1.z.string().max(500).optional(), }); /** * Blog post workflow status */ exports.BlogPostStatusSchema = zod_1.z.enum(['draft', 'published', 'scheduled', 'archived']); /** * Blog post metadata schema (extends text content metadata) */ exports.BlogPostMetadataSchema = zod_1.z.object({ // Inherited from TextContentMetadata content: zod_1.z.string().min(1, 'Content is required'), createdAt: zod_1.z.date(), updatedAt: zod_1.z.date(), // Blog-specific fields title: zod_1.z.string().min(1).max(200), slug: zod_1.z.string().min(1).regex(/^[a-z0-9-]+$/, 'Slug must be lowercase letters, numbers, and hyphens'), excerpt: zod_1.z.string().max(300).optional(), // SEO metadata seo: exports.BlogPostSEOSchema, // Author information author: exports.BlogPostAuthorSchema, // Taxonomy tags: zod_1.z.array(zod_1.z.string()).default([]), categories: zod_1.z.array(zod_1.z.string()).default([]), // Publishing workflow status: exports.BlogPostStatusSchema.default('draft'), publishedAt: zod_1.z.date().optional(), scheduledFor: zod_1.z.date().optional(), // Additional metadata featuredImage: zod_1.z.string().url().optional(), readingTime: zod_1.z.number().positive().optional(), // minutes wordCount: zod_1.z.number().nonnegative().default(0), });