@vitnode/blog 1.2.0-canary.78 → 2.0.0-canary.10

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 (167) hide show
  1. package/dist/src/admin/content.d.ts +5 -0
  2. package/dist/src/admin/content.d.ts.map +1 -0
  3. package/dist/src/admin/content.js +1 -0
  4. package/dist/src/admin/nav.d.ts +41 -0
  5. package/dist/src/admin/nav.d.ts.map +1 -0
  6. package/dist/src/admin/nav.js +1 -0
  7. package/dist/src/api/lib/events.d.ts +11 -3
  8. package/dist/src/api/lib/events.d.ts.map +1 -1
  9. package/dist/src/api/lib/events.js +1 -1
  10. package/dist/src/api/modules/admin/admin.module.d.ts +1 -218
  11. package/dist/src/api/modules/admin/admin.module.d.ts.map +1 -1
  12. package/dist/src/api/modules/admin/admin.module.js +1 -1
  13. package/dist/src/config.api.d.ts.map +1 -1
  14. package/dist/src/config.api.js +1 -1
  15. package/dist/src/config.d.ts.map +1 -1
  16. package/dist/src/config.js +1 -1
  17. package/dist/src/content/category.d.ts +5 -0
  18. package/dist/src/content/category.d.ts.map +1 -0
  19. package/dist/src/content/category.js +1 -0
  20. package/dist/src/content/post.d.ts +10 -0
  21. package/dist/src/content/post.d.ts.map +1 -0
  22. package/dist/src/content/post.js +1 -0
  23. package/dist/src/database/categories.d.ts +10 -77
  24. package/dist/src/database/categories.d.ts.map +1 -1
  25. package/dist/src/database/categories.js +1 -1
  26. package/dist/src/database/posts.d.ts +22 -92
  27. package/dist/src/database/posts.d.ts.map +1 -1
  28. package/dist/src/database/posts.js +1 -1
  29. package/dist/src/globals.css +1 -0
  30. package/dist/src/locales/en.json +50 -73
  31. package/dist/src/locales/index.d.ts.map +1 -1
  32. package/dist/src/locales/index.js +1 -1
  33. package/dist/src/locales/pl.json +69 -0
  34. package/dist/src/views/admin/article/editor-field.d.ts +4 -0
  35. package/dist/src/views/admin/article/editor-field.d.ts.map +1 -0
  36. package/dist/src/views/admin/article/editor-field.js +1 -0
  37. package/dist/src/views/admin/article/form-layout.d.ts +3 -0
  38. package/dist/src/views/admin/article/form-layout.d.ts.map +1 -0
  39. package/dist/src/views/admin/article/form-layout.js +1 -0
  40. package/dist/src/views/admin/category/color-cell.d.ts +4 -0
  41. package/dist/src/views/admin/category/color-cell.d.ts.map +1 -0
  42. package/dist/src/views/admin/category/color-cell.js +1 -0
  43. package/dist/src/views/admin/category/color-field.d.ts +3 -0
  44. package/dist/src/views/admin/category/color-field.d.ts.map +1 -0
  45. package/dist/src/views/admin/category/color-field.js +1 -0
  46. package/dist/vitest.config.d.ts +3 -0
  47. package/dist/vitest.config.d.ts.map +1 -0
  48. package/package.json +32 -25
  49. package/src/locales/en.json +50 -73
  50. package/src/locales/index.ts +1 -0
  51. package/src/locales/pl.json +69 -0
  52. package/tsconfig.build.json +6 -1
  53. package/dist/src/api/lib/categories-language.d.ts +0 -10
  54. package/dist/src/api/lib/categories-language.d.ts.map +0 -1
  55. package/dist/src/api/lib/categories-language.js +0 -1
  56. package/dist/src/api/lib/posts-language.d.ts +0 -17
  57. package/dist/src/api/lib/posts-language.d.ts.map +0 -1
  58. package/dist/src/api/lib/posts-language.js +0 -1
  59. package/dist/src/api/lib/search.d.ts +0 -13
  60. package/dist/src/api/lib/search.d.ts.map +0 -1
  61. package/dist/src/api/lib/search.js +0 -1
  62. package/dist/src/api/modules/admin/categories/categories.admin.module.d.ts +0 -100
  63. package/dist/src/api/modules/admin/categories/categories.admin.module.d.ts.map +0 -1
  64. package/dist/src/api/modules/admin/categories/categories.admin.module.js +0 -1
  65. package/dist/src/api/modules/admin/categories/routes/create.route.d.ts +0 -47
  66. package/dist/src/api/modules/admin/categories/routes/create.route.d.ts.map +0 -1
  67. package/dist/src/api/modules/admin/categories/routes/create.route.js +0 -1
  68. package/dist/src/api/modules/admin/categories/routes/delete.route.d.ts +0 -21
  69. package/dist/src/api/modules/admin/categories/routes/delete.route.d.ts.map +0 -1
  70. package/dist/src/api/modules/admin/categories/routes/delete.route.js +0 -1
  71. package/dist/src/api/modules/admin/categories/routes/edit.route.d.ts +0 -46
  72. package/dist/src/api/modules/admin/categories/routes/edit.route.d.ts.map +0 -1
  73. package/dist/src/api/modules/admin/categories/routes/edit.route.js +0 -1
  74. package/dist/src/api/modules/admin/posts/posts.admin.module.d.ts +0 -121
  75. package/dist/src/api/modules/admin/posts/posts.admin.module.d.ts.map +0 -1
  76. package/dist/src/api/modules/admin/posts/posts.admin.module.js +0 -1
  77. package/dist/src/api/modules/admin/posts/routes/create.route.d.ts +0 -67
  78. package/dist/src/api/modules/admin/posts/routes/create.route.d.ts.map +0 -1
  79. package/dist/src/api/modules/admin/posts/routes/create.route.js +0 -1
  80. package/dist/src/api/modules/admin/posts/routes/delete.route.d.ts +0 -21
  81. package/dist/src/api/modules/admin/posts/routes/delete.route.d.ts.map +0 -1
  82. package/dist/src/api/modules/admin/posts/routes/delete.route.js +0 -1
  83. package/dist/src/api/modules/admin/posts/routes/edit.route.d.ts +0 -55
  84. package/dist/src/api/modules/admin/posts/routes/edit.route.d.ts.map +0 -1
  85. package/dist/src/api/modules/admin/posts/routes/edit.route.js +0 -1
  86. package/dist/src/api/modules/categories/categories.module.d.ts +0 -75
  87. package/dist/src/api/modules/categories/categories.module.d.ts.map +0 -1
  88. package/dist/src/api/modules/categories/categories.module.js +0 -1
  89. package/dist/src/api/modules/categories/routes/get.route.d.ts +0 -62
  90. package/dist/src/api/modules/categories/routes/get.route.d.ts.map +0 -1
  91. package/dist/src/api/modules/categories/routes/get.route.js +0 -1
  92. package/dist/src/api/modules/categories/test.route.d.ts +0 -27
  93. package/dist/src/api/modules/categories/test.route.d.ts.map +0 -1
  94. package/dist/src/api/modules/categories/test.route.js +0 -1
  95. package/dist/src/api/modules/posts/posts.module.d.ts +0 -73
  96. package/dist/src/api/modules/posts/posts.module.d.ts.map +0 -1
  97. package/dist/src/api/modules/posts/posts.module.js +0 -1
  98. package/dist/src/api/modules/posts/routes/get.route.d.ts +0 -105
  99. package/dist/src/api/modules/posts/routes/get.route.d.ts.map +0 -1
  100. package/dist/src/api/modules/posts/routes/get.route.js +0 -1
  101. package/dist/src/database/index.d.ts +0 -4
  102. package/dist/src/database/index.d.ts.map +0 -1
  103. package/dist/src/database/index.js +0 -1
  104. package/dist/src/database/relations.d.ts +0 -7
  105. package/dist/src/database/relations.d.ts.map +0 -1
  106. package/dist/src/database/relations.js +0 -1
  107. package/dist/src/routes/admin/blog/categories/page.d.ts +0 -9
  108. package/dist/src/routes/admin/blog/categories/page.d.ts.map +0 -1
  109. package/dist/src/routes/admin/blog/categories/page.js +0 -1
  110. package/dist/src/routes/admin/blog/posts/page.d.ts +0 -9
  111. package/dist/src/routes/admin/blog/posts/page.d.ts.map +0 -1
  112. package/dist/src/routes/admin/blog/posts/page.js +0 -1
  113. package/dist/src/routes/breadcrumb/admin/blog/categories/page.d.ts +0 -2
  114. package/dist/src/routes/breadcrumb/admin/blog/categories/page.d.ts.map +0 -1
  115. package/dist/src/routes/breadcrumb/admin/blog/categories/page.js +0 -1
  116. package/dist/src/routes/breadcrumb/admin/blog/posts/page.d.ts +0 -2
  117. package/dist/src/routes/breadcrumb/admin/blog/posts/page.d.ts.map +0 -1
  118. package/dist/src/routes/breadcrumb/admin/blog/posts/page.js +0 -1
  119. package/dist/src/views/admin/categories/actions/actions.d.ts +0 -3
  120. package/dist/src/views/admin/categories/actions/actions.d.ts.map +0 -1
  121. package/dist/src/views/admin/categories/actions/actions.js +0 -1
  122. package/dist/src/views/admin/categories/actions/create-edit/create-edit.d.ts +0 -8
  123. package/dist/src/views/admin/categories/actions/create-edit/create-edit.d.ts.map +0 -1
  124. package/dist/src/views/admin/categories/actions/create-edit/create-edit.js +0 -1
  125. package/dist/src/views/admin/categories/actions/create-edit/mutation-api.server.d.ts +0 -11
  126. package/dist/src/views/admin/categories/actions/create-edit/mutation-api.server.d.ts.map +0 -1
  127. package/dist/src/views/admin/categories/actions/create-edit/mutation-api.server.js +0 -1
  128. package/dist/src/views/admin/categories/table/actions/delete/delete-action.d.ts +0 -5
  129. package/dist/src/views/admin/categories/table/actions/delete/delete-action.d.ts.map +0 -1
  130. package/dist/src/views/admin/categories/table/actions/delete/delete-action.js +0 -1
  131. package/dist/src/views/admin/categories/table/actions/delete/mutation-api.server.d.ts +0 -4
  132. package/dist/src/views/admin/categories/table/actions/delete/mutation-api.server.d.ts.map +0 -1
  133. package/dist/src/views/admin/categories/table/actions/delete/mutation-api.server.js +0 -1
  134. package/dist/src/views/admin/categories/table/actions/edit-action.d.ts +0 -9
  135. package/dist/src/views/admin/categories/table/actions/edit-action.d.ts.map +0 -1
  136. package/dist/src/views/admin/categories/table/actions/edit-action.js +0 -1
  137. package/dist/src/views/admin/categories/table/categories-admin-view.d.ts +0 -4
  138. package/dist/src/views/admin/categories/table/categories-admin-view.d.ts.map +0 -1
  139. package/dist/src/views/admin/categories/table/categories-admin-view.js +0 -1
  140. package/dist/src/views/admin/posts/actions/actions.d.ts +0 -3
  141. package/dist/src/views/admin/posts/actions/actions.d.ts.map +0 -1
  142. package/dist/src/views/admin/posts/actions/actions.js +0 -1
  143. package/dist/src/views/admin/posts/actions/create-edit/create-edit.d.ts +0 -9
  144. package/dist/src/views/admin/posts/actions/create-edit/create-edit.d.ts.map +0 -1
  145. package/dist/src/views/admin/posts/actions/create-edit/create-edit.js +0 -1
  146. package/dist/src/views/admin/posts/actions/create-edit/multi-lang-fields.d.ts +0 -10
  147. package/dist/src/views/admin/posts/actions/create-edit/multi-lang-fields.d.ts.map +0 -1
  148. package/dist/src/views/admin/posts/actions/create-edit/multi-lang-fields.js +0 -1
  149. package/dist/src/views/admin/posts/actions/create-edit/mutation-api.server.d.ts +0 -11
  150. package/dist/src/views/admin/posts/actions/create-edit/mutation-api.server.d.ts.map +0 -1
  151. package/dist/src/views/admin/posts/actions/create-edit/mutation-api.server.js +0 -1
  152. package/dist/src/views/admin/posts/table/actions/delete/delete-action.d.ts +0 -5
  153. package/dist/src/views/admin/posts/table/actions/delete/delete-action.d.ts.map +0 -1
  154. package/dist/src/views/admin/posts/table/actions/delete/delete-action.js +0 -1
  155. package/dist/src/views/admin/posts/table/actions/delete/mutation-api.server.d.ts +0 -4
  156. package/dist/src/views/admin/posts/table/actions/delete/mutation-api.server.d.ts.map +0 -1
  157. package/dist/src/views/admin/posts/table/actions/delete/mutation-api.server.js +0 -1
  158. package/dist/src/views/admin/posts/table/actions/edit-action.d.ts +0 -9
  159. package/dist/src/views/admin/posts/table/actions/edit-action.d.ts.map +0 -1
  160. package/dist/src/views/admin/posts/table/actions/edit-action.js +0 -1
  161. package/dist/src/views/admin/posts/table/posts-admin-view.d.ts +0 -4
  162. package/dist/src/views/admin/posts/table/posts-admin-view.d.ts.map +0 -1
  163. package/dist/src/views/admin/posts/table/posts-admin-view.js +0 -1
  164. package/src/routes/admin/blog/categories/page.tsx +0 -64
  165. package/src/routes/admin/blog/posts/page.tsx +0 -64
  166. package/src/routes/breadcrumb/admin/blog/categories/page.tsx +0 -5
  167. package/src/routes/breadcrumb/admin/blog/posts/page.tsx +0 -5
