@vitnode/blog 1.2.0-canary.75 → 1.2.0-canary.77

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.
Files changed (108) hide show
  1. package/dist/src/api/lib/categories-language.d.ts +10 -0
  2. package/dist/src/api/lib/categories-language.d.ts.map +1 -0
  3. package/dist/src/api/lib/categories-language.js +1 -0
  4. package/dist/src/api/lib/events.d.ts +28 -0
  5. package/dist/src/api/lib/events.d.ts.map +1 -0
  6. package/dist/src/api/lib/events.js +1 -0
  7. package/dist/src/api/lib/posts-language.d.ts +17 -0
  8. package/dist/src/api/lib/posts-language.d.ts.map +1 -0
  9. package/dist/src/api/lib/posts-language.js +1 -0
  10. package/dist/src/api/lib/search.d.ts +13 -0
  11. package/dist/src/api/lib/search.d.ts.map +1 -0
  12. package/dist/src/api/lib/search.js +1 -0
  13. package/dist/src/api/modules/admin/admin.module.d.ts +34 -14
  14. package/dist/src/api/modules/admin/admin.module.d.ts.map +1 -1
  15. package/dist/src/api/modules/admin/admin.module.js +1 -1
  16. package/dist/src/api/modules/admin/categories/categories.admin.module.d.ts +10 -4
  17. package/dist/src/api/modules/admin/categories/categories.admin.module.d.ts.map +1 -1
  18. package/dist/src/api/modules/admin/categories/routes/create.route.d.ts +10 -3
  19. package/dist/src/api/modules/admin/categories/routes/create.route.d.ts.map +1 -1
  20. package/dist/src/api/modules/admin/categories/routes/create.route.js +1 -1
  21. package/dist/src/api/modules/admin/categories/routes/delete.route.d.ts.map +1 -1
  22. package/dist/src/api/modules/admin/categories/routes/delete.route.js +1 -1
  23. package/dist/src/api/modules/admin/categories/routes/edit.route.d.ts +5 -2
  24. package/dist/src/api/modules/admin/categories/routes/edit.route.d.ts.map +1 -1
  25. package/dist/src/api/modules/admin/categories/routes/edit.route.js +1 -1
  26. package/dist/src/api/modules/admin/posts/posts.admin.module.d.ts +24 -10
  27. package/dist/src/api/modules/admin/posts/posts.admin.module.d.ts.map +1 -1
  28. package/dist/src/api/modules/admin/posts/routes/create.route.d.ts +24 -7
  29. package/dist/src/api/modules/admin/posts/routes/create.route.d.ts.map +1 -1
  30. package/dist/src/api/modules/admin/posts/routes/create.route.js +1 -1
  31. package/dist/src/api/modules/admin/posts/routes/delete.route.d.ts.map +1 -1
  32. package/dist/src/api/modules/admin/posts/routes/delete.route.js +1 -1
  33. package/dist/src/api/modules/admin/posts/routes/edit.route.d.ts +12 -5
  34. package/dist/src/api/modules/admin/posts/routes/edit.route.d.ts.map +1 -1
  35. package/dist/src/api/modules/admin/posts/routes/edit.route.js +1 -1
  36. package/dist/src/api/modules/categories/categories.module.d.ts +5 -1
  37. package/dist/src/api/modules/categories/categories.module.d.ts.map +1 -1
  38. package/dist/src/api/modules/categories/routes/get.route.d.ts +15 -1
  39. package/dist/src/api/modules/categories/routes/get.route.d.ts.map +1 -1
  40. package/dist/src/api/modules/categories/routes/get.route.js +1 -1
  41. package/dist/src/api/modules/posts/posts.module.d.ts +22 -5
  42. package/dist/src/api/modules/posts/posts.module.d.ts.map +1 -1
  43. package/dist/src/api/modules/posts/routes/get.route.d.ts +44 -10
  44. package/dist/src/api/modules/posts/routes/get.route.d.ts.map +1 -1
  45. package/dist/src/api/modules/posts/routes/get.route.js +1 -1
  46. package/dist/src/config.api.d.ts.map +1 -1
  47. package/dist/src/config.api.js +1 -1
  48. package/dist/src/config.d.ts.map +1 -1
  49. package/dist/src/config.js +1 -1
  50. package/dist/src/database/categories.d.ts +4 -23
  51. package/dist/src/database/categories.d.ts.map +1 -1
  52. package/dist/src/database/categories.js +1 -1
  53. package/dist/src/database/posts.d.ts +10 -48
  54. package/dist/src/database/posts.d.ts.map +1 -1
  55. package/dist/src/database/posts.js +1 -1
  56. package/dist/src/globals.css +44 -0
  57. package/dist/src/locales/en.json +92 -0
  58. package/dist/src/locales/index.d.ts +4 -0
  59. package/dist/src/locales/index.d.ts.map +1 -0
  60. package/dist/src/locales/index.js +1 -0
  61. package/dist/src/routes/breadcrumb/admin/blog/categories/page.d.ts +2 -0
  62. package/dist/src/routes/breadcrumb/admin/blog/categories/page.d.ts.map +1 -0
  63. package/dist/src/routes/breadcrumb/admin/blog/categories/page.js +1 -0
  64. package/dist/src/routes/breadcrumb/admin/blog/posts/page.d.ts +2 -0
  65. package/dist/src/routes/breadcrumb/admin/blog/posts/page.d.ts.map +1 -0
  66. package/dist/src/routes/breadcrumb/admin/blog/posts/page.js +1 -0
  67. package/dist/src/views/admin/categories/actions/create-edit/create-edit.d.ts +2 -2
  68. package/dist/src/views/admin/categories/actions/create-edit/create-edit.d.ts.map +1 -1
  69. package/dist/src/views/admin/categories/actions/create-edit/create-edit.js +1 -1
  70. package/dist/src/views/admin/categories/actions/create-edit/{mutation-api.d.ts → mutation-api.server.d.ts} +1 -1
  71. package/dist/src/views/admin/categories/actions/create-edit/mutation-api.server.d.ts.map +1 -0
  72. package/dist/src/views/admin/categories/table/actions/delete/delete-action.js +1 -1
  73. package/dist/src/views/admin/{posts/table/actions/delete/mutation-api.d.ts → categories/table/actions/delete/mutation-api.server.d.ts} +1 -1
  74. package/dist/src/views/admin/categories/table/actions/delete/mutation-api.server.d.ts.map +1 -0
  75. package/dist/src/views/admin/categories/table/actions/edit-action.d.ts +1 -1
  76. package/dist/src/views/admin/categories/table/actions/edit-action.d.ts.map +1 -1
  77. package/dist/src/views/admin/categories/table/actions/edit-action.js +1 -1
  78. package/dist/src/views/admin/categories/table/categories-admin-view.d.ts.map +1 -1
  79. package/dist/src/views/admin/categories/table/categories-admin-view.js +1 -1
  80. package/dist/src/views/admin/posts/actions/create-edit/create-edit.d.ts +2 -1
  81. package/dist/src/views/admin/posts/actions/create-edit/create-edit.d.ts.map +1 -1
  82. package/dist/src/views/admin/posts/actions/create-edit/create-edit.js +1 -1
  83. package/dist/src/views/admin/posts/actions/create-edit/multi-lang-fields.d.ts +10 -0
  84. package/dist/src/views/admin/posts/actions/create-edit/multi-lang-fields.d.ts.map +1 -0
  85. package/dist/src/views/admin/posts/actions/create-edit/multi-lang-fields.js +1 -0
  86. package/dist/src/views/admin/posts/actions/create-edit/{mutation-api.d.ts → mutation-api.server.d.ts} +1 -1
  87. package/dist/src/views/admin/posts/actions/create-edit/mutation-api.server.d.ts.map +1 -0
  88. package/dist/src/views/admin/posts/table/actions/delete/delete-action.js +1 -1
  89. package/dist/src/views/admin/{categories/table/actions/delete/mutation-api.d.ts → posts/table/actions/delete/mutation-api.server.d.ts} +1 -1
  90. package/dist/src/views/admin/posts/table/actions/delete/mutation-api.server.d.ts.map +1 -0
  91. package/dist/src/views/admin/posts/table/actions/edit-action.d.ts.map +1 -1
  92. package/dist/src/views/admin/posts/table/actions/edit-action.js +1 -1
  93. package/dist/src/views/admin/posts/table/posts-admin-view.d.ts.map +1 -1
  94. package/dist/src/views/admin/posts/table/posts-admin-view.js +1 -1
  95. package/package.json +19 -19
  96. package/src/locales/en.json +17 -5
  97. package/src/locales/index.ts +11 -0
  98. package/src/routes/breadcrumb/admin/blog/categories/page.tsx +5 -0
  99. package/src/routes/breadcrumb/admin/blog/posts/page.tsx +5 -0
  100. package/tsconfig.build.json +5 -0
  101. package/dist/src/views/admin/categories/actions/create-edit/mutation-api.d.ts.map +0 -1
  102. package/dist/src/views/admin/categories/table/actions/delete/mutation-api.d.ts.map +0 -1
  103. package/dist/src/views/admin/posts/actions/create-edit/mutation-api.d.ts.map +0 -1
  104. package/dist/src/views/admin/posts/table/actions/delete/mutation-api.d.ts.map +0 -1
  105. /package/dist/src/views/admin/categories/actions/create-edit/{mutation-api.js → mutation-api.server.js} +0 -0
  106. /package/dist/src/views/admin/categories/table/actions/delete/{mutation-api.js → mutation-api.server.js} +0 -0
  107. /package/dist/src/views/admin/posts/actions/create-edit/{mutation-api.js → mutation-api.server.js} +0 -0
  108. /package/dist/src/views/admin/posts/table/actions/delete/{mutation-api.js → mutation-api.server.js} +0 -0
