m14i-blogging 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -846,3 +846,4 @@ Contributions are welcome! Please feel free to submit a Pull Request.
846
846
  ## License
847
847
 
848
848
  MIT
849
+ # Schema Fix
@@ -334,7 +334,7 @@ function createBlogClient(supabase, config = {}) {
334
334
  * List all categories
335
335
  */
336
336
  async list() {
337
- const { data, error } = await supabase.from("blog.categories").select("*").order("display_order", { ascending: true });
337
+ const { data, error } = await supabase.from("blog_categories").select("*").order("display_order", { ascending: true });
338
338
  if (error) {
339
339
  throw new Error(`Failed to fetch categories: ${error.message}`);
340
340
  }
@@ -354,7 +354,7 @@ function createBlogClient(supabase, config = {}) {
354
354
  * Get category by ID
355
355
  */
356
356
  async getById(id) {
357
- const { data, error } = await supabase.from("blog.categories").select("*").eq("id", id).single();
357
+ const { data, error } = await supabase.from("blog_categories").select("*").eq("id", id).single();
358
358
  if (error) {
359
359
  if (error.code === "PGRST116") return null;
360
360
  throw new Error(`Failed to fetch category: ${error.message}`);
@@ -365,7 +365,7 @@ function createBlogClient(supabase, config = {}) {
365
365
  * Get category by slug
366
366
  */
367
367
  async getBySlug(slug) {
368
- const { data, error } = await supabase.from("blog.categories").select("*").eq("slug", slug).single();
368
+ const { data, error } = await supabase.from("blog_categories").select("*").eq("slug", slug).single();
369
369
  if (error) {
370
370
  if (error.code === "PGRST116") return null;
371
371
  throw new Error(`Failed to fetch category: ${error.message}`);
@@ -376,7 +376,7 @@ function createBlogClient(supabase, config = {}) {
376
376
  * Create a new category
377
377
  */
378
378
  async create(category) {
379
- const { data, error } = await supabase.from("blog.categories").insert(category).select().single();
379
+ const { data, error } = await supabase.from("blog_categories").insert(category).select().single();
380
380
  if (error) {
381
381
  throw new Error(`Failed to create category: ${error.message}`);
382
382
  }
@@ -386,7 +386,7 @@ function createBlogClient(supabase, config = {}) {
386
386
  * Update an existing category
387
387
  */
388
388
  async update(id, updates) {
389
- const { data, error } = await supabase.from("blog.categories").update(updates).eq("id", id).select().single();
389
+ const { data, error } = await supabase.from("blog_categories").update(updates).eq("id", id).select().single();
390
390
  if (error) {
391
391
  throw new Error(`Failed to update category: ${error.message}`);
392
392
  }
@@ -396,7 +396,7 @@ function createBlogClient(supabase, config = {}) {
396
396
  * Delete a category
397
397
  */
398
398
  async delete(id) {
399
- const { error } = await supabase.from("blog.categories").delete().eq("id", id);
399
+ const { error } = await supabase.from("blog_categories").delete().eq("id", id);
400
400
  if (error) {
401
401
  throw new Error(`Failed to delete category: ${error.message}`);
402
402
  }
@@ -410,7 +410,7 @@ function createBlogClient(supabase, config = {}) {
410
410
  * List all tags
411
411
  */
412
412
  async list() {
413
- const { data, error } = await supabase.from("blog.tags").select("*").order("name", { ascending: true });
413
+ const { data, error } = await supabase.from("blog_tags").select("*").order("name", { ascending: true });
414
414
  if (error) {
415
415
  throw new Error(`Failed to fetch tags: ${error.message}`);
416
416
  }
@@ -430,7 +430,7 @@ function createBlogClient(supabase, config = {}) {
430
430
  * Get tag by ID
431
431
  */
432
432
  async getById(id) {
433
- const { data, error } = await supabase.from("blog.tags").select("*").eq("id", id).single();
433
+ const { data, error } = await supabase.from("blog_tags").select("*").eq("id", id).single();
434
434
  if (error) {
435
435
  if (error.code === "PGRST116") return null;
436
436
  throw new Error(`Failed to fetch tag: ${error.message}`);
@@ -441,7 +441,7 @@ function createBlogClient(supabase, config = {}) {
441
441
  * Get tag by slug
442
442
  */
443
443
  async getBySlug(slug) {
444
- const { data, error } = await supabase.from("blog.tags").select("*").eq("slug", slug).single();
444
+ const { data, error } = await supabase.from("blog_tags").select("*").eq("slug", slug).single();
445
445
  if (error) {
446
446
  if (error.code === "PGRST116") return null;
447
447
  throw new Error(`Failed to fetch tag: ${error.message}`);
@@ -452,7 +452,7 @@ function createBlogClient(supabase, config = {}) {
452
452
  * Create a new tag
453
453
  */
454
454
  async create(tag) {
455
- const { data, error } = await supabase.from("blog.tags").insert(tag).select().single();
455
+ const { data, error } = await supabase.from("blog_tags").insert(tag).select().single();
456
456
  if (error) {
457
457
  throw new Error(`Failed to create tag: ${error.message}`);
458
458
  }
@@ -462,7 +462,7 @@ function createBlogClient(supabase, config = {}) {
462
462
  * Update an existing tag
463
463
  */
464
464
  async update(id, updates) {
465
- const { data, error } = await supabase.from("blog.tags").update(updates).eq("id", id).select().single();
465
+ const { data, error } = await supabase.from("blog_tags").update(updates).eq("id", id).select().single();
466
466
  if (error) {
467
467
  throw new Error(`Failed to update tag: ${error.message}`);
468
468
  }
@@ -472,7 +472,7 @@ function createBlogClient(supabase, config = {}) {
472
472
  * Delete a tag
473
473
  */
474
474
  async delete(id) {
475
- const { error } = await supabase.from("blog.tags").delete().eq("id", id);
475
+ const { error } = await supabase.from("blog_tags").delete().eq("id", id);
476
476
  if (error) {
477
477
  throw new Error(`Failed to delete tag: ${error.message}`);
478
478
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/index.ts","../../src/client/supabase.ts"],"sourcesContent":["/**\n * Client exports for m14i-blogging\n *\n * Pre-built data access layer for Supabase integration\n *\n * @example\n * ```typescript\n * import { createBlogClient } from 'm14i-blogging/client';\n * import { createClient } from '@supabase/supabase-js';\n *\n * const supabase = createClient(url, key);\n * const blog = createBlogClient(supabase);\n *\n * // Use the client\n * const { posts } = await blog.posts.list({ status: 'published' });\n * ```\n */\n\nexport { createBlogClient } from './supabase';\nexport type { BlogClient, BlogClientConfig, SupabaseClient } from './supabase';\n","/**\n * Supabase Data Access Layer for m14i-blogging\n *\n * Provides pre-built CRUD operations for blog posts and media.\n * Works with the blog_posts and blog_media tables.\n *\n * @example\n * ```typescript\n * import { createBlogClient } from 'm14i-blogging/client';\n * import { createClient } from '@supabase/supabase-js';\n *\n * const supabase = createClient(url, key);\n * const blog = createBlogClient(supabase);\n *\n * // Use it\n * const posts = await blog.posts.list({ status: 'published' });\n * const post = await blog.posts.getBySlug('my-post');\n * ```\n */\n\nimport type {\n BlogPostRow,\n BlogPostInsert,\n BlogPostUpdate,\n BlogPostWithAuthor,\n BlogFilterParams,\n BlogPostListResponse,\n BlogMediaRow,\n BlogMediaInsert,\n BlogMediaUpdate,\n BlogStats,\n BlogCategory,\n BlogTag,\n} from \"../types/database\";\n\n// ============================================================================\n// Supabase Client Type\n// ============================================================================\n\nexport interface SupabaseClient {\n from(table: string): {\n select(query: string, options?: { count?: string }): any;\n insert(data: any): any;\n update(data: any): any;\n delete(): any;\n upsert(data: any): any;\n };\n rpc(functionName: string, params?: any): any;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface BlogClientConfig {\n /**\n * Table name for blog posts (default: \"blog_posts\")\n */\n postsTable?: string;\n /**\n * Table name for blog media (default: \"blog_media\")\n */\n mediaTable?: string;\n /**\n * Enable/disable author joins (default: true)\n */\n includeAuthor?: boolean;\n /**\n * Users table name for author joins (default: \"users\")\n */\n usersTable?: string;\n}\n\nconst DEFAULT_CONFIG: Required<BlogClientConfig> = {\n postsTable: \"blog_posts\",\n mediaTable: \"blog_media\",\n includeAuthor: true,\n usersTable: \"users\",\n};\n\n// ============================================================================\n// Blog Client Factory\n// ============================================================================\n\n/**\n * Creates a blog client with pre-built CRUD operations\n */\nexport function createBlogClient(\n supabase: SupabaseClient,\n config: BlogClientConfig = {}\n) {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n return {\n /**\n * Blog post operations\n */\n posts: {\n /**\n * List blog posts with filtering and pagination\n */\n async list(\n params: BlogFilterParams = {}\n ): Promise<BlogPostListResponse> {\n const {\n page = 1,\n pageSize = 10,\n status,\n category,\n tag,\n search,\n orderBy = \"created_at\",\n orderDirection = \"desc\",\n } = params;\n\n const from = (page - 1) * pageSize;\n const to = from + pageSize - 1;\n\n let query = supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\",\n { count: \"exact\" }\n )\n .range(from, to)\n .order(orderBy, { ascending: orderDirection === \"asc\" });\n\n if (status) {\n query = query.eq(\"status\", status);\n }\n\n if (category) {\n query = query.eq(\"category\", category);\n }\n\n if (tag) {\n query = query.contains(\"tags\", [tag]);\n }\n\n if (search) {\n query = query.or(\n `title.ilike.%${search}%,excerpt.ilike.%${search}%,category.ilike.%${search}%`\n );\n }\n\n const { data, error, count } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog posts: ${error.message}`);\n }\n\n return {\n posts: (data as unknown as BlogPostWithAuthor[]) || [],\n total: count || 0,\n page,\n pageSize,\n totalPages: Math.ceil((count || 0) / pageSize),\n };\n },\n\n /**\n * Get a single post by slug\n */\n async getBySlug(slug: string): Promise<BlogPostWithAuthor | null> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\"\n )\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n // Not found\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostWithAuthor;\n },\n\n /**\n * Get a single post by ID\n */\n async getById(id: string): Promise<BlogPostRow | null> {\n const { data, error} = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Create a new blog post\n */\n async create(post: BlogPostInsert): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .insert(post)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Update an existing blog post\n */\n async update(\n id: string,\n updates: BlogPostUpdate\n ): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Delete a blog post\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.postsTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog post: ${error.message}`);\n }\n },\n\n /**\n * Publish a draft post\n */\n async publish(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"published\" });\n },\n\n /**\n * Unpublish (archive) a post\n */\n async archive(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"archived\" });\n },\n\n /**\n * Search posts using full-text search\n */\n async search(query: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_search_posts\", { search_query: query })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to search blog posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by tag\n */\n async getByTag(tag: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_tag\", { tag_name: tag })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get posts by tag: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by category\n */\n async getByCategory(\n category: string,\n limit: number = 10\n ): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_category\", { category_name: category })\n .limit(limit);\n\n if (error) {\n throw new Error(\n `Failed to get posts by category: ${error.message}`\n );\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get related posts (by tags and category)\n */\n async getRelated(postId: string, limit: number = 3): Promise<BlogPostRow[]> {\n const post = await this.getById(postId);\n if (!post) return [];\n\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"status\", \"published\")\n .neq(\"id\", postId)\n .or(`category.eq.${post.category},tags.ov.{${post.tags.join(\",\")}}`)\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get related posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n },\n\n /**\n * Blog media operations\n */\n media: {\n /**\n * List all media files\n */\n async list(\n type?: string,\n limit: number = 50\n ): Promise<BlogMediaRow[]> {\n let query = supabase\n .from(cfg.mediaTable)\n .select(\"*\")\n .order(\"uploaded_at\", { ascending: false })\n .limit(limit);\n\n if (type) {\n query = query.eq(\"type\", type);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog media: ${error.message}`);\n }\n\n return (data as unknown as BlogMediaRow[]) || [];\n },\n\n /**\n * Create new media record\n */\n async create(media: BlogMediaInsert): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .insert(media)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Update media record\n */\n async update(id: string, updates: BlogMediaUpdate): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Delete media record\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.mediaTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog media: ${error.message}`);\n }\n },\n },\n\n /**\n * Statistics and analytics\n */\n stats: {\n /**\n * Get blog statistics\n */\n async getStats(): Promise<BlogStats> {\n const { data: posts, error } = await supabase\n .from(cfg.postsTable)\n .select(\"status, category, tags\");\n\n if (error) {\n throw new Error(`Failed to fetch blog stats: ${error.message}`);\n }\n\n const stats: BlogStats = {\n totalPosts: posts.length,\n publishedPosts: 0,\n draftPosts: 0,\n archivedPosts: 0,\n categoryCounts: {},\n tagCounts: {},\n };\n\n posts.forEach((post: any) => {\n if (post.status === \"published\") stats.publishedPosts++;\n if (post.status === \"draft\") stats.draftPosts++;\n if (post.status === \"archived\") stats.archivedPosts++;\n\n if (post.category) {\n stats.categoryCounts[post.category] =\n (stats.categoryCounts[post.category] || 0) + 1;\n }\n\n post.tags?.forEach((tag: string) => {\n stats.tagCounts[tag] = (stats.tagCounts[tag] || 0) + 1;\n });\n });\n\n return stats;\n },\n\n /**\n * Get all categories with post counts\n */\n async getCategories(): Promise<BlogCategory[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"category\")\n .eq(\"status\", \"published\")\n .not(\"category\", \"is\", null);\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n if (row.category) {\n counts[row.category] = (counts[row.category] || 0) + 1;\n }\n });\n\n return Object.entries(counts).map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }));\n },\n\n /**\n * Get all tags with post counts\n */\n async getTags(): Promise<BlogTag[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"tags\")\n .eq(\"status\", \"published\");\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n row.tags?.forEach((tag: string) => {\n counts[tag] = (counts[tag] || 0) + 1;\n });\n });\n\n return Object.entries(counts)\n .map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }))\n .sort((a, b) => b.postCount - a.postCount);\n },\n },\n\n /**\n * Category management operations (v0.4.0+)\n */\n categories: {\n /**\n * List all categories\n */\n async list(): Promise<import(\"../types/database\").CategoryRow[]> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .select(\"*\")\n .order(\"display_order\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryRow[]) || [];\n },\n\n /**\n * List categories with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").CategoryWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_categories_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch categories with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryWithCount[]) || [];\n },\n\n /**\n * Get category by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Get category by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Create a new category\n */\n async create(category: import(\"../types/database\").CategoryInsert): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .insert(category)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Update an existing category\n */\n async update(id: string, updates: import(\"../types/database\").CategoryUpdate): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Delete a category\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog.categories\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete category: ${error.message}`);\n }\n },\n },\n\n /**\n * Tag management operations (v0.4.0+)\n */\n tags: {\n /**\n * List all tags\n */\n async list(): Promise<import(\"../types/database\").TagRow[]> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .select(\"*\")\n .order(\"name\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagRow[]) || [];\n },\n\n /**\n * List tags with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").TagWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_tags_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch tags with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagWithCount[]) || [];\n },\n\n /**\n * Get tag by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Get tag by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Create a new tag\n */\n async create(tag: import(\"../types/database\").TagInsert): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .insert(tag)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Update an existing tag\n */\n async update(id: string, updates: import(\"../types/database\").TagUpdate): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Delete a tag\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog.tags\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete tag: ${error.message}`);\n }\n },\n },\n };\n}\n\n/**\n * Type helper to extract the blog client type\n */\nexport type BlogClient = ReturnType<typeof createBlogClient>;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/client/index.ts","../../src/client/supabase.ts"],"sourcesContent":["/**\n * Client exports for m14i-blogging\n *\n * Pre-built data access layer for Supabase integration\n *\n * @example\n * ```typescript\n * import { createBlogClient } from 'm14i-blogging/client';\n * import { createClient } from '@supabase/supabase-js';\n *\n * const supabase = createClient(url, key);\n * const blog = createBlogClient(supabase);\n *\n * // Use the client\n * const { posts } = await blog.posts.list({ status: 'published' });\n * ```\n */\n\nexport { createBlogClient } from './supabase';\nexport type { BlogClient, BlogClientConfig, SupabaseClient } from './supabase';\n","/**\n * Supabase Data Access Layer for m14i-blogging\n *\n * Provides pre-built CRUD operations for blog posts and media.\n * Works with the blog_posts and blog_media tables.\n *\n * @example\n * ```typescript\n * import { createBlogClient } from 'm14i-blogging/client';\n * import { createClient } from '@supabase/supabase-js';\n *\n * const supabase = createClient(url, key);\n * const blog = createBlogClient(supabase);\n *\n * // Use it\n * const posts = await blog.posts.list({ status: 'published' });\n * const post = await blog.posts.getBySlug('my-post');\n * ```\n */\n\nimport type {\n BlogPostRow,\n BlogPostInsert,\n BlogPostUpdate,\n BlogPostWithAuthor,\n BlogFilterParams,\n BlogPostListResponse,\n BlogMediaRow,\n BlogMediaInsert,\n BlogMediaUpdate,\n BlogStats,\n BlogCategory,\n BlogTag,\n} from \"../types/database\";\n\n// ============================================================================\n// Supabase Client Type\n// ============================================================================\n\nexport interface SupabaseClient {\n from(table: string): {\n select(query: string, options?: { count?: string }): any;\n insert(data: any): any;\n update(data: any): any;\n delete(): any;\n upsert(data: any): any;\n };\n rpc(functionName: string, params?: any): any;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface BlogClientConfig {\n /**\n * Table name for blog posts (default: \"blog_posts\")\n */\n postsTable?: string;\n /**\n * Table name for blog media (default: \"blog_media\")\n */\n mediaTable?: string;\n /**\n * Enable/disable author joins (default: true)\n */\n includeAuthor?: boolean;\n /**\n * Users table name for author joins (default: \"users\")\n */\n usersTable?: string;\n}\n\nconst DEFAULT_CONFIG: Required<BlogClientConfig> = {\n postsTable: \"blog_posts\",\n mediaTable: \"blog_media\",\n includeAuthor: true,\n usersTable: \"users\",\n};\n\n// ============================================================================\n// Blog Client Factory\n// ============================================================================\n\n/**\n * Creates a blog client with pre-built CRUD operations\n */\nexport function createBlogClient(\n supabase: SupabaseClient,\n config: BlogClientConfig = {}\n) {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n return {\n /**\n * Blog post operations\n */\n posts: {\n /**\n * List blog posts with filtering and pagination\n */\n async list(\n params: BlogFilterParams = {}\n ): Promise<BlogPostListResponse> {\n const {\n page = 1,\n pageSize = 10,\n status,\n category,\n tag,\n search,\n orderBy = \"created_at\",\n orderDirection = \"desc\",\n } = params;\n\n const from = (page - 1) * pageSize;\n const to = from + pageSize - 1;\n\n let query = supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\",\n { count: \"exact\" }\n )\n .range(from, to)\n .order(orderBy, { ascending: orderDirection === \"asc\" });\n\n if (status) {\n query = query.eq(\"status\", status);\n }\n\n if (category) {\n query = query.eq(\"category\", category);\n }\n\n if (tag) {\n query = query.contains(\"tags\", [tag]);\n }\n\n if (search) {\n query = query.or(\n `title.ilike.%${search}%,excerpt.ilike.%${search}%,category.ilike.%${search}%`\n );\n }\n\n const { data, error, count } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog posts: ${error.message}`);\n }\n\n return {\n posts: (data as unknown as BlogPostWithAuthor[]) || [],\n total: count || 0,\n page,\n pageSize,\n totalPages: Math.ceil((count || 0) / pageSize),\n };\n },\n\n /**\n * Get a single post by slug\n */\n async getBySlug(slug: string): Promise<BlogPostWithAuthor | null> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\"\n )\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n // Not found\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostWithAuthor;\n },\n\n /**\n * Get a single post by ID\n */\n async getById(id: string): Promise<BlogPostRow | null> {\n const { data, error} = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Create a new blog post\n */\n async create(post: BlogPostInsert): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .insert(post)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Update an existing blog post\n */\n async update(\n id: string,\n updates: BlogPostUpdate\n ): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Delete a blog post\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.postsTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog post: ${error.message}`);\n }\n },\n\n /**\n * Publish a draft post\n */\n async publish(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"published\" });\n },\n\n /**\n * Unpublish (archive) a post\n */\n async archive(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"archived\" });\n },\n\n /**\n * Search posts using full-text search\n */\n async search(query: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_search_posts\", { search_query: query })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to search blog posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by tag\n */\n async getByTag(tag: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_tag\", { tag_name: tag })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get posts by tag: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by category\n */\n async getByCategory(\n category: string,\n limit: number = 10\n ): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_category\", { category_name: category })\n .limit(limit);\n\n if (error) {\n throw new Error(\n `Failed to get posts by category: ${error.message}`\n );\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get related posts (by tags and category)\n */\n async getRelated(postId: string, limit: number = 3): Promise<BlogPostRow[]> {\n const post = await this.getById(postId);\n if (!post) return [];\n\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"status\", \"published\")\n .neq(\"id\", postId)\n .or(`category.eq.${post.category},tags.ov.{${post.tags.join(\",\")}}`)\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get related posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n },\n\n /**\n * Blog media operations\n */\n media: {\n /**\n * List all media files\n */\n async list(\n type?: string,\n limit: number = 50\n ): Promise<BlogMediaRow[]> {\n let query = supabase\n .from(cfg.mediaTable)\n .select(\"*\")\n .order(\"uploaded_at\", { ascending: false })\n .limit(limit);\n\n if (type) {\n query = query.eq(\"type\", type);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog media: ${error.message}`);\n }\n\n return (data as unknown as BlogMediaRow[]) || [];\n },\n\n /**\n * Create new media record\n */\n async create(media: BlogMediaInsert): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .insert(media)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Update media record\n */\n async update(id: string, updates: BlogMediaUpdate): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Delete media record\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.mediaTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog media: ${error.message}`);\n }\n },\n },\n\n /**\n * Statistics and analytics\n */\n stats: {\n /**\n * Get blog statistics\n */\n async getStats(): Promise<BlogStats> {\n const { data: posts, error } = await supabase\n .from(cfg.postsTable)\n .select(\"status, category, tags\");\n\n if (error) {\n throw new Error(`Failed to fetch blog stats: ${error.message}`);\n }\n\n const stats: BlogStats = {\n totalPosts: posts.length,\n publishedPosts: 0,\n draftPosts: 0,\n archivedPosts: 0,\n categoryCounts: {},\n tagCounts: {},\n };\n\n posts.forEach((post: any) => {\n if (post.status === \"published\") stats.publishedPosts++;\n if (post.status === \"draft\") stats.draftPosts++;\n if (post.status === \"archived\") stats.archivedPosts++;\n\n if (post.category) {\n stats.categoryCounts[post.category] =\n (stats.categoryCounts[post.category] || 0) + 1;\n }\n\n post.tags?.forEach((tag: string) => {\n stats.tagCounts[tag] = (stats.tagCounts[tag] || 0) + 1;\n });\n });\n\n return stats;\n },\n\n /**\n * Get all categories with post counts\n */\n async getCategories(): Promise<BlogCategory[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"category\")\n .eq(\"status\", \"published\")\n .not(\"category\", \"is\", null);\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n if (row.category) {\n counts[row.category] = (counts[row.category] || 0) + 1;\n }\n });\n\n return Object.entries(counts).map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }));\n },\n\n /**\n * Get all tags with post counts\n */\n async getTags(): Promise<BlogTag[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"tags\")\n .eq(\"status\", \"published\");\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n row.tags?.forEach((tag: string) => {\n counts[tag] = (counts[tag] || 0) + 1;\n });\n });\n\n return Object.entries(counts)\n .map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }))\n .sort((a, b) => b.postCount - a.postCount);\n },\n },\n\n /**\n * Category management operations (v0.4.0+)\n */\n categories: {\n /**\n * List all categories\n */\n async list(): Promise<import(\"../types/database\").CategoryRow[]> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .select(\"*\")\n .order(\"display_order\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryRow[]) || [];\n },\n\n /**\n * List categories with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").CategoryWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_categories_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch categories with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryWithCount[]) || [];\n },\n\n /**\n * Get category by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Get category by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Create a new category\n */\n async create(category: import(\"../types/database\").CategoryInsert): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .insert(category)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Update an existing category\n */\n async update(id: string, updates: import(\"../types/database\").CategoryUpdate): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Delete a category\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog_categories\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete category: ${error.message}`);\n }\n },\n },\n\n /**\n * Tag management operations (v0.4.0+)\n */\n tags: {\n /**\n * List all tags\n */\n async list(): Promise<import(\"../types/database\").TagRow[]> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .select(\"*\")\n .order(\"name\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagRow[]) || [];\n },\n\n /**\n * List tags with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").TagWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_tags_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch tags with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagWithCount[]) || [];\n },\n\n /**\n * Get tag by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Get tag by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Create a new tag\n */\n async create(tag: import(\"../types/database\").TagInsert): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .insert(tag)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Update an existing tag\n */\n async update(id: string, updates: import(\"../types/database\").TagUpdate): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Delete a tag\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog_tags\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete tag: ${error.message}`);\n }\n },\n },\n };\n}\n\n/**\n * Type helper to extract the blog client type\n */\nexport type BlogClient = ReturnType<typeof createBlogClient>;\n"],"mappings":"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","names":[]}
@@ -308,7 +308,7 @@ function createBlogClient(supabase, config = {}) {
308
308
  * List all categories
309
309
  */
310
310
  async list() {
311
- const { data, error } = await supabase.from("blog.categories").select("*").order("display_order", { ascending: true });
311
+ const { data, error } = await supabase.from("blog_categories").select("*").order("display_order", { ascending: true });
312
312
  if (error) {
313
313
  throw new Error(`Failed to fetch categories: ${error.message}`);
314
314
  }
@@ -328,7 +328,7 @@ function createBlogClient(supabase, config = {}) {
328
328
  * Get category by ID
329
329
  */
330
330
  async getById(id) {
331
- const { data, error } = await supabase.from("blog.categories").select("*").eq("id", id).single();
331
+ const { data, error } = await supabase.from("blog_categories").select("*").eq("id", id).single();
332
332
  if (error) {
333
333
  if (error.code === "PGRST116") return null;
334
334
  throw new Error(`Failed to fetch category: ${error.message}`);
@@ -339,7 +339,7 @@ function createBlogClient(supabase, config = {}) {
339
339
  * Get category by slug
340
340
  */
341
341
  async getBySlug(slug) {
342
- const { data, error } = await supabase.from("blog.categories").select("*").eq("slug", slug).single();
342
+ const { data, error } = await supabase.from("blog_categories").select("*").eq("slug", slug).single();
343
343
  if (error) {
344
344
  if (error.code === "PGRST116") return null;
345
345
  throw new Error(`Failed to fetch category: ${error.message}`);
@@ -350,7 +350,7 @@ function createBlogClient(supabase, config = {}) {
350
350
  * Create a new category
351
351
  */
352
352
  async create(category) {
353
- const { data, error } = await supabase.from("blog.categories").insert(category).select().single();
353
+ const { data, error } = await supabase.from("blog_categories").insert(category).select().single();
354
354
  if (error) {
355
355
  throw new Error(`Failed to create category: ${error.message}`);
356
356
  }
@@ -360,7 +360,7 @@ function createBlogClient(supabase, config = {}) {
360
360
  * Update an existing category
361
361
  */
362
362
  async update(id, updates) {
363
- const { data, error } = await supabase.from("blog.categories").update(updates).eq("id", id).select().single();
363
+ const { data, error } = await supabase.from("blog_categories").update(updates).eq("id", id).select().single();
364
364
  if (error) {
365
365
  throw new Error(`Failed to update category: ${error.message}`);
366
366
  }
@@ -370,7 +370,7 @@ function createBlogClient(supabase, config = {}) {
370
370
  * Delete a category
371
371
  */
372
372
  async delete(id) {
373
- const { error } = await supabase.from("blog.categories").delete().eq("id", id);
373
+ const { error } = await supabase.from("blog_categories").delete().eq("id", id);
374
374
  if (error) {
375
375
  throw new Error(`Failed to delete category: ${error.message}`);
376
376
  }
@@ -384,7 +384,7 @@ function createBlogClient(supabase, config = {}) {
384
384
  * List all tags
385
385
  */
386
386
  async list() {
387
- const { data, error } = await supabase.from("blog.tags").select("*").order("name", { ascending: true });
387
+ const { data, error } = await supabase.from("blog_tags").select("*").order("name", { ascending: true });
388
388
  if (error) {
389
389
  throw new Error(`Failed to fetch tags: ${error.message}`);
390
390
  }
@@ -404,7 +404,7 @@ function createBlogClient(supabase, config = {}) {
404
404
  * Get tag by ID
405
405
  */
406
406
  async getById(id) {
407
- const { data, error } = await supabase.from("blog.tags").select("*").eq("id", id).single();
407
+ const { data, error } = await supabase.from("blog_tags").select("*").eq("id", id).single();
408
408
  if (error) {
409
409
  if (error.code === "PGRST116") return null;
410
410
  throw new Error(`Failed to fetch tag: ${error.message}`);
@@ -415,7 +415,7 @@ function createBlogClient(supabase, config = {}) {
415
415
  * Get tag by slug
416
416
  */
417
417
  async getBySlug(slug) {
418
- const { data, error } = await supabase.from("blog.tags").select("*").eq("slug", slug).single();
418
+ const { data, error } = await supabase.from("blog_tags").select("*").eq("slug", slug).single();
419
419
  if (error) {
420
420
  if (error.code === "PGRST116") return null;
421
421
  throw new Error(`Failed to fetch tag: ${error.message}`);
@@ -426,7 +426,7 @@ function createBlogClient(supabase, config = {}) {
426
426
  * Create a new tag
427
427
  */
428
428
  async create(tag) {
429
- const { data, error } = await supabase.from("blog.tags").insert(tag).select().single();
429
+ const { data, error } = await supabase.from("blog_tags").insert(tag).select().single();
430
430
  if (error) {
431
431
  throw new Error(`Failed to create tag: ${error.message}`);
432
432
  }
@@ -436,7 +436,7 @@ function createBlogClient(supabase, config = {}) {
436
436
  * Update an existing tag
437
437
  */
438
438
  async update(id, updates) {
439
- const { data, error } = await supabase.from("blog.tags").update(updates).eq("id", id).select().single();
439
+ const { data, error } = await supabase.from("blog_tags").update(updates).eq("id", id).select().single();
440
440
  if (error) {
441
441
  throw new Error(`Failed to update tag: ${error.message}`);
442
442
  }
@@ -446,7 +446,7 @@ function createBlogClient(supabase, config = {}) {
446
446
  * Delete a tag
447
447
  */
448
448
  async delete(id) {
449
- const { error } = await supabase.from("blog.tags").delete().eq("id", id);
449
+ const { error } = await supabase.from("blog_tags").delete().eq("id", id);
450
450
  if (error) {
451
451
  throw new Error(`Failed to delete tag: ${error.message}`);
452
452
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/supabase.ts"],"sourcesContent":["/**\n * Supabase Data Access Layer for m14i-blogging\n *\n * Provides pre-built CRUD operations for blog posts and media.\n * Works with the blog_posts and blog_media tables.\n *\n * @example\n * ```typescript\n * import { createBlogClient } from 'm14i-blogging/client';\n * import { createClient } from '@supabase/supabase-js';\n *\n * const supabase = createClient(url, key);\n * const blog = createBlogClient(supabase);\n *\n * // Use it\n * const posts = await blog.posts.list({ status: 'published' });\n * const post = await blog.posts.getBySlug('my-post');\n * ```\n */\n\nimport type {\n BlogPostRow,\n BlogPostInsert,\n BlogPostUpdate,\n BlogPostWithAuthor,\n BlogFilterParams,\n BlogPostListResponse,\n BlogMediaRow,\n BlogMediaInsert,\n BlogMediaUpdate,\n BlogStats,\n BlogCategory,\n BlogTag,\n} from \"../types/database\";\n\n// ============================================================================\n// Supabase Client Type\n// ============================================================================\n\nexport interface SupabaseClient {\n from(table: string): {\n select(query: string, options?: { count?: string }): any;\n insert(data: any): any;\n update(data: any): any;\n delete(): any;\n upsert(data: any): any;\n };\n rpc(functionName: string, params?: any): any;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface BlogClientConfig {\n /**\n * Table name for blog posts (default: \"blog_posts\")\n */\n postsTable?: string;\n /**\n * Table name for blog media (default: \"blog_media\")\n */\n mediaTable?: string;\n /**\n * Enable/disable author joins (default: true)\n */\n includeAuthor?: boolean;\n /**\n * Users table name for author joins (default: \"users\")\n */\n usersTable?: string;\n}\n\nconst DEFAULT_CONFIG: Required<BlogClientConfig> = {\n postsTable: \"blog_posts\",\n mediaTable: \"blog_media\",\n includeAuthor: true,\n usersTable: \"users\",\n};\n\n// ============================================================================\n// Blog Client Factory\n// ============================================================================\n\n/**\n * Creates a blog client with pre-built CRUD operations\n */\nexport function createBlogClient(\n supabase: SupabaseClient,\n config: BlogClientConfig = {}\n) {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n return {\n /**\n * Blog post operations\n */\n posts: {\n /**\n * List blog posts with filtering and pagination\n */\n async list(\n params: BlogFilterParams = {}\n ): Promise<BlogPostListResponse> {\n const {\n page = 1,\n pageSize = 10,\n status,\n category,\n tag,\n search,\n orderBy = \"created_at\",\n orderDirection = \"desc\",\n } = params;\n\n const from = (page - 1) * pageSize;\n const to = from + pageSize - 1;\n\n let query = supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\",\n { count: \"exact\" }\n )\n .range(from, to)\n .order(orderBy, { ascending: orderDirection === \"asc\" });\n\n if (status) {\n query = query.eq(\"status\", status);\n }\n\n if (category) {\n query = query.eq(\"category\", category);\n }\n\n if (tag) {\n query = query.contains(\"tags\", [tag]);\n }\n\n if (search) {\n query = query.or(\n `title.ilike.%${search}%,excerpt.ilike.%${search}%,category.ilike.%${search}%`\n );\n }\n\n const { data, error, count } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog posts: ${error.message}`);\n }\n\n return {\n posts: (data as unknown as BlogPostWithAuthor[]) || [],\n total: count || 0,\n page,\n pageSize,\n totalPages: Math.ceil((count || 0) / pageSize),\n };\n },\n\n /**\n * Get a single post by slug\n */\n async getBySlug(slug: string): Promise<BlogPostWithAuthor | null> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\"\n )\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n // Not found\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostWithAuthor;\n },\n\n /**\n * Get a single post by ID\n */\n async getById(id: string): Promise<BlogPostRow | null> {\n const { data, error} = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Create a new blog post\n */\n async create(post: BlogPostInsert): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .insert(post)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Update an existing blog post\n */\n async update(\n id: string,\n updates: BlogPostUpdate\n ): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Delete a blog post\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.postsTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog post: ${error.message}`);\n }\n },\n\n /**\n * Publish a draft post\n */\n async publish(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"published\" });\n },\n\n /**\n * Unpublish (archive) a post\n */\n async archive(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"archived\" });\n },\n\n /**\n * Search posts using full-text search\n */\n async search(query: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_search_posts\", { search_query: query })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to search blog posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by tag\n */\n async getByTag(tag: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_tag\", { tag_name: tag })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get posts by tag: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by category\n */\n async getByCategory(\n category: string,\n limit: number = 10\n ): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_category\", { category_name: category })\n .limit(limit);\n\n if (error) {\n throw new Error(\n `Failed to get posts by category: ${error.message}`\n );\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get related posts (by tags and category)\n */\n async getRelated(postId: string, limit: number = 3): Promise<BlogPostRow[]> {\n const post = await this.getById(postId);\n if (!post) return [];\n\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"status\", \"published\")\n .neq(\"id\", postId)\n .or(`category.eq.${post.category},tags.ov.{${post.tags.join(\",\")}}`)\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get related posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n },\n\n /**\n * Blog media operations\n */\n media: {\n /**\n * List all media files\n */\n async list(\n type?: string,\n limit: number = 50\n ): Promise<BlogMediaRow[]> {\n let query = supabase\n .from(cfg.mediaTable)\n .select(\"*\")\n .order(\"uploaded_at\", { ascending: false })\n .limit(limit);\n\n if (type) {\n query = query.eq(\"type\", type);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog media: ${error.message}`);\n }\n\n return (data as unknown as BlogMediaRow[]) || [];\n },\n\n /**\n * Create new media record\n */\n async create(media: BlogMediaInsert): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .insert(media)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Update media record\n */\n async update(id: string, updates: BlogMediaUpdate): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Delete media record\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.mediaTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog media: ${error.message}`);\n }\n },\n },\n\n /**\n * Statistics and analytics\n */\n stats: {\n /**\n * Get blog statistics\n */\n async getStats(): Promise<BlogStats> {\n const { data: posts, error } = await supabase\n .from(cfg.postsTable)\n .select(\"status, category, tags\");\n\n if (error) {\n throw new Error(`Failed to fetch blog stats: ${error.message}`);\n }\n\n const stats: BlogStats = {\n totalPosts: posts.length,\n publishedPosts: 0,\n draftPosts: 0,\n archivedPosts: 0,\n categoryCounts: {},\n tagCounts: {},\n };\n\n posts.forEach((post: any) => {\n if (post.status === \"published\") stats.publishedPosts++;\n if (post.status === \"draft\") stats.draftPosts++;\n if (post.status === \"archived\") stats.archivedPosts++;\n\n if (post.category) {\n stats.categoryCounts[post.category] =\n (stats.categoryCounts[post.category] || 0) + 1;\n }\n\n post.tags?.forEach((tag: string) => {\n stats.tagCounts[tag] = (stats.tagCounts[tag] || 0) + 1;\n });\n });\n\n return stats;\n },\n\n /**\n * Get all categories with post counts\n */\n async getCategories(): Promise<BlogCategory[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"category\")\n .eq(\"status\", \"published\")\n .not(\"category\", \"is\", null);\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n if (row.category) {\n counts[row.category] = (counts[row.category] || 0) + 1;\n }\n });\n\n return Object.entries(counts).map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }));\n },\n\n /**\n * Get all tags with post counts\n */\n async getTags(): Promise<BlogTag[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"tags\")\n .eq(\"status\", \"published\");\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n row.tags?.forEach((tag: string) => {\n counts[tag] = (counts[tag] || 0) + 1;\n });\n });\n\n return Object.entries(counts)\n .map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }))\n .sort((a, b) => b.postCount - a.postCount);\n },\n },\n\n /**\n * Category management operations (v0.4.0+)\n */\n categories: {\n /**\n * List all categories\n */\n async list(): Promise<import(\"../types/database\").CategoryRow[]> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .select(\"*\")\n .order(\"display_order\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryRow[]) || [];\n },\n\n /**\n * List categories with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").CategoryWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_categories_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch categories with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryWithCount[]) || [];\n },\n\n /**\n * Get category by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Get category by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Create a new category\n */\n async create(category: import(\"../types/database\").CategoryInsert): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .insert(category)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Update an existing category\n */\n async update(id: string, updates: import(\"../types/database\").CategoryUpdate): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog.categories\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Delete a category\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog.categories\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete category: ${error.message}`);\n }\n },\n },\n\n /**\n * Tag management operations (v0.4.0+)\n */\n tags: {\n /**\n * List all tags\n */\n async list(): Promise<import(\"../types/database\").TagRow[]> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .select(\"*\")\n .order(\"name\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagRow[]) || [];\n },\n\n /**\n * List tags with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").TagWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_tags_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch tags with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagWithCount[]) || [];\n },\n\n /**\n * Get tag by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Get tag by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Create a new tag\n */\n async create(tag: import(\"../types/database\").TagInsert): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .insert(tag)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Update an existing tag\n */\n async update(id: string, updates: import(\"../types/database\").TagUpdate): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog.tags\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Delete a tag\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog.tags\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete tag: ${error.message}`);\n }\n },\n },\n };\n}\n\n/**\n * Type helper to extract the blog client type\n */\nexport type BlogClient = ReturnType<typeof createBlogClient>;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/client/supabase.ts"],"sourcesContent":["/**\n * Supabase Data Access Layer for m14i-blogging\n *\n * Provides pre-built CRUD operations for blog posts and media.\n * Works with the blog_posts and blog_media tables.\n *\n * @example\n * ```typescript\n * import { createBlogClient } from 'm14i-blogging/client';\n * import { createClient } from '@supabase/supabase-js';\n *\n * const supabase = createClient(url, key);\n * const blog = createBlogClient(supabase);\n *\n * // Use it\n * const posts = await blog.posts.list({ status: 'published' });\n * const post = await blog.posts.getBySlug('my-post');\n * ```\n */\n\nimport type {\n BlogPostRow,\n BlogPostInsert,\n BlogPostUpdate,\n BlogPostWithAuthor,\n BlogFilterParams,\n BlogPostListResponse,\n BlogMediaRow,\n BlogMediaInsert,\n BlogMediaUpdate,\n BlogStats,\n BlogCategory,\n BlogTag,\n} from \"../types/database\";\n\n// ============================================================================\n// Supabase Client Type\n// ============================================================================\n\nexport interface SupabaseClient {\n from(table: string): {\n select(query: string, options?: { count?: string }): any;\n insert(data: any): any;\n update(data: any): any;\n delete(): any;\n upsert(data: any): any;\n };\n rpc(functionName: string, params?: any): any;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface BlogClientConfig {\n /**\n * Table name for blog posts (default: \"blog_posts\")\n */\n postsTable?: string;\n /**\n * Table name for blog media (default: \"blog_media\")\n */\n mediaTable?: string;\n /**\n * Enable/disable author joins (default: true)\n */\n includeAuthor?: boolean;\n /**\n * Users table name for author joins (default: \"users\")\n */\n usersTable?: string;\n}\n\nconst DEFAULT_CONFIG: Required<BlogClientConfig> = {\n postsTable: \"blog_posts\",\n mediaTable: \"blog_media\",\n includeAuthor: true,\n usersTable: \"users\",\n};\n\n// ============================================================================\n// Blog Client Factory\n// ============================================================================\n\n/**\n * Creates a blog client with pre-built CRUD operations\n */\nexport function createBlogClient(\n supabase: SupabaseClient,\n config: BlogClientConfig = {}\n) {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n return {\n /**\n * Blog post operations\n */\n posts: {\n /**\n * List blog posts with filtering and pagination\n */\n async list(\n params: BlogFilterParams = {}\n ): Promise<BlogPostListResponse> {\n const {\n page = 1,\n pageSize = 10,\n status,\n category,\n tag,\n search,\n orderBy = \"created_at\",\n orderDirection = \"desc\",\n } = params;\n\n const from = (page - 1) * pageSize;\n const to = from + pageSize - 1;\n\n let query = supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\",\n { count: \"exact\" }\n )\n .range(from, to)\n .order(orderBy, { ascending: orderDirection === \"asc\" });\n\n if (status) {\n query = query.eq(\"status\", status);\n }\n\n if (category) {\n query = query.eq(\"category\", category);\n }\n\n if (tag) {\n query = query.contains(\"tags\", [tag]);\n }\n\n if (search) {\n query = query.or(\n `title.ilike.%${search}%,excerpt.ilike.%${search}%,category.ilike.%${search}%`\n );\n }\n\n const { data, error, count } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog posts: ${error.message}`);\n }\n\n return {\n posts: (data as unknown as BlogPostWithAuthor[]) || [],\n total: count || 0,\n page,\n pageSize,\n totalPages: Math.ceil((count || 0) / pageSize),\n };\n },\n\n /**\n * Get a single post by slug\n */\n async getBySlug(slug: string): Promise<BlogPostWithAuthor | null> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\n cfg.includeAuthor\n ? `\n *,\n author:${cfg.usersTable}!created_by(full_name, email, avatar_url)\n `\n : \"*\"\n )\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n // Not found\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostWithAuthor;\n },\n\n /**\n * Get a single post by ID\n */\n async getById(id: string): Promise<BlogPostRow | null> {\n const { data, error} = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n return null;\n }\n throw new Error(`Failed to fetch blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Create a new blog post\n */\n async create(post: BlogPostInsert): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .insert(post)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Update an existing blog post\n */\n async update(\n id: string,\n updates: BlogPostUpdate\n ): Promise<BlogPostRow> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog post: ${error.message}`);\n }\n\n return data as unknown as BlogPostRow;\n },\n\n /**\n * Delete a blog post\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.postsTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog post: ${error.message}`);\n }\n },\n\n /**\n * Publish a draft post\n */\n async publish(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"published\" });\n },\n\n /**\n * Unpublish (archive) a post\n */\n async archive(id: string): Promise<BlogPostRow> {\n return this.update(id, { status: \"archived\" });\n },\n\n /**\n * Search posts using full-text search\n */\n async search(query: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_search_posts\", { search_query: query })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to search blog posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by tag\n */\n async getByTag(tag: string, limit: number = 10): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_tag\", { tag_name: tag })\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get posts by tag: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get posts by category\n */\n async getByCategory(\n category: string,\n limit: number = 10\n ): Promise<BlogPostRow[]> {\n const { data, error } = await supabase\n .rpc(\"blog_get_posts_by_category\", { category_name: category })\n .limit(limit);\n\n if (error) {\n throw new Error(\n `Failed to get posts by category: ${error.message}`\n );\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n\n /**\n * Get related posts (by tags and category)\n */\n async getRelated(postId: string, limit: number = 3): Promise<BlogPostRow[]> {\n const post = await this.getById(postId);\n if (!post) return [];\n\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"*\")\n .eq(\"status\", \"published\")\n .neq(\"id\", postId)\n .or(`category.eq.${post.category},tags.ov.{${post.tags.join(\",\")}}`)\n .limit(limit);\n\n if (error) {\n throw new Error(`Failed to get related posts: ${error.message}`);\n }\n\n return (data as unknown as BlogPostRow[]) || [];\n },\n },\n\n /**\n * Blog media operations\n */\n media: {\n /**\n * List all media files\n */\n async list(\n type?: string,\n limit: number = 50\n ): Promise<BlogMediaRow[]> {\n let query = supabase\n .from(cfg.mediaTable)\n .select(\"*\")\n .order(\"uploaded_at\", { ascending: false })\n .limit(limit);\n\n if (type) {\n query = query.eq(\"type\", type);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new Error(`Failed to fetch blog media: ${error.message}`);\n }\n\n return (data as unknown as BlogMediaRow[]) || [];\n },\n\n /**\n * Create new media record\n */\n async create(media: BlogMediaInsert): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .insert(media)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Update media record\n */\n async update(id: string, updates: BlogMediaUpdate): Promise<BlogMediaRow> {\n const { data, error } = await supabase\n .from(cfg.mediaTable)\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update blog media: ${error.message}`);\n }\n\n return data as unknown as BlogMediaRow;\n },\n\n /**\n * Delete media record\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(cfg.mediaTable)\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete blog media: ${error.message}`);\n }\n },\n },\n\n /**\n * Statistics and analytics\n */\n stats: {\n /**\n * Get blog statistics\n */\n async getStats(): Promise<BlogStats> {\n const { data: posts, error } = await supabase\n .from(cfg.postsTable)\n .select(\"status, category, tags\");\n\n if (error) {\n throw new Error(`Failed to fetch blog stats: ${error.message}`);\n }\n\n const stats: BlogStats = {\n totalPosts: posts.length,\n publishedPosts: 0,\n draftPosts: 0,\n archivedPosts: 0,\n categoryCounts: {},\n tagCounts: {},\n };\n\n posts.forEach((post: any) => {\n if (post.status === \"published\") stats.publishedPosts++;\n if (post.status === \"draft\") stats.draftPosts++;\n if (post.status === \"archived\") stats.archivedPosts++;\n\n if (post.category) {\n stats.categoryCounts[post.category] =\n (stats.categoryCounts[post.category] || 0) + 1;\n }\n\n post.tags?.forEach((tag: string) => {\n stats.tagCounts[tag] = (stats.tagCounts[tag] || 0) + 1;\n });\n });\n\n return stats;\n },\n\n /**\n * Get all categories with post counts\n */\n async getCategories(): Promise<BlogCategory[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"category\")\n .eq(\"status\", \"published\")\n .not(\"category\", \"is\", null);\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n if (row.category) {\n counts[row.category] = (counts[row.category] || 0) + 1;\n }\n });\n\n return Object.entries(counts).map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }));\n },\n\n /**\n * Get all tags with post counts\n */\n async getTags(): Promise<BlogTag[]> {\n const { data, error } = await supabase\n .from(cfg.postsTable)\n .select(\"tags\")\n .eq(\"status\", \"published\");\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n const counts: Record<string, number> = {};\n data?.forEach((row: any) => {\n row.tags?.forEach((tag: string) => {\n counts[tag] = (counts[tag] || 0) + 1;\n });\n });\n\n return Object.entries(counts)\n .map(([name, postCount]) => ({\n name,\n slug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n postCount,\n }))\n .sort((a, b) => b.postCount - a.postCount);\n },\n },\n\n /**\n * Category management operations (v0.4.0+)\n */\n categories: {\n /**\n * List all categories\n */\n async list(): Promise<import(\"../types/database\").CategoryRow[]> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .select(\"*\")\n .order(\"display_order\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch categories: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryRow[]) || [];\n },\n\n /**\n * List categories with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").CategoryWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_categories_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch categories with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").CategoryWithCount[]) || [];\n },\n\n /**\n * Get category by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Get category by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").CategoryRow | null> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Create a new category\n */\n async create(category: import(\"../types/database\").CategoryInsert): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .insert(category)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Update an existing category\n */\n async update(id: string, updates: import(\"../types/database\").CategoryUpdate): Promise<import(\"../types/database\").CategoryRow> {\n const { data, error } = await supabase\n .from(\"blog_categories\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update category: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").CategoryRow;\n },\n\n /**\n * Delete a category\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog_categories\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete category: ${error.message}`);\n }\n },\n },\n\n /**\n * Tag management operations (v0.4.0+)\n */\n tags: {\n /**\n * List all tags\n */\n async list(): Promise<import(\"../types/database\").TagRow[]> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .select(\"*\")\n .order(\"name\", { ascending: true });\n\n if (error) {\n throw new Error(`Failed to fetch tags: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagRow[]) || [];\n },\n\n /**\n * List tags with post counts\n */\n async listWithCounts(): Promise<import(\"../types/database\").TagWithCount[]> {\n const { data, error } = await supabase\n .rpc(\"blog.get_tags_with_counts\");\n\n if (error) {\n throw new Error(`Failed to fetch tags with counts: ${error.message}`);\n }\n\n return (data as unknown as import(\"../types/database\").TagWithCount[]) || [];\n },\n\n /**\n * Get tag by ID\n */\n async getById(id: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .select(\"*\")\n .eq(\"id\", id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Get tag by slug\n */\n async getBySlug(slug: string): Promise<import(\"../types/database\").TagRow | null> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .select(\"*\")\n .eq(\"slug\", slug)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null;\n throw new Error(`Failed to fetch tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Create a new tag\n */\n async create(tag: import(\"../types/database\").TagInsert): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .insert(tag)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Update an existing tag\n */\n async update(id: string, updates: import(\"../types/database\").TagUpdate): Promise<import(\"../types/database\").TagRow> {\n const { data, error } = await supabase\n .from(\"blog_tags\")\n .update(updates)\n .eq(\"id\", id)\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to update tag: ${error.message}`);\n }\n\n return data as unknown as import(\"../types/database\").TagRow;\n },\n\n /**\n * Delete a tag\n */\n async delete(id: string): Promise<void> {\n const { error } = await supabase\n .from(\"blog_tags\")\n .delete()\n .eq(\"id\", id);\n\n if (error) {\n throw new Error(`Failed to delete tag: ${error.message}`);\n }\n },\n },\n };\n}\n\n/**\n * Type helper to extract the blog client type\n */\nexport type BlogClient = ReturnType<typeof createBlogClient>;\n"],"mappings":"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","names":[]}