@@ -1,89 +1,66 @@
1
1
  {
2
2
  "@vitnode/blog": {
3
3
  "title": "Blog",
4
- "admin": {
5
- "nav": {
6
- "posts": "Posts",
7
- "categories": "Categories"
8
- },
9
- "categories": {
10
- "desc": "Manage categories for blog posts.",
11
- "table": {
4
+ "content": {
5
+ "post": {
6
+ "label": "{count, plural, one {Article} other {Articles}}",
7
+ "title": "Articles",
8
+ "desc": "Write and manage your blog articles.",
9
+ "fields": {
12
10
  "title": "Title",
11
+ "friendlyUrl": "Friendly URL",
12
+ "content": "Content",
13
+ "categoryId": "Categories",
14
+ "authorId": "Authors",
15
+ "coverImage": "Cover image",
16
+ "coverImageAlt": "Cover image alt text",
17
+ "status": "Status",
18
+ "publishedAt": "Published",
19
+ "updatedAt": "Updated"
20
+ }
21
+ },
22
+ "category": {
23
+ "label": "{count, plural, one {Category} other {Categories}}",
24
+ "title": "Categories",
25
+ "desc": "Group articles together.",
26
+ "fields": {
27
+ "name": "Name",
13
28
  "color": "Color",
14
- "updated_at": "Updated At"
15
- },
16
- "delete": {
17
- "title": "Delete Category",
18
- "desc": "Are you sure you want to delete <title></title> category? This action cannot be undone.",
19
- "confirm": "Yes, delete this category",
20
- "success": "Category has been deleted successfully."
29
+ "updatedAt": "Updated"
30
+ }
31
+ }
32
+ },
33
+ "admin": {
34
+ "article": {
35
+ "content": {
36
+ "label": "Content"
21
37
  },
22
- "create": {
23
- "title": "Create Category",
24
- "desc": "A new category for your blog posts.",
25
- "form": {
26
- "title": {
27
- "label": "Title",
28
- "already_exists": "This category title already exists."
29
- },
30
- "color": "Color"
38
+ "form": {
39
+ "publish": "Publish",
40
+ "cover": {
41
+ "title": "Cover image"
31
42
  },
32
- "submit": "Create",
33
- "success": "Category has been created successfully."
34
- },
35
- "edit": {
36
- "title": "Edit Category",
37
- "submit": "Save Changes",
38
- "success": "Category has been updated successfully."
43
+ "settings": {
44
+ "title": "Article settings"
45
+ }
39
46
  }
40
47
  },
41
- "posts": {
42
- "desc": "Write and manage your blog posts.",
43
- "table": {
44
- "title": "Title",
45
- "category": "Category",
46
- "author": "Author",
47
- "updated_at": "Updated At"
48
- },
49
- "create": {
50
- "title": "Create Post",
51
- "desc": "Write a new article for your blog.",
52
- "form": {
53
- "title": {
54
- "label": "Title",
55
- "already_exists": "This post title already exists."
56
- },
57
- "friendly_url": {
58
- "label": "Friendly URL",
59
- "desc": "Used in the post address. Auto-filled from the title.",
60
- "already_exists": "This friendly URL already exists."
61
- },
62
- "content": "Content",
63
- "category": "Category"
64
- },
65
- "submit": "Create Post",
66
- "success": "Post has been created successfully."
67
- },
68
- "edit": {
69
- "title": "Edit Post",
70
- "submit": "Save Changes",
71
- "success": "Post has been updated successfully."
72
- },
73
- "delete": {
74
- "title": "Delete Post",
75
- "desc": "Are you sure you want to delete <title></title> post? This action cannot be undone.",
76
- "confirm": "Yes, delete this post",
77
- "success": "Post has been deleted successfully."
48
+ "category": {
49
+ "color": {
50
+ "label": "Color",
51
+ "desc": "Shown next to the category in lists.",
52
+ "none": "No color"
78
53
  }
79
54
  }
80
55
  }
81
56
  },
82
- "@vitnode/blog:posts": "Posts",
83
- "@vitnode/blog:posts:can_view": "View posts list",
84
- "@vitnode/blog:posts:can_create": "Create posts",
85
- "@vitnode/blog:posts:can_edit": "Edit posts",
86
- "@vitnode/blog:posts:can_delete": "Delete posts",
57
+ "@vitnode/blog:posts": "Articles",
58
+ "@vitnode/blog:posts:can_view": "View articles list",
59
+ "@vitnode/blog:posts:can_create": "Create articles",
60
+ "@vitnode/blog:posts:can_edit": "Edit articles",
61
+ "@vitnode/blog:posts:can_delete": "Delete articles",
62
+ "@vitnode/blog:posts:can_publish": "Publish and unpublish articles",
63
+ "@vitnode/blog:posts:can_restore": "Restore an earlier version of an article",
87
64
  "@vitnode/blog:categories": "Categories",
88
65
  "@vitnode/blog:categories:can_view": "View categories list",
89
66
  "@vitnode/blog:categories:can_create": "Create categories",
@@ -6,6 +6,7 @@ import type { LocaleMessagesMap } from "@vitnode/core/lib/i18n/types";
6
6
  */
7
7
  const messages: LocaleMessagesMap = {
8
8
  en: async () => await import("./en.json", { with: { type: "json" } }),
9
+ pl: async () => await import("./pl.json", { with: { type: "json" } }),
9
10
  };
10
11
 
11
12
  export default messages;
@@ -0,0 +1,69 @@
1
+ {
2
+ "@vitnode/blog": {
3
+ "title": "Blog",
4
+ "content": {
5
+ "post": {
6
+ "label": "{count, plural, one {Artykuł} few {Artykuły} many {Artykułów} other {Artykułu}}",
7
+ "title": "Artykuły",
8
+ "desc": "Pisz artykuły na blogu i zarządzaj nimi.",
9
+ "fields": {
10
+ "title": "Tytuł",
11
+ "friendlyUrl": "Przyjazny adres URL",
12
+ "content": "Treść",
13
+ "categoryId": "Kategoria",
14
+ "authorId": "Autor",
15
+ "coverImage": "Obraz wyróżniający",
16
+ "coverImageAlt": "Tekst alternatywny obrazu",
17
+ "status": "Status",
18
+ "publishedAt": "Opublikowano",
19
+ "updatedAt": "Zaktualizowano"
20
+ }
21
+ },
22
+ "category": {
23
+ "label": "{count, plural, one {Kategoria} few {Kategorie} many {Kategorii} other {Kategorii}}",
24
+ "title": "Kategorie",
25
+ "desc": "Grupuj artykuły razem.",
26
+ "fields": {
27
+ "name": "Nazwa",
28
+ "color": "Kolor",
29
+ "updatedAt": "Zaktualizowano"
30
+ }
31
+ }
32
+ },
33
+ "admin": {
34
+ "article": {
35
+ "content": {
36
+ "label": "Treść"
37
+ },
38
+ "form": {
39
+ "publish": "Publikacja",
40
+ "cover": {
41
+ "title": "Obraz wyróżniający"
42
+ },
43
+ "settings": {
44
+ "title": "Ustawienia artykułu"
45
+ }
46
+ }
47
+ },
48
+ "category": {
49
+ "color": {
50
+ "label": "Kolor",
51
+ "desc": "Wyświetlany obok kategorii na listach.",
52
+ "none": "Brak koloru"
53
+ }
54
+ }
55
+ }
56
+ },
57
+ "@vitnode/blog:posts": "Artykuły",
58
+ "@vitnode/blog:posts:can_view": "Wyświetlanie listy artykułów",
59
+ "@vitnode/blog:posts:can_create": "Tworzenie artykułów",
60
+ "@vitnode/blog:posts:can_edit": "Edytowanie artykułów",
61
+ "@vitnode/blog:posts:can_delete": "Usuwanie artykułów",
62
+ "@vitnode/blog:posts:can_publish": "Publikowanie i cofanie publikacji artykułów",
63
+ "@vitnode/blog:posts:can_restore": "Przywracanie wcześniejszej wersji artykułu",
64
+ "@vitnode/blog:categories": "Kategorie",
65
+ "@vitnode/blog:categories:can_view": "Wyświetlanie listy kategorii",
66
+ "@vitnode/blog:categories:can_create": "Tworzenie kategorii",
67
+ "@vitnode/blog:categories:can_edit": "Edytowanie kategorii",
68
+ "@vitnode/blog:categories:can_delete": "Usuwanie kategorii"
69
+ }
@@ -1,5 +1,10 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/tsconfig",
3
3
  "extends": "./tsconfig.json",
4
- "exclude": ["node_modules", "**/*.test.ts", "**/*.test.tsx"]
4
+ "exclude": [
5
+ "node_modules",
6
+ "**/*.test.ts",
7
+ "**/*.test.tsx",
8
+ "**/*.test-d.ts"
9
+ ]
5
10
  }
@@ -1,10 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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};
@@ -1,17 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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};
@@ -1,13 +0,0 @@
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
@@ -1 +0,0 @@
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;AAcpC,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;AAmDD,eAAO,MAAM,eAAe,GAC1B,GAAG,OAAO,EACV,MAAM,iBAAiB,KACtB,OAAO,CAAC,IAAI,CAoBd,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,aA4CnC,CAAC"}
@@ -1 +0,0 @@
1
- import{asc,count}from"drizzle-orm";import{blog_posts}from"../../database/posts.js";import{getDefaultLanguageCode,loadPostTranslations,resolveLangValue}from"./posts-language.js";const getEnabledLanguageCodes=c=>c.get("core").i18n.locales.filter(locale=>locale.enabled!==false).map(locale=>locale.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=getEnabledLanguageCodes(c);const[defaultLanguageCode,translations]=await Promise.all([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=getEnabledLanguageCodes(c);const[defaultLanguageCode,translations]=await Promise.all([getDefaultLanguageCode(c),loadPostTranslations(c,rows.map(row=>row.id))]);return rows.flatMap(post=>buildDocumentsForPost(post,languageCodes,translations.get(post.id),defaultLanguageCode))}};
@@ -1,100 +0,0 @@
1
- export declare const categoriesAdminModule: import("@vitnode/core/api/lib/module").BuildModuleReturn<"@vitnode/blog", "categories", [import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
2
- method: "post";
3
- path: "/";
4
- request: {
5
- body: {
6
- content: {
7
- "application/json": {
8
- schema: import("zod").ZodObject<{
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>>;
14
- }, import("zod/v4/core").$strip>;
15
- };
16
- };
17
- };
18
- };
19
- responses: {
20
- 201: {
21
- content: {
22
- "application/json": {
23
- schema: import("zod").ZodObject<{
24
- id: import("zod").ZodNumber;
25
- createdAt: import("zod").ZodDate;
26
- updatedAt: import("zod").ZodDate;
27
- }, import("zod/v4/core").$strip>;
28
- };
29
- };
30
- description: string;
31
- };
32
- 400: {
33
- description: string;
34
- };
35
- };
36
- } & {
37
- path: string;
38
- }>, import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
39
- method: "put";
40
- path: "/{id}";
41
- request: {
42
- params: import("zod").ZodObject<{
43
- id: import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<number, string>>;
44
- }, import("zod/v4/core").$strip>;
45
- body: {
46
- content: {
47
- "application/json": {
48
- schema: import("zod").ZodObject<{
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>>;
54
- }, import("zod/v4/core").$strip>;
55
- };
56
- };
57
- };
58
- };
59
- responses: {
60
- 200: {
61
- content: {
62
- "application/json": {
63
- schema: import("zod").ZodObject<{
64
- id: import("zod").ZodNumber;
65
- createdAt: import("zod").ZodDate;
66
- updatedAt: import("zod").ZodDate;
67
- }, import("zod/v4/core").$strip>;
68
- };
69
- };
70
- description: string;
71
- };
72
- 400: {
73
- description: string;
74
- };
75
- 404: {
76
- description: string;
77
- };
78
- };
79
- } & {
80
- path: string;
81
- }>, import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
82
- method: "delete";
83
- path: "/{id}";
84
- request: {
85
- params: import("zod").ZodObject<{
86
- id: import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<number, string>>;
87
- }, import("zod/v4/core").$strip>;
88
- };
89
- responses: {
90
- 204: {
91
- description: string;
92
- };
93
- 404: {
94
- description: string;
95
- };
96
- };
97
- } & {
98
- path: string;
99
- }>], import("@vitnode/core/api/lib/module").BaseBuildModuleReturn<"@vitnode/blog", string, import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", import("@hono/zod-openapi").RouteConfig>[]>[]>;
100
- //# sourceMappingURL=categories.admin.module.d.ts.map
@@ -1 +0,0 @@
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 +0,0 @@
1
- import{buildModule}from"@vitnode/core/api/lib/module";import{CONFIG_PLUGIN}from"../../../../const.js";import{createCategoryRoute}from"./routes/create.route.js";import{deleteCategoryRoute}from"./routes/delete.route.js";import{editCategoryRoute}from"./routes/edit.route.js";export const categoriesAdminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"categories",routes:[createCategoryRoute,editCategoryRoute,deleteCategoryRoute]});
@@ -1,47 +0,0 @@
1
- import { z } from "@hono/zod-openapi";
2
- export declare const zodCreateCategorySchema: z.ZodObject<{
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>>;
8
- }, z.core.$strip>;
9
- export declare const createCategoryRoute: import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
10
- method: "post";
11
- path: "/";
12
- request: {
13
- body: {
14
- content: {
15
- "application/json": {
16
- schema: z.ZodObject<{
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>>;
22
- }, z.core.$strip>;
23
- };
24
- };
25
- };
26
- };
27
- responses: {
28
- 201: {
29
- content: {
30
- "application/json": {
31
- schema: z.ZodObject<{
32
- id: z.ZodNumber;
33
- createdAt: z.ZodDate;
34
- updatedAt: z.ZodDate;
35
- }, z.core.$strip>;
36
- };
37
- };
38
- description: string;
39
- };
40
- 400: {
41
- description: string;
42
- };
43
- };
44
- } & {
45
- path: string;
46
- }>;
47
- //# sourceMappingURL=create.route.d.ts.map
@@ -1 +0,0 @@
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 +0,0 @@
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,21 +0,0 @@
1
- import { z } from "@hono/zod-openapi";
2
- export declare const deleteCategoryRoute: import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
3
- method: "delete";
4
- path: "/{id}";
5
- request: {
6
- params: z.ZodObject<{
7
- id: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
8
- }, z.core.$strip>;
9
- };
10
- responses: {
11
- 204: {
12
- description: string;
13
- };
14
- 404: {
15
- description: string;
16
- };
17
- };
18
- } & {
19
- path: string;
20
- }>;
21
- //# sourceMappingURL=delete.route.d.ts.map
@@ -1 +0,0 @@
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 +0,0 @@
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)}});
@@ -1,46 +0,0 @@
1
- import { z } from "@hono/zod-openapi";
2
- export declare const editCategoryRoute: import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", {
3
- method: "put";
4
- path: "/{id}";
5
- request: {
6
- params: z.ZodObject<{
7
- id: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
8
- }, z.core.$strip>;
9
- body: {
10
- content: {
11
- "application/json": {
12
- schema: z.ZodObject<{
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>>;
18
- }, z.core.$strip>;
19
- };
20
- };
21
- };
22
- };
23
- responses: {
24
- 200: {
25
- content: {
26
- "application/json": {
27
- schema: z.ZodObject<{
28
- id: z.ZodNumber;
29
- createdAt: z.ZodDate;
30
- updatedAt: z.ZodDate;
31
- }, z.core.$strip>;
32
- };
33
- };
34
- description: string;
35
- };
36
- 400: {
37
- description: string;
38
- };
39
- 404: {
40
- description: string;
41
- };
42
- };
43
- } & {
44
- path: string;
45
- }>;
46
- //# sourceMappingURL=edit.route.d.ts.map
@@ -1 +0,0 @@
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 +0,0 @@
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)}});