@@ -0,0 +1,10 @@
1
+ import type { MultiLangValue } from "@vitnode/core/lib/helpers/multi-lang";
2
+ import type { Context } from "hono";
3
+ export declare const CATEGORY_LANG_TABLE = "blog_categories";
4
+ export declare const CATEGORY_LANG_VARIABLE = "title";
5
+ export interface CategoryTranslations {
6
+ title: MultiLangValue;
7
+ }
8
+ export declare const saveCategoryTranslations: (c: Context, itemId: number, { title }: CategoryTranslations) => Promise<void>;
9
+ export declare const loadCategoryTranslations: (c: Context, categoryIds: number[]) => Promise<Map<number, MultiLangValue>>;
10
+ //# sourceMappingURL=categories-language.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categories-language.d.ts","sourceRoot":"","sources":["../../../../src/api/lib/categories-language.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAQpC,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAE9C,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,CAAC;CACvB;AAID,eAAO,MAAM,wBAAwB,GACnC,GAAG,OAAO,EACV,QAAQ,MAAM,EACd,WAAW,oBAAoB,KAC9B,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,GAAG,OAAO,EACV,aAAa,MAAM,EAAE,KACpB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAiCrC,CAAC"}
@@ -0,0 +1 @@
1
+ import{saveLanguageWords}from"@vitnode/core/api/lib/save-language-words";import{core_languages_words}from"@vitnode/core/database/languages";import{and,eq,inArray}from"drizzle-orm";import{CONFIG_PLUGIN}from"../../const.js";export const CATEGORY_LANG_TABLE="blog_categories";export const CATEGORY_LANG_VARIABLE="title";export const saveCategoryTranslations=async(c,itemId,{title})=>{await saveLanguageWords(c,{pluginCode:CONFIG_PLUGIN.pluginId,tableName:CATEGORY_LANG_TABLE,variable:CATEGORY_LANG_VARIABLE,itemId,values:title})};export const loadCategoryTranslations=async(c,categoryIds)=>{const result=new Map;if(categoryIds.length===0){return result}const words=await c.get("db").select({itemId:core_languages_words.itemId,languageCode:core_languages_words.languageCode,value:core_languages_words.value}).from(core_languages_words).where(and(eq(core_languages_words.pluginCode,CONFIG_PLUGIN.pluginId),eq(core_languages_words.tableName,CATEGORY_LANG_TABLE),eq(core_languages_words.variable,CATEGORY_LANG_VARIABLE),inArray(core_languages_words.itemId,categoryIds)));for(const id of categoryIds){result.set(id,words.filter(word=>word.itemId===id).map(({languageCode,value})=>({languageCode,value})))}return result};
@@ -0,0 +1,28 @@
1
+ declare module "@vitnode/core/api/models/events" {
2
+ interface VitNodeEvents {
3
+ "blog.category.created": {
4
+ categoryId: number;
5
+ };
6
+ "blog.category.deleted": {
7
+ categoryId: number;
8
+ postIds: number[];
9
+ };
10
+ "blog.category.updated": {
11
+ categoryId: number;
12
+ };
13
+ "blog.post.created": {
14
+ categoryId: number;
15
+ postId: number;
16
+ };
17
+ "blog.post.deleted": {
18
+ categoryId: number;
19
+ postId: number;
20
+ };
21
+ "blog.post.updated": {
22
+ categoryId: number;
23
+ postId: number;
24
+ };
25
+ }
26
+ }
27
+ export declare const cleanupCategorySearchListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
28
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/api/lib/events.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,iCAAiC,CAAC;IAC/C,UAAU,aAAa;QACrB,uBAAuB,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,uBAAuB,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC;YACnB,OAAO,EAAE,MAAM,EAAE,CAAC;SACnB,CAAC;QACF,uBAAuB,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,mBAAmB,EAAE;YACnB,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,mBAAmB,EAAE;YACnB,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,mBAAmB,EAAE;YACnB,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH;CACF;AAED,eAAO,MAAM,6BAA6B,gIAUxC,CAAC"}
@@ -0,0 +1 @@
1
+ import{buildEventListener}from"@vitnode/core/api/lib/events";export const cleanupCategorySearchListener=buildEventListener({event:"blog.category.deleted",name:"cleanup-category-search",description:"Remove search index rows of posts cascade-deleted with a category",handler:async(c,payload)=>{for(const postId of payload.postIds){await c.get("search").delete("blog_post",postId)}}});
@@ -0,0 +1,17 @@
1
+ import type { MultiLangValue } from "@vitnode/core/lib/helpers/multi-lang";
2
+ import type { Context } from "hono";
3
+ export declare const POST_LANG_TABLE = "blog_posts";
4
+ export declare const POST_LANG_VARIABLES: readonly ["title", "content", "friendlyUrl"];
5
+ export type PostLangVariable = (typeof POST_LANG_VARIABLES)[number];
6
+ export interface PostTranslations {
7
+ content: MultiLangValue;
8
+ friendlyUrl: MultiLangValue;
9
+ title: MultiLangValue;
10
+ }
11
+ export declare const slugifyMultiLang: (values: MultiLangValue) => MultiLangValue;
12
+ export declare const getDefaultLanguageCode: (c: Context) => Promise<null | string>;
13
+ export declare const pickDefaultValue: (values: MultiLangValue, defaultLanguageCode: null | string) => string;
14
+ export declare const resolveLangValue: (values: MultiLangValue | undefined, languageCode: string, defaultLanguageCode: null | string) => string;
15
+ export declare const savePostTranslations: (c: Context, itemId: number, translations: PostTranslations) => Promise<void>;
16
+ export declare const loadPostTranslations: (c: Context, postIds: number[]) => Promise<Map<number, PostTranslations>>;
17
+ //# sourceMappingURL=posts-language.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posts-language.d.ts","sourceRoot":"","sources":["../../../../src/api/lib/posts-language.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAapC,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,mBAAmB,8CAA+C,CAAC;AAChF,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,cAAc,CAAC;IAC5B,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,eAAO,MAAM,gBAAgB,GAAI,QAAQ,cAAc,KAAG,cAIrD,CAAC;AAEN,eAAO,MAAM,sBAAsB,GACjC,GAAG,OAAO,KACT,OAAO,CAAC,IAAI,GAAG,MAAM,CASvB,CAAC;AAKF,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,cAAc,EACtB,qBAAqB,IAAI,GAAG,MAAM,KACjC,MAGC,CAAC;AAKL,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,cAAc,GAAG,SAAS,EAClC,cAAc,MAAM,EACpB,qBAAqB,IAAI,GAAG,MAAM,KACjC,MAEkD,CAAC;AAEtD,eAAO,MAAM,oBAAoB,GAC/B,GAAG,OAAO,EACV,QAAQ,MAAM,EACd,cAAc,gBAAgB,KAC7B,OAAO,CAAC,IAAI,CAed,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,GAAG,OAAO,EACV,SAAS,MAAM,EAAE,KAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAuCvC,CAAC"}
@@ -0,0 +1 @@
1
+ import{saveLanguageWords}from"@vitnode/core/api/lib/save-language-words";import{core_languages,core_languages_words}from"@vitnode/core/database/languages";import{getLangValue}from"@vitnode/core/lib/helpers/multi-lang";import{removeSpecialCharacters}from"@vitnode/core/lib/special-characters";import{and,eq,inArray}from"drizzle-orm";import{CONFIG_PLUGIN}from"../../const.js";export const POST_LANG_TABLE="blog_posts";export const POST_LANG_VARIABLES=["title","content","friendlyUrl"];export const slugifyMultiLang=values=>values.map(({languageCode,value})=>({languageCode,value:removeSpecialCharacters(value)}));export const getDefaultLanguageCode=async c=>{const[language]=await c.get("db").select({code:core_languages.code}).from(core_languages).where(eq(core_languages.default,true)).limit(1);return language?.code??null};export const pickDefaultValue=(values,defaultLanguageCode)=>values.find(item=>item.languageCode===defaultLanguageCode)?.value??values[0]?.value??"";export const resolveLangValue=(values,languageCode,defaultLanguageCode)=>getLangValue(values,languageCode)||pickDefaultValue(values??[],defaultLanguageCode);export const savePostTranslations=async(c,itemId,translations)=>{await Promise.all(POST_LANG_VARIABLES.map(async variable=>{await saveLanguageWords(c,{pluginCode:CONFIG_PLUGIN.pluginId,tableName:POST_LANG_TABLE,variable,itemId,values:variable==="friendlyUrl"?slugifyMultiLang(translations.friendlyUrl):translations[variable]})}))};export const loadPostTranslations=async(c,postIds)=>{const result=new Map;if(postIds.length===0){return result}const words=await c.get("db").select({itemId:core_languages_words.itemId,variable:core_languages_words.variable,languageCode:core_languages_words.languageCode,value:core_languages_words.value}).from(core_languages_words).where(and(eq(core_languages_words.pluginCode,CONFIG_PLUGIN.pluginId),eq(core_languages_words.tableName,POST_LANG_TABLE),inArray(core_languages_words.variable,[...POST_LANG_VARIABLES]),inArray(core_languages_words.itemId,postIds)));for(const id of postIds){result.set(id,{title:words.filter(word=>word.itemId===id&&word.variable==="title").map(({languageCode,value})=>({languageCode,value})),content:words.filter(word=>word.itemId===id&&word.variable==="content").map(({languageCode,value})=>({languageCode,value})),friendlyUrl:words.filter(word=>word.itemId===id&&word.variable==="friendlyUrl").map(({languageCode,value})=>({languageCode,value}))})}return result};
@@ -0,0 +1,13 @@
1
+ import type { SearchIndexer } from "@vitnode/core/api/models/search";
2
+ import type { Context } from "hono";
3
+ interface BlogPostForSearch {
4
+ authorId: null | number;
5
+ categoryId: number;
6
+ createdAt: Date;
7
+ id: number;
8
+ updatedAt?: Date;
9
+ }
10
+ export declare const reindexBlogPost: (c: Context, post: BlogPostForSearch) => Promise<void>;
11
+ export declare const blogPostSearchIndexer: SearchIndexer;
12
+ export {};
13
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../src/api/lib/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAepC,UAAU,iBAAiB;IACzB,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAuDD,eAAO,MAAM,eAAe,GAC1B,GAAG,OAAO,EACV,MAAM,iBAAiB,KACtB,OAAO,CAAC,IAAI,CAoBd,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,aA6CnC,CAAC"}
@@ -0,0 +1 @@
1
+ import{core_languages}from"@vitnode/core/database/languages";import{asc,count,eq}from"drizzle-orm";import{blog_posts}from"../../database/posts.js";import{getDefaultLanguageCode,loadPostTranslations,resolveLangValue}from"./posts-language.js";const getEnabledLanguageCodes=async c=>{const rows=await c.get("db").select({code:core_languages.code}).from(core_languages).where(eq(core_languages.enabled,true));return rows.map(row=>row.code)};const buildDocumentsForPost=(post,languageCodes,translations,defaultLanguageCode)=>{const codes=languageCodes.length>0?languageCodes:[""];return codes.map(languageCode=>{const friendlyUrl=resolveLangValue(translations?.friendlyUrl,languageCode,defaultLanguageCode);return{itemType:"blog_post",itemId:post.id,languageCode,authorId:post.authorId,title:resolveLangValue(translations?.title,languageCode,defaultLanguageCode),content:resolveLangValue(translations?.content,languageCode,defaultLanguageCode),containerType:"blog_category",containerId:post.categoryId,url:`/blog/${post.categoryId}/${friendlyUrl}`,isPublic:true,createdAt:post.createdAt,updatedAt:post.updatedAt}})};export const reindexBlogPost=async(c,post)=>{const[languageCodes,defaultLanguageCode,translations]=await Promise.all([getEnabledLanguageCodes(c),getDefaultLanguageCode(c),loadPostTranslations(c,[post.id])]);await c.get("search").delete("blog_post",post.id);await c.get("search").bulkIndex(buildDocumentsForPost(post,languageCodes,translations.get(post.id),defaultLanguageCode))};export const blogPostSearchIndexer={itemType:"blog_post",count:async c=>{const[row]=await c.get("db").select({value:count()}).from(blog_posts);return row?.value??0},load:async(c,offset,limit)=>{const rows=await c.get("db").select({id:blog_posts.id,categoryId:blog_posts.categoryId,authorId:blog_posts.authorId,createdAt:blog_posts.createdAt,updatedAt:blog_posts.updatedAt}).from(blog_posts).orderBy(asc(blog_posts.id)).limit(limit).offset(offset);if(rows.length===0){return[]}const[languageCodes,defaultLanguageCode,translations]=await Promise.all([getEnabledLanguageCodes(c),getDefaultLanguageCode(c),loadPostTranslations(c,rows.map(row=>row.id))]);return rows.flatMap(post=>buildDocumentsForPost(post,languageCodes,translations.get(post.id),defaultLanguageCode))}};
@@ -6,7 +6,11 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
6
6
  content: {
7
7
  "application/json": {
8
8
  schema: import("zod").ZodObject<{
9
- title: import("zod").ZodString;
9
+ title: import("zod").ZodArray<import("zod").ZodObject<{
10
+ languageCode: import("zod").ZodString;
11
+ value: import("zod").ZodString;
12
+ }, import("zod/v4/core").$strip>>;
13
+ color: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
10
14
  }, import("zod/v4/core").$strip>;
11
15
  };
12
16
  };
@@ -18,7 +22,6 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
18
22
  "application/json": {
19
23
  schema: import("zod").ZodObject<{
20
24
  id: import("zod").ZodNumber;
21
- title: import("zod").ZodString;
22
25
  createdAt: import("zod").ZodDate;
23
26
  updatedAt: import("zod").ZodDate;
24
27
  }, import("zod/v4/core").$strip>;
@@ -43,7 +46,11 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
43
46
  content: {
44
47
  "application/json": {
45
48
  schema: import("zod").ZodObject<{
46
- title: import("zod").ZodString;
49
+ title: import("zod").ZodArray<import("zod").ZodObject<{
50
+ languageCode: import("zod").ZodString;
51
+ value: import("zod").ZodString;
52
+ }, import("zod/v4/core").$strip>>;
53
+ color: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
47
54
  }, import("zod/v4/core").$strip>;
48
55
  };
49
56
  };
@@ -55,7 +62,6 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
55
62
  "application/json": {
56
63
  schema: import("zod").ZodObject<{
57
64
  id: import("zod").ZodNumber;
58
- title: import("zod").ZodString;
59
65
  createdAt: import("zod").ZodDate;
60
66
  updatedAt: import("zod").ZodDate;
61
67
  }, import("zod/v4/core").$strip>;
@@ -101,8 +107,18 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
101
107
  content: {
102
108
  "application/json": {
103
109
  schema: import("zod").ZodObject<{
104
- title: import("zod").ZodString;
105
- content: import("zod").ZodString;
110
+ title: import("zod").ZodArray<import("zod").ZodObject<{
111
+ languageCode: import("zod").ZodString;
112
+ value: import("zod").ZodString;
113
+ }, import("zod/v4/core").$strip>>;
114
+ content: import("zod").ZodArray<import("zod").ZodObject<{
115
+ languageCode: import("zod").ZodString;
116
+ value: import("zod").ZodString;
117
+ }, import("zod/v4/core").$strip>>;
118
+ friendlyUrl: import("zod").ZodArray<import("zod").ZodObject<{
119
+ languageCode: import("zod").ZodString;
120
+ value: import("zod").ZodString;
121
+ }, import("zod/v4/core").$strip>>;
106
122
  categoryId: import("zod").ZodNumber;
107
123
  }, import("zod/v4/core").$strip>;
108
124
  };
@@ -115,9 +131,6 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
115
131
  "application/json": {
116
132
  schema: import("zod").ZodObject<{
117
133
  id: import("zod").ZodNumber;
118
- title: import("zod").ZodString;
119
- titleSeo: import("zod").ZodString;
120
- content: import("zod").ZodString;
121
134
  categoryId: import("zod").ZodNumber;
122
135
  createdAt: import("zod").ZodDate;
123
136
  updatedAt: import("zod").ZodDate;
@@ -143,8 +156,18 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
143
156
  content: {
144
157
  "application/json": {
145
158
  schema: import("zod").ZodObject<{
146
- title: import("zod").ZodString;
147
- content: import("zod").ZodString;
159
+ title: import("zod").ZodArray<import("zod").ZodObject<{
160
+ languageCode: import("zod").ZodString;
161
+ value: import("zod").ZodString;
162
+ }, import("zod/v4/core").$strip>>;
163
+ content: import("zod").ZodArray<import("zod").ZodObject<{
164
+ languageCode: import("zod").ZodString;
165
+ value: import("zod").ZodString;
166
+ }, import("zod/v4/core").$strip>>;
167
+ friendlyUrl: import("zod").ZodArray<import("zod").ZodObject<{
168
+ languageCode: import("zod").ZodString;
169
+ value: import("zod").ZodString;
170
+ }, import("zod/v4/core").$strip>>;
148
171
  categoryId: import("zod").ZodNumber;
149
172
  }, import("zod/v4/core").$strip>;
150
173
  };
@@ -157,9 +180,6 @@ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildMo
157
180
  "application/json": {
158
181
  schema: import("zod").ZodObject<{
159
182
  id: import("zod").ZodNumber;
160
- title: import("zod").ZodString;
161
- titleSeo: import("zod").ZodString;
162
- content: import("zod").ZodString;
163
183
  categoryId: import("zod").ZodNumber;
164
184
  createdAt: import("zod").ZodDate;
165
185
  updatedAt: import("zod").ZodDate;
@@ -1 +1 @@
1
- {"version":3,"file":"admin.module.d.ts","sourceRoot":"","sources":["../../../../../src/api/modules/admin/admin.module.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0MAKtB,CAAC"}
1
+ {"version":3,"file":"admin.module.d.ts","sourceRoot":"","sources":["../../../../../src/api/modules/admin/admin.module.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0MAStB,CAAC"}
@@ -1 +1 @@
1
- import{buildModule}from"@vitnode/core/api/lib/module";import{CONFIG_PLUGIN}from"../../../const.js";import{categoriesAdminModule}from"./categories/categories.admin.module.js";import{postsAdminModule}from"./posts/posts.admin.module.js";export const adminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"admin",modules:[categoriesAdminModule,postsAdminModule],routes:[]});
1
+ import{buildModule}from"@vitnode/core/api/lib/module";import{CONFIG_PLUGIN}from"../../../const.js";import{cleanupCategorySearchListener}from"../../lib/events.js";import{categoriesAdminModule}from"./categories/categories.admin.module.js";import{postsAdminModule}from"./posts/posts.admin.module.js";export const adminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"admin",modules:[categoriesAdminModule,postsAdminModule],routes:[],events:[cleanupCategorySearchListener]});
@@ -6,7 +6,11 @@ export declare const categoriesAdminModule: import("@vitnode/core/api/lib/module
6
6
  content: {
7
7
  "application/json": {
8
8
  schema: import("zod").ZodObject<{
9
- title: import("zod").ZodString;
9
+ title: import("zod").ZodArray<import("zod").ZodObject<{
10
+ languageCode: import("zod").ZodString;
11
+ value: import("zod").ZodString;
12
+ }, import("zod/v4/core").$strip>>;
13
+ color: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
10
14
  }, import("zod/v4/core").$strip>;
11
15
  };
12
16
  };
@@ -18,7 +22,6 @@ export declare const categoriesAdminModule: import("@vitnode/core/api/lib/module
18
22
  "application/json": {
19
23
  schema: import("zod").ZodObject<{
20
24
  id: import("zod").ZodNumber;
21
- title: import("zod").ZodString;
22
25
  createdAt: import("zod").ZodDate;
23
26
  updatedAt: import("zod").ZodDate;
24
27
  }, import("zod/v4/core").$strip>;
@@ -43,7 +46,11 @@ export declare const categoriesAdminModule: import("@vitnode/core/api/lib/module
43
46
  content: {
44
47
  "application/json": {
45
48
  schema: import("zod").ZodObject<{
46
- title: import("zod").ZodString;
49
+ title: import("zod").ZodArray<import("zod").ZodObject<{
50
+ languageCode: import("zod").ZodString;
51
+ value: import("zod").ZodString;
52
+ }, import("zod/v4/core").$strip>>;
53
+ color: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
47
54
  }, import("zod/v4/core").$strip>;
48
55
  };
49
56
  };
@@ -55,7 +62,6 @@ export declare const categoriesAdminModule: import("@vitnode/core/api/lib/module
55
62
  "application/json": {
56
63
  schema: import("zod").ZodObject<{
57
64
  id: import("zod").ZodNumber;
58
- title: import("zod").ZodString;
59
65
  createdAt: import("zod").ZodDate;
60
66
  updatedAt: import("zod").ZodDate;
61
67
  }, import("zod/v4/core").$strip>;
@@ -1 +1 @@
1
- {"version":3,"file":"categories.admin.module.d.ts","sourceRoot":"","sources":["../../../../../../src/api/modules/admin/categories/categories.admin.module.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sMAIhC,CAAC"}
1
+ {"version":3,"file":"categories.admin.module.d.ts","sourceRoot":"","sources":["../../../../../../src/api/modules/admin/categories/categories.admin.module.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sMAIhC,CAAC"}
@@ -1,6 +1,10 @@
1
1
  import { z } from "@hono/zod-openapi";
2
2
  export declare const zodCreateCategorySchema: z.ZodObject<{
3
- title: z.ZodString;
3
+ title: z.ZodArray<z.ZodObject<{
4
+ languageCode: z.ZodString;
5
+ value: z.ZodString;
6
+ }, z.core.$strip>>;
7
+ color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
4
8
  }, z.core.$strip>;
5
9
  export declare const createCategoryRoute: import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
6
10
  method: "post";
@@ -10,7 +14,11 @@ export declare const createCategoryRoute: import("@vitnode/core/api/lib/route").
10
14
  content: {
11
15
  "application/json": {
12
16
  schema: z.ZodObject<{
13
- title: z.ZodString;
17
+ title: z.ZodArray<z.ZodObject<{
18
+ languageCode: z.ZodString;
19
+ value: z.ZodString;
20
+ }, z.core.$strip>>;
21
+ color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
14
22
  }, z.core.$strip>;
15
23
  };
16
24
  };
@@ -22,7 +30,6 @@ export declare const createCategoryRoute: import("@vitnode/core/api/lib/route").
22
30
  "application/json": {
23
31
  schema: z.ZodObject<{
24
32
  id: z.ZodNumber;
25
- title: z.ZodString;
26
33
  createdAt: z.ZodDate;
27
34
  updatedAt: z.ZodDate;
28
35
  }, z.core.$strip>;
@@ -1 +1 @@
1
- {"version":3,"file":"create.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/categories/routes/create.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAgBtC,eAAO,MAAM,uBAAuB;;iBAElC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0D9B,CAAC"}
1
+ {"version":3,"file":"create.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/categories/routes/create.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAetC,eAAO,MAAM,uBAAuB;;;;;;iBAGlC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+C9B,CAAC"}
@@ -1 +1 @@
1
- import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{removeSpecialCharacters}from"@vitnode/core/lib/special-characters";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";const zodCategoryResponseSchema=z.object({id:z.number(),title:z.string(),createdAt:z.date(),updatedAt:z.date()});export const zodCreateCategorySchema=z.object({title:z.string()});export const createCategoryRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"categories",permission:"can_create"},route:{method:"post",path:"/",request:{body:{content:{"application/json":{schema:zodCreateCategorySchema}}}},responses:{201:{content:{"application/json":{schema:zodCategoryResponseSchema}},description:"Category created successfully"},400:{description:"Bad request - Invalid input data"}}},handler:async c=>{const{title}=c.req.valid("json");const titleSeo=removeSpecialCharacters(title);const[titleSEODuplocate]=await c.get("db").select({titleSeo:blog_categories.titleSeo}).from(blog_categories).where(eq(blog_categories.titleSeo,titleSeo)).limit(1);if(titleSEODuplocate?.titleSeo===titleSeo){throw new HTTPException(400,{message:"Category with this title already exists."})}const[category]=await c.get("db").insert(blog_categories).values({title,titleSeo:removeSpecialCharacters(title)}).returning();return c.json(category,201)}});
1
+ import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{multiLangValueSchema}from"@vitnode/core/lib/helpers/multi-lang";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{saveCategoryTranslations}from"../../../../lib/categories-language.js";const zodCategoryResponseSchema=z.object({id:z.number(),createdAt:z.date(),updatedAt:z.date()});export const zodCreateCategorySchema=z.object({title:multiLangValueSchema({minLength:1,maxLength:100}).min(1),color:z.string().nullish()});export const createCategoryRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"categories",permission:"can_create"},route:{method:"post",path:"/",request:{body:{content:{"application/json":{schema:zodCreateCategorySchema}}}},responses:{201:{content:{"application/json":{schema:zodCategoryResponseSchema}},description:"Category created successfully"},400:{description:"Bad request - Invalid input data"}}},handler:async c=>{const{title,color}=c.req.valid("json");const[category]=await c.get("db").insert(blog_categories).values({color:color?.trim()?color:null}).returning();await saveCategoryTranslations(c,category.id,{title});await c.get("events").emit("blog.category.created",{categoryId:category.id});return c.json(category,201)}});
@@ -1 +1 @@
1
- {"version":3,"file":"delete.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/categories/routes/delete.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAQtC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAmC9B,CAAC"}
1
+ {"version":3,"file":"delete.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/categories/routes/delete.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAStC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAgD9B,CAAC"}
@@ -1 +1 @@
1
- import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";export const deleteCategoryRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"categories",permission:"can_delete"},route:{method:"delete",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)})},responses:{204:{description:"Category deleted successfully"},404:{description:"Category not found"}}},handler:async c=>{const{id}=c.req.valid("param");const result=await c.get("db").delete(blog_categories).where(eq(blog_categories.id,id)).returning();if(result.length===0){throw new HTTPException(404)}return c.body(null,204)}});
1
+ import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{blog_posts}from"../../../../../database/posts.js";export const deleteCategoryRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"categories",permission:"can_delete"},route:{method:"delete",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)})},responses:{204:{description:"Category deleted successfully"},404:{description:"Category not found"}}},handler:async c=>{const{id}=c.req.valid("param");const posts=await c.get("db").select({id:blog_posts.id}).from(blog_posts).where(eq(blog_posts.categoryId,id));const result=await c.get("db").delete(blog_categories).where(eq(blog_categories.id,id)).returning();if(result.length===0){throw new HTTPException(404)}await c.get("events").emit("blog.category.deleted",{categoryId:id,postIds:posts.map(post=>post.id)});return c.body(null,204)}});
@@ -10,7 +10,11 @@ export declare const editCategoryRoute: import("@vitnode/core/api/lib/route").Ro
10
10
  content: {
11
11
  "application/json": {
12
12
  schema: z.ZodObject<{
13
- title: z.ZodString;
13
+ title: z.ZodArray<z.ZodObject<{
14
+ languageCode: z.ZodString;
15
+ value: z.ZodString;
16
+ }, z.core.$strip>>;
17
+ color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
14
18
  }, z.core.$strip>;
15
19
  };
16
20
  };
@@ -22,7 +26,6 @@ export declare const editCategoryRoute: import("@vitnode/core/api/lib/route").Ro
22
26
  "application/json": {
23
27
  schema: z.ZodObject<{
24
28
  id: z.ZodNumber;
25
- title: z.ZodString;
26
29
  createdAt: z.ZodDate;
27
30
  updatedAt: z.ZodDate;
28
31
  }, z.core.$strip>;
@@ -1 +1 @@
1
- {"version":3,"file":"edit.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/categories/routes/edit.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAkBtC,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkF5B,CAAC"}
1
+ {"version":3,"file":"edit.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/categories/routes/edit.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAiBtC,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkE5B,CAAC"}
@@ -1 +1 @@
1
- import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{removeSpecialCharacters}from"@vitnode/core/lib/special-characters";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{zodCreateCategorySchema}from"./create.route.js";const zodCategoryResponseSchema=z.object({id:z.number(),title:z.string(),createdAt:z.date(),updatedAt:z.date()});export const editCategoryRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"categories",permission:"can_edit"},route:{method:"put",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)}),body:{content:{"application/json":{schema:zodCreateCategorySchema}}}},responses:{200:{content:{"application/json":{schema:zodCategoryResponseSchema}},description:"Category updated successfully"},400:{description:"Bad request - Invalid input data"},404:{description:"Category not found"}}},handler:async c=>{const{id}=c.req.valid("param");const{title}=c.req.valid("json");const titleSeo=removeSpecialCharacters(title);const[editData]=await c.get("db").select({titleSeo:blog_categories.titleSeo}).from(blog_categories).where(eq(blog_categories.id,id)).limit(1);if(!editData){throw new HTTPException(404)}const[titleSEODuplocate]=await c.get("db").select({titleSeo:blog_categories.titleSeo}).from(blog_categories).where(eq(blog_categories.titleSeo,titleSeo)).limit(1);if(titleSEODuplocate?.titleSeo===titleSeo&&titleSEODuplocate.titleSeo!==editData.titleSeo){throw new HTTPException(400,{message:"Category with this title already exists."})}const[category]=await c.get("db").update(blog_categories).set({title,titleSeo:removeSpecialCharacters(title)}).where(eq(blog_categories.id,id)).returning();return c.json(category)}});
1
+ import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{saveCategoryTranslations}from"../../../../lib/categories-language.js";import{zodCreateCategorySchema}from"./create.route.js";const zodCategoryResponseSchema=z.object({id:z.number(),createdAt:z.date(),updatedAt:z.date()});export const editCategoryRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"categories",permission:"can_edit"},route:{method:"put",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)}),body:{content:{"application/json":{schema:zodCreateCategorySchema}}}},responses:{200:{content:{"application/json":{schema:zodCategoryResponseSchema}},description:"Category updated successfully"},400:{description:"Bad request - Invalid input data"},404:{description:"Category not found"}}},handler:async c=>{const{id}=c.req.valid("param");const{title,color}=c.req.valid("json");const[editData]=await c.get("db").select({id:blog_categories.id}).from(blog_categories).where(eq(blog_categories.id,id)).limit(1);if(!editData){throw new HTTPException(404)}const[category]=await c.get("db").update(blog_categories).set({color:color?.trim()?color:null}).where(eq(blog_categories.id,id)).returning();await saveCategoryTranslations(c,id,{title});await c.get("events").emit("blog.category.updated",{categoryId:id});return c.json(category)}});
@@ -9,8 +9,18 @@ export declare const postsAdminModule: import("@vitnode/core/api/lib/module").Bu
9
9
  content: {
10
10
  "application/json": {
11
11
  schema: import("zod").ZodObject<{
12
- title: import("zod").ZodString;
13
- content: import("zod").ZodString;
12
+ title: import("zod").ZodArray<import("zod").ZodObject<{
13
+ languageCode: import("zod").ZodString;
14
+ value: import("zod").ZodString;
15
+ }, import("zod/v4/core").$strip>>;
16
+ content: import("zod").ZodArray<import("zod").ZodObject<{
17
+ languageCode: import("zod").ZodString;
18
+ value: import("zod").ZodString;
19
+ }, import("zod/v4/core").$strip>>;
20
+ friendlyUrl: import("zod").ZodArray<import("zod").ZodObject<{
21
+ languageCode: import("zod").ZodString;
22
+ value: import("zod").ZodString;
23
+ }, import("zod/v4/core").$strip>>;
14
24
  categoryId: import("zod").ZodNumber;
15
25
  }, import("zod/v4/core").$strip>;
16
26
  };
@@ -23,9 +33,6 @@ export declare const postsAdminModule: import("@vitnode/core/api/lib/module").Bu
23
33
  "application/json": {
24
34
  schema: import("zod").ZodObject<{
25
35
  id: import("zod").ZodNumber;
26
- title: import("zod").ZodString;
27
- titleSeo: import("zod").ZodString;
28
- content: import("zod").ZodString;
29
36
  categoryId: import("zod").ZodNumber;
30
37
  createdAt: import("zod").ZodDate;
31
38
  updatedAt: import("zod").ZodDate;
@@ -51,8 +58,18 @@ export declare const postsAdminModule: import("@vitnode/core/api/lib/module").Bu
51
58
  content: {
52
59
  "application/json": {
53
60
  schema: import("zod").ZodObject<{
54
- title: import("zod").ZodString;
55
- content: import("zod").ZodString;
61
+ title: import("zod").ZodArray<import("zod").ZodObject<{
62
+ languageCode: import("zod").ZodString;
63
+ value: import("zod").ZodString;
64
+ }, import("zod/v4/core").$strip>>;
65
+ content: import("zod").ZodArray<import("zod").ZodObject<{
66
+ languageCode: import("zod").ZodString;
67
+ value: import("zod").ZodString;
68
+ }, import("zod/v4/core").$strip>>;
69
+ friendlyUrl: import("zod").ZodArray<import("zod").ZodObject<{
70
+ languageCode: import("zod").ZodString;
71
+ value: import("zod").ZodString;
72
+ }, import("zod/v4/core").$strip>>;
56
73
  categoryId: import("zod").ZodNumber;
57
74
  }, import("zod/v4/core").$strip>;
58
75
  };
@@ -65,9 +82,6 @@ export declare const postsAdminModule: import("@vitnode/core/api/lib/module").Bu
65
82
  "application/json": {
66
83
  schema: import("zod").ZodObject<{
67
84
  id: import("zod").ZodNumber;
68
- title: import("zod").ZodString;
69
- titleSeo: import("zod").ZodString;
70
- content: import("zod").ZodString;
71
85
  categoryId: import("zod").ZodNumber;
72
86
  createdAt: import("zod").ZodDate;
73
87
  updatedAt: import("zod").ZodDate;
@@ -1 +1 @@
1
- {"version":3,"file":"posts.admin.module.d.ts","sourceRoot":"","sources":["../../../../../../src/api/modules/admin/posts/posts.admin.module.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sMAI3B,CAAC"}
1
+ {"version":3,"file":"posts.admin.module.d.ts","sourceRoot":"","sources":["../../../../../../src/api/modules/admin/posts/posts.admin.module.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sMAI3B,CAAC"}
@@ -1,7 +1,17 @@
1
1
  import { z } from "@hono/zod-openapi";
2
2
  export declare const zodCreatePostSchema: z.ZodObject<{
3
- title: z.ZodString;
4
- content: z.ZodString;
3
+ title: z.ZodArray<z.ZodObject<{
4
+ languageCode: z.ZodString;
5
+ value: z.ZodString;
6
+ }, z.core.$strip>>;
7
+ content: z.ZodArray<z.ZodObject<{
8
+ languageCode: z.ZodString;
9
+ value: z.ZodString;
10
+ }, z.core.$strip>>;
11
+ friendlyUrl: z.ZodArray<z.ZodObject<{
12
+ languageCode: z.ZodString;
13
+ value: z.ZodString;
14
+ }, z.core.$strip>>;
5
15
  categoryId: z.ZodNumber;
6
16
  }, z.core.$strip>;
7
17
  export declare const createPostRoute: import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
@@ -12,8 +22,18 @@ export declare const createPostRoute: import("@vitnode/core/api/lib/route").Rout
12
22
  content: {
13
23
  "application/json": {
14
24
  schema: z.ZodObject<{
15
- title: z.ZodString;
16
- content: z.ZodString;
25
+ title: z.ZodArray<z.ZodObject<{
26
+ languageCode: z.ZodString;
27
+ value: z.ZodString;
28
+ }, z.core.$strip>>;
29
+ content: z.ZodArray<z.ZodObject<{
30
+ languageCode: z.ZodString;
31
+ value: z.ZodString;
32
+ }, z.core.$strip>>;
33
+ friendlyUrl: z.ZodArray<z.ZodObject<{
34
+ languageCode: z.ZodString;
35
+ value: z.ZodString;
36
+ }, z.core.$strip>>;
17
37
  categoryId: z.ZodNumber;
18
38
  }, z.core.$strip>;
19
39
  };
@@ -26,9 +46,6 @@ export declare const createPostRoute: import("@vitnode/core/api/lib/route").Rout
26
46
  "application/json": {
27
47
  schema: z.ZodObject<{
28
48
  id: z.ZodNumber;
29
- title: z.ZodString;
30
- titleSeo: z.ZodString;
31
- content: z.ZodString;
32
49
  categoryId: z.ZodNumber;
33
50
  createdAt: z.ZodDate;
34
51
  updatedAt: z.ZodDate;
@@ -1 +1 @@
1
- {"version":3,"file":"create.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/posts/routes/create.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAoBtC,eAAO,MAAM,mBAAmB;;;;iBAO9B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6E1B,CAAC"}
1
+ {"version":3,"file":"create.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/posts/routes/create.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAyBtC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;iBAK9B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoG1B,CAAC"}
@@ -1 +1 @@
1
- import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{removeSpecialCharacters}from"@vitnode/core/lib/special-characters";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{blog_posts}from"../../../../../database/posts.js";const zodPostResponseSchema=z.object({id:z.number(),title:z.string(),titleSeo:z.string(),content:z.string(),categoryId:z.number(),createdAt:z.date(),updatedAt:z.date()});export const zodCreatePostSchema=z.object({title:z.string().min(3,"Title must be at least 3 characters long").max(255,"Title must not exceed 255 characters"),content:z.string(),categoryId:z.number()});export const createPostRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"posts",permission:"can_create"},route:{method:"post",path:"/",request:{body:{content:{"application/json":{schema:zodCreatePostSchema}}}},responses:{201:{content:{"application/json":{schema:zodPostResponseSchema}},description:"Post created successfully"},400:{description:"Bad request - Invalid input data"},404:{description:"Category not found"}}},handler:async c=>{const{title,content,categoryId}=c.req.valid("json");const titleSeo=removeSpecialCharacters(title);const[category]=await c.get("db").select({id:blog_categories.id}).from(blog_categories).where(eq(blog_categories.id,categoryId)).limit(1);if(!category){throw new HTTPException(404,{message:"Category not found."})}const[titleSEODuplicate]=await c.get("db").select({titleSeo:blog_posts.titleSeo}).from(blog_posts).where(eq(blog_posts.titleSeo,titleSeo)).limit(1);if(titleSEODuplicate?.titleSeo===titleSeo){throw new HTTPException(400,{message:"Post with this title already exists."})}const[post]=await c.get("db").insert(blog_posts).values({title,titleSeo,content,categoryId}).returning();return c.json(post,201)}});
1
+ import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{core_languages_words}from"@vitnode/core/database/languages";import{multiLangValueSchema}from"@vitnode/core/lib/helpers/multi-lang";import{and,eq,inArray}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{blog_posts}from"../../../../../database/posts.js";import{POST_LANG_TABLE,savePostTranslations,slugifyMultiLang}from"../../../../lib/posts-language.js";import{reindexBlogPost}from"../../../../lib/search.js";const zodPostResponseSchema=z.object({id:z.number(),categoryId:z.number(),createdAt:z.date(),updatedAt:z.date()});export const zodCreatePostSchema=z.object({title:multiLangValueSchema({minLength:3,maxLength:255}).min(1),content:multiLangValueSchema(),friendlyUrl:multiLangValueSchema({minLength:1,maxLength:255}).min(1),categoryId:z.number()});export const createPostRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"posts",permission:"can_create"},route:{method:"post",path:"/",request:{body:{content:{"application/json":{schema:zodCreatePostSchema}}}},responses:{201:{content:{"application/json":{schema:zodPostResponseSchema}},description:"Post created successfully"},400:{description:"Bad request - Invalid input data"},404:{description:"Category not found"}}},handler:async c=>{const{title,content,friendlyUrl,categoryId}=c.req.valid("json");const slugFriendlyUrl=slugifyMultiLang(friendlyUrl);const friendlyUrlValues=[...new Set(slugFriendlyUrl.map(item=>item.value).filter(Boolean))];if(friendlyUrlValues.length===0){throw new HTTPException(400,{message:"Friendly URL is required."})}const[category]=await c.get("db").select({id:blog_categories.id}).from(blog_categories).where(eq(blog_categories.id,categoryId)).limit(1);if(!category){throw new HTTPException(404,{message:"Category not found."})}const[duplicate]=await c.get("db").select({itemId:core_languages_words.itemId}).from(core_languages_words).where(and(eq(core_languages_words.pluginCode,CONFIG_PLUGIN.pluginId),eq(core_languages_words.tableName,POST_LANG_TABLE),eq(core_languages_words.variable,"friendlyUrl"),inArray(core_languages_words.value,friendlyUrlValues))).limit(1);if(duplicate){throw new HTTPException(400,{message:"Post with this title already exists."})}const[post]=await c.get("db").insert(blog_posts).values({categoryId,authorId:c.get("admin")?.user.id??c.get("user")?.id??null}).returning();await savePostTranslations(c,post.id,{title,content,friendlyUrl});await reindexBlogPost(c,post);await c.get("events").emit("blog.post.created",{postId:post.id,categoryId:post.categoryId});return c.json(post,201)}});
@@ -1 +1 @@
1
- {"version":3,"file":"delete.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/posts/routes/delete.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAQtC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;EAmC1B,CAAC"}
1
+ {"version":3,"file":"delete.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/posts/routes/delete.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAQtC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;EA0C1B,CAAC"}
@@ -1 +1 @@
1
- import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_posts}from"../../../../../database/posts.js";export const deletePostRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"posts",permission:"can_delete"},route:{method:"delete",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)})},responses:{204:{description:"Post deleted successfully"},404:{description:"Post not found"}}},handler:async c=>{const{id}=c.req.valid("param");const result=await c.get("db").delete(blog_posts).where(eq(blog_posts.id,id)).returning();if(result.length===0){throw new HTTPException(404)}return c.body(null,204)}});
1
+ import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_posts}from"../../../../../database/posts.js";export const deletePostRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"posts",permission:"can_delete"},route:{method:"delete",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)})},responses:{204:{description:"Post deleted successfully"},404:{description:"Post not found"}}},handler:async c=>{const{id}=c.req.valid("param");const result=await c.get("db").delete(blog_posts).where(eq(blog_posts.id,id)).returning();if(result.length===0){throw new HTTPException(404)}await c.get("search").delete("blog_post",id);await c.get("events").emit("blog.post.deleted",{postId:id,categoryId:result[0].categoryId});return c.body(null,204)}});
@@ -10,8 +10,18 @@ export declare const editPostRoute: import("@vitnode/core/api/lib/route").Route<
10
10
  content: {
11
11
  "application/json": {
12
12
  schema: z.ZodObject<{
13
- title: z.ZodString;
14
- content: z.ZodString;
13
+ title: z.ZodArray<z.ZodObject<{
14
+ languageCode: z.ZodString;
15
+ value: z.ZodString;
16
+ }, z.core.$strip>>;
17
+ content: z.ZodArray<z.ZodObject<{
18
+ languageCode: z.ZodString;
19
+ value: z.ZodString;
20
+ }, z.core.$strip>>;
21
+ friendlyUrl: z.ZodArray<z.ZodObject<{
22
+ languageCode: z.ZodString;
23
+ value: z.ZodString;
24
+ }, z.core.$strip>>;
15
25
  categoryId: z.ZodNumber;
16
26
  }, z.core.$strip>;
17
27
  };
@@ -24,9 +34,6 @@ export declare const editPostRoute: import("@vitnode/core/api/lib/route").Route<
24
34
  "application/json": {
25
35
  schema: z.ZodObject<{
26
36
  id: z.ZodNumber;
27
- title: z.ZodString;
28
- titleSeo: z.ZodString;
29
- content: z.ZodString;
30
37
  categoryId: z.ZodNumber;
31
38
  createdAt: z.ZodDate;
32
39
  updatedAt: z.ZodDate;
@@ -1 +1 @@
1
- {"version":3,"file":"edit.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/posts/routes/edit.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAsBtC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+FxB,CAAC"}
1
+ {"version":3,"file":"edit.route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/modules/admin/posts/routes/edit.route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAyBtC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHxB,CAAC"}
@@ -1 +1 @@
1
- import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{removeSpecialCharacters}from"@vitnode/core/lib/special-characters";import{eq}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{blog_posts}from"../../../../../database/posts.js";import{zodCreatePostSchema}from"./create.route.js";const zodPostResponseSchema=z.object({id:z.number(),title:z.string(),titleSeo:z.string(),content:z.string(),categoryId:z.number(),createdAt:z.date(),updatedAt:z.date()});export const editPostRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"posts",permission:"can_edit"},route:{method:"put",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)}),body:{content:{"application/json":{schema:zodCreatePostSchema}}}},responses:{200:{content:{"application/json":{schema:zodPostResponseSchema}},description:"Post updated successfully"},400:{description:"Bad request - Invalid input data"},404:{description:"Post or category not found"}}},handler:async c=>{const{id}=c.req.valid("param");const{title,content,categoryId}=c.req.valid("json");const titleSeo=removeSpecialCharacters(title);const[existingPost]=await c.get("db").select({titleSeo:blog_posts.titleSeo}).from(blog_posts).where(eq(blog_posts.id,id)).limit(1);if(!existingPost){throw new HTTPException(404,{message:"Post not found."})}const[category]=await c.get("db").select({id:blog_categories.id}).from(blog_categories).where(eq(blog_categories.id,categoryId)).limit(1);if(!category){throw new HTTPException(404,{message:"Category not found."})}const[titleSEODuplicate]=await c.get("db").select({titleSeo:blog_posts.titleSeo}).from(blog_posts).where(eq(blog_posts.titleSeo,titleSeo)).limit(1);if(titleSEODuplicate?.titleSeo===titleSeo&&titleSEODuplicate.titleSeo!==existingPost.titleSeo){throw new HTTPException(400,{message:"Post with this title already exists."})}const[post]=await c.get("db").update(blog_posts).set({title,titleSeo,content,categoryId}).where(eq(blog_posts.id,id)).returning();return c.json(post)}});
1
+ import{z}from"@hono/zod-openapi";import{buildRoute}from"@vitnode/core/api/lib/route";import{core_languages_words}from"@vitnode/core/database/languages";import{and,eq,inArray,ne}from"drizzle-orm";import{HTTPException}from"hono/http-exception";import{CONFIG_PLUGIN}from"../../../../../const.js";import{blog_categories}from"../../../../../database/categories.js";import{blog_posts}from"../../../../../database/posts.js";import{POST_LANG_TABLE,savePostTranslations,slugifyMultiLang}from"../../../../lib/posts-language.js";import{reindexBlogPost}from"../../../../lib/search.js";import{zodCreatePostSchema}from"./create.route.js";const zodPostResponseSchema=z.object({id:z.number(),categoryId:z.number(),createdAt:z.date(),updatedAt:z.date()});export const editPostRoute=buildRoute({pluginId:CONFIG_PLUGIN.pluginId,adminStaffPermission:{module:"posts",permission:"can_edit"},route:{method:"put",path:"/{id}",request:{params:z.object({id:z.string().transform(Number)}),body:{content:{"application/json":{schema:zodCreatePostSchema}}}},responses:{200:{content:{"application/json":{schema:zodPostResponseSchema}},description:"Post updated successfully"},400:{description:"Bad request - Invalid input data"},404:{description:"Post or category not found"}}},handler:async c=>{const{id}=c.req.valid("param");const{title,content,friendlyUrl,categoryId}=c.req.valid("json");const slugFriendlyUrl=slugifyMultiLang(friendlyUrl);const friendlyUrlValues=[...new Set(slugFriendlyUrl.map(item=>item.value).filter(Boolean))];if(friendlyUrlValues.length===0){throw new HTTPException(400,{message:"Friendly URL is required."})}const[existingPost]=await c.get("db").select({id:blog_posts.id}).from(blog_posts).where(eq(blog_posts.id,id)).limit(1);if(!existingPost){throw new HTTPException(404,{message:"Post not found."})}const[category]=await c.get("db").select({id:blog_categories.id}).from(blog_categories).where(eq(blog_categories.id,categoryId)).limit(1);if(!category){throw new HTTPException(404,{message:"Category not found."})}const[duplicate]=await c.get("db").select({itemId:core_languages_words.itemId}).from(core_languages_words).where(and(eq(core_languages_words.pluginCode,CONFIG_PLUGIN.pluginId),eq(core_languages_words.tableName,POST_LANG_TABLE),eq(core_languages_words.variable,"friendlyUrl"),inArray(core_languages_words.value,friendlyUrlValues),ne(core_languages_words.itemId,id))).limit(1);if(duplicate){throw new HTTPException(400,{message:"Post with this title already exists."})}const[post]=await c.get("db").update(blog_posts).set({categoryId}).where(eq(blog_posts.id,id)).returning();await savePostTranslations(c,id,{title,content,friendlyUrl});await reindexBlogPost(c,post);await c.get("events").emit("blog.post.updated",{postId:post.id,categoryId:post.categoryId});return c.json(post)}});