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

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 (42) hide show
  1. package/dist/src/api/modules/admin/categories/routes/create.route.d.ts.map +1 -1
  2. package/dist/src/api/modules/admin/categories/routes/create.route.js +1 -1
  3. package/dist/src/api/modules/admin/categories/routes/delete.route.d.ts.map +1 -1
  4. package/dist/src/api/modules/admin/categories/routes/delete.route.js +1 -1
  5. package/dist/src/api/modules/admin/categories/routes/edit.route.d.ts.map +1 -1
  6. package/dist/src/api/modules/admin/categories/routes/edit.route.js +1 -1
  7. package/dist/src/api/modules/admin/posts/routes/create.route.d.ts.map +1 -1
  8. package/dist/src/api/modules/admin/posts/routes/create.route.js +1 -1
  9. package/dist/src/api/modules/admin/posts/routes/delete.route.d.ts.map +1 -1
  10. package/dist/src/api/modules/admin/posts/routes/delete.route.js +1 -1
  11. package/dist/src/api/modules/admin/posts/routes/edit.route.d.ts.map +1 -1
  12. package/dist/src/api/modules/admin/posts/routes/edit.route.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/emails/test-template.d.ts.map +1 -1
  18. package/dist/src/emails/test-template.js +1 -1
  19. package/dist/src/routes/admin/blog/categories/page.d.ts.map +1 -1
  20. package/dist/src/routes/admin/blog/categories/page.js +1 -1
  21. package/dist/src/routes/admin/blog/posts/page.d.ts.map +1 -1
  22. package/dist/src/routes/admin/blog/posts/page.js +1 -1
  23. package/dist/src/views/admin/categories/actions/actions.d.ts.map +1 -1
  24. package/dist/src/views/admin/categories/actions/actions.js +1 -1
  25. package/dist/src/views/admin/categories/table/actions/delete/delete-action.d.ts +1 -1
  26. package/dist/src/views/admin/categories/table/actions/delete/delete-action.d.ts.map +1 -1
  27. package/dist/src/views/admin/categories/table/actions/delete/delete-action.js +1 -1
  28. package/dist/src/views/admin/categories/table/actions/edit-action.d.ts +1 -1
  29. package/dist/src/views/admin/categories/table/actions/edit-action.d.ts.map +1 -1
  30. package/dist/src/views/admin/categories/table/actions/edit-action.js +1 -1
  31. package/dist/src/views/admin/posts/actions/actions.d.ts.map +1 -1
  32. package/dist/src/views/admin/posts/actions/actions.js +1 -1
  33. package/dist/src/views/admin/posts/table/actions/delete/delete-action.d.ts +1 -1
  34. package/dist/src/views/admin/posts/table/actions/delete/delete-action.d.ts.map +1 -1
  35. package/dist/src/views/admin/posts/table/actions/delete/delete-action.js +1 -1
  36. package/dist/src/views/admin/posts/table/actions/edit-action.d.ts +1 -1
  37. package/dist/src/views/admin/posts/table/actions/edit-action.d.ts.map +1 -1
  38. package/dist/src/views/admin/posts/table/actions/edit-action.js +1 -1
  39. package/package.json +10 -11
  40. package/src/locales/en.json +11 -1
  41. package/src/routes/admin/blog/categories/page.tsx +19 -2
  42. package/src/routes/admin/blog/posts/page.tsx +19 -2
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyD9B,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;AAgBtC,eAAO,MAAM,uBAAuB;;iBAElC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0D9B,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,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{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 +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;;;;;;;;;;;;;;;;;;EAkC9B,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;AAQtC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAmC9B,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,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";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 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiF5B,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;AAkBtC,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkF5B,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,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{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 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4E1B,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;AAoBtC,eAAO,MAAM,mBAAmB;;;;iBAO9B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6E1B,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,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{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 +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;;;;;;;;;;;;;;;;;;EAkC1B,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;;;;;;;;;;;;;;;;;;EAmC1B,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,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)}return c.body(null,204)}});
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8FxB,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;AAsBtC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+FxB,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,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{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 +1 @@
1
- {"version":3,"file":"config.api.d.ts","sourceRoot":"","sources":["../../src/config.api.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,mEAKzB,CAAC"}
1
+ {"version":3,"file":"config.api.d.ts","sourceRoot":"","sources":["../../src/config.api.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,mEAsBzB,CAAC"}
@@ -1 +1 @@
1
- import{buildApiPlugin}from"@vitnode/core/api/lib/plugin";import{CONFIG_PLUGIN}from"./const.js";import{adminModule}from"./api/modules/admin/admin.module.js";import{categoriesModule}from"./api/modules/categories/categories.module.js";import{postsModule}from"./api/modules/posts/posts.module.js";export const blogApiPlugin=()=>{return buildApiPlugin({pluginId:CONFIG_PLUGIN.pluginId,modules:[adminModule,categoriesModule,postsModule]})};
1
+ import{buildApiPlugin}from"@vitnode/core/api/lib/plugin";import{CONFIG_PLUGIN}from"./const.js";import{adminModule}from"./api/modules/admin/admin.module.js";import{categoriesModule}from"./api/modules/categories/categories.module.js";import{postsModule}from"./api/modules/posts/posts.module.js";export const blogApiPlugin=()=>{return buildApiPlugin({pluginId:CONFIG_PLUGIN.pluginId,modules:[adminModule,categoriesModule,postsModule],permissionStaff:{moderator:{posts:["can_edit","can_delete"]},admin:{posts:["can_view",{permission:"can_create",dependsOn:["can_view"]},"can_edit","can_delete"],categories:["can_view","can_create","can_edit","can_delete"]}}})};
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.tsx"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU,6EAkBtB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.tsx"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU,6EAoBtB,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx}from"react/jsx-runtime";import{buildPlugin}from"@vitnode/core/lib/plugin";import{ListIcon,NotebookPenIcon}from"lucide-react";import{CONFIG_PLUGIN}from"./const.js";export const blogPlugin=()=>{return buildPlugin({pluginId:CONFIG_PLUGIN.pluginId,admin:{nav:[{id:"posts",href:"/admin/blog/posts",icon:_jsx(NotebookPenIcon,{})},{id:"categories",href:"/admin/blog/categories",icon:_jsx(ListIcon,{})}]}})};
1
+ import{jsx as _jsx}from"react/jsx-runtime";import{buildPlugin}from"@vitnode/core/lib/plugin";import{ListIcon,NotebookPenIcon}from"lucide-react";import{CONFIG_PLUGIN}from"./const.js";export const blogPlugin=()=>{return buildPlugin({pluginId:CONFIG_PLUGIN.pluginId,admin:{nav:[{id:"posts",href:"/admin/blog/posts",icon:_jsx(NotebookPenIcon,{}),permission:{module:"posts",permission:"can_view"}},{id:"categories",href:"/admin/blog/categories",icon:_jsx(ListIcon,{}),permission:{module:"categories",permission:"can_view"}}]}})};
@@ -1 +1 @@
1
- {"version":3,"file":"test-template.d.ts","sourceRoot":"","sources":["../../../src/emails/test-template.tsx"],"names":[],"mappings":"AACA,OAA6B,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,uCAAuC,CAAC;AAK/C,iBAAwB,iBAAiB,CAAC,EACxC,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,yBAAyB,sCAQ3B;kBAXuB,iBAAiB;;;;;;;;;;;;;;;;;;;eAAjB,iBAAiB"}
1
+ {"version":3,"file":"test-template.d.ts","sourceRoot":"","sources":["../../../src/emails/test-template.tsx"],"names":[],"mappings":"AAAA,OAA6B,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,uCAAuC,CAAC;AAM/C,iBAAwB,iBAAiB,CAAC,EACxC,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,yBAAyB,sCAQ3B;kBAXuB,iBAAiB;;;;;;;;;;;;;;;;;;;eAAjB,iBAAiB"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Text}from"@react-email/components";import DefaultTemplateEmail from"@vitnode/core/emails/default-template";TestTemplateEmail.PreviewProps=DefaultTemplateEmail.PreviewProps;export default function TestTemplateEmail({user,...props}){if(!user)return null;return _jsx(DefaultTemplateEmail,{...props,children:_jsxs(Text,{children:["This message is for ",user.name]})})}
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import DefaultTemplateEmail from"@vitnode/core/emails/default-template";import{Text}from"react-email";TestTemplateEmail.PreviewProps=DefaultTemplateEmail.PreviewProps;export default function TestTemplateEmail({user,...props}){if(!user)return null;return _jsx(DefaultTemplateEmail,{...props,children:_jsxs(Text,{children:["This message is for ",user.name]})})}
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/admin/blog/categories/page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAOrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,QAAA,MAAM,mBAAmB;;EAIxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,QAAQ,CAMzD,CAAC;AAEF,wBAA8B,cAAc,CAC1C,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,8BAoBzD"}
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/admin/blog/categories/page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AASrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,QAAA,MAAM,mBAAmB;;EAIxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,QAAQ,CAMzD,CAAC;AAEF,wBAA8B,cAAc,CAC1C,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,8BAkCzD"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{I18nProvider}from"@vitnode/core/components/i18n-provider";import{DataTableSkeleton}from"@vitnode/core/components/table/data-table";import{HeaderContent}from"@vitnode/core/components/ui/header-content";import{getTranslations}from"next-intl/server";import dynamic from"next/dynamic";import React from"react";import{ActionsCategoriesAdmin}from"../../../../views/admin/categories/actions/actions.js";const CategoriesAdminView=dynamic(async()=>import("../../../../views/admin/categories/table/categories-admin-view.js").then(mod=>({default:mod.CategoriesAdminView})));export const generateMetadata=async()=>{const t=await getTranslations("@vitnode/blog.admin.nav");return{title:t("categories")}};export default async function CategoriesPage(params){const[t,tNav]=await Promise.all([getTranslations("@vitnode/blog.admin.categories"),getTranslations("@vitnode/blog.admin.nav")]);return _jsx(I18nProvider,{namespaces:["@vitnode/blog.admin.categories"],children:_jsxs("div",{className:"p-4",children:[_jsx(HeaderContent,{desc:t("desc"),h1:tNav("categories"),children:_jsx(ActionsCategoriesAdmin,{})}),_jsx(React.Suspense,{fallback:_jsx(DataTableSkeleton,{columns:4}),children:_jsx(CategoriesAdminView,{...params})})]})})}
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{I18nProvider}from"@vitnode/core/components/i18n-provider";import{DataTableSkeleton}from"@vitnode/core/components/table/data-table";import{HeaderContent}from"@vitnode/core/components/ui/header-content";import{checkAdminPermissionApi}from"@vitnode/core/lib/api/get-session-admin-api";import{getTranslations}from"next-intl/server";import dynamic from"next/dynamic";import{notFound}from"next/navigation";import React from"react";import{CONFIG_PLUGIN}from"../../../../const.js";import{ActionsCategoriesAdmin}from"../../../../views/admin/categories/actions/actions.js";const CategoriesAdminView=dynamic(async()=>import("../../../../views/admin/categories/table/categories-admin-view.js").then(mod=>({default:mod.CategoriesAdminView})));export const generateMetadata=async()=>{const t=await getTranslations("@vitnode/blog.admin.nav");return{title:t("categories")}};export default async function CategoriesPage(params){const[t,tNav,canView,canCreate]=await Promise.all([getTranslations("@vitnode/blog.admin.categories"),getTranslations("@vitnode/blog.admin.nav"),checkAdminPermissionApi({plugin:CONFIG_PLUGIN.pluginId,module:"categories",permission:"can_view"}),checkAdminPermissionApi({plugin:CONFIG_PLUGIN.pluginId,module:"categories",permission:"can_create"})]);if(!canView){notFound()}return _jsx(I18nProvider,{namespaces:["@vitnode/blog.admin.categories"],children:_jsxs("div",{className:"p-4",children:[_jsx(HeaderContent,{desc:t("desc"),h1:tNav("categories"),children:canCreate&&_jsx(ActionsCategoriesAdmin,{})}),_jsx(React.Suspense,{fallback:_jsx(DataTableSkeleton,{columns:4}),children:_jsx(CategoriesAdminView,{...params})})]})})}
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/admin/blog/posts/page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAOrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,QAAA,MAAM,cAAc;;EAInB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,QAAQ,CAMzD,CAAC;AAEF,wBAA8B,SAAS,CACrC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,8BAoBpD"}
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/admin/blog/posts/page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AASrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,QAAA,MAAM,cAAc;;EAInB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,QAAQ,CAMzD,CAAC;AAEF,wBAA8B,SAAS,CACrC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,8BAkCpD"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{I18nProvider}from"@vitnode/core/components/i18n-provider";import{DataTableSkeleton}from"@vitnode/core/components/table/data-table";import{HeaderContent}from"@vitnode/core/components/ui/header-content";import{getTranslations}from"next-intl/server";import dynamic from"next/dynamic";import React from"react";import{ActionsPostsAdmin}from"../../../../views/admin/posts/actions/actions.js";const PostsAdminView=dynamic(async()=>import("../../../../views/admin/posts/table/posts-admin-view.js").then(mod=>({default:mod.PostsAdminView})));export const generateMetadata=async()=>{const t=await getTranslations("@vitnode/blog.admin.nav");return{title:t("posts")}};export default async function PostsPage(params){const[t,tNav]=await Promise.all([getTranslations("@vitnode/blog.admin.posts"),getTranslations("@vitnode/blog.admin.nav")]);return _jsx(I18nProvider,{namespaces:["@vitnode/blog.admin.posts"],children:_jsxs("div",{className:"p-4",children:[_jsx(HeaderContent,{desc:t("desc"),h1:tNav("posts"),children:_jsx(ActionsPostsAdmin,{})}),_jsx(React.Suspense,{fallback:_jsx(DataTableSkeleton,{columns:5}),children:_jsx(PostsAdminView,{...params})})]})})}
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{I18nProvider}from"@vitnode/core/components/i18n-provider";import{DataTableSkeleton}from"@vitnode/core/components/table/data-table";import{HeaderContent}from"@vitnode/core/components/ui/header-content";import{checkAdminPermissionApi}from"@vitnode/core/lib/api/get-session-admin-api";import{getTranslations}from"next-intl/server";import dynamic from"next/dynamic";import{notFound}from"next/navigation";import React from"react";import{CONFIG_PLUGIN}from"../../../../const.js";import{ActionsPostsAdmin}from"../../../../views/admin/posts/actions/actions.js";const PostsAdminView=dynamic(async()=>import("../../../../views/admin/posts/table/posts-admin-view.js").then(mod=>({default:mod.PostsAdminView})));export const generateMetadata=async()=>{const t=await getTranslations("@vitnode/blog.admin.nav");return{title:t("posts")}};export default async function PostsPage(params){const[t,tNav,canView,canCreate]=await Promise.all([getTranslations("@vitnode/blog.admin.posts"),getTranslations("@vitnode/blog.admin.nav"),checkAdminPermissionApi({plugin:CONFIG_PLUGIN.pluginId,module:"posts",permission:"can_view"}),checkAdminPermissionApi({plugin:CONFIG_PLUGIN.pluginId,module:"posts",permission:"can_create"})]);if(!canView){notFound()}return _jsx(I18nProvider,{namespaces:["@vitnode/blog.admin.posts"],children:_jsxs("div",{className:"p-4",children:[_jsx(HeaderContent,{desc:t("desc"),h1:tNav("posts"),children:canCreate&&_jsx(ActionsPostsAdmin,{})}),_jsx(React.Suspense,{fallback:_jsx(DataTableSkeleton,{columns:5}),children:_jsx(PostsAdminView,{...params})})]})})}
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../../../src/views/admin/categories/actions/actions.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,eAAO,MAAM,sBAAsB,yBAwBlC,CAAC"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../../../src/views/admin/categories/actions/actions.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,eAAO,MAAM,sBAAsB,yBAsBlC,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{PlusIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";const CreateEditActionCategoriesAdmin=dynamic(async()=>import("./create-edit/create-edit.js").then(mod=>({default:mod.CreateEditActionCategoriesAdmin})));export const ActionsCategoriesAdmin=()=>{const t=useTranslations("@vitnode/blog.admin.categories.create");return _jsxs(Dialog,{children:[_jsx(DialogTrigger,{asChild:true,children:_jsxs(Button,{children:[_jsx(PlusIcon,{}),t("title")]})}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:t("desc")})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionCategoriesAdmin,{})})]})]})};
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{PlusIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";const CreateEditActionCategoriesAdmin=dynamic(async()=>import("./create-edit/create-edit.js").then(mod=>({default:mod.CreateEditActionCategoriesAdmin})));export const ActionsCategoriesAdmin=()=>{const t=useTranslations("@vitnode/blog.admin.categories.create");return _jsxs(Dialog,{children:[_jsxs(DialogTrigger,{render:_jsx(Button,{}),children:[_jsx(PlusIcon,{}),t("title")]}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:t("desc")})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionCategoriesAdmin,{})})]})]})};
@@ -1,5 +1,5 @@
1
1
  export declare const DeleteAction: ({ title, id }: {
2
2
  id: number;
3
3
  title: string;
4
- }) => import("react").JSX.Element;
4
+ }) => import("react").JSX.Element | null;
5
5
  //# sourceMappingURL=delete-action.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delete-action.d.ts","sourceRoot":"","sources":["../../../../../../../../src/views/admin/categories/table/actions/delete/delete-action.tsx"],"names":[],"mappings":"AAgBA,eAAO,MAAM,YAAY,GAAI,eAAe;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,gCA4CxE,CAAC"}
1
+ {"version":3,"file":"delete-action.d.ts","sourceRoot":"","sources":["../../../../../../../../src/views/admin/categories/table/actions/delete/delete-action.tsx"],"names":[],"mappings":"AAmBA,eAAO,MAAM,YAAY,GAAI,eAAe;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,uCAmDxE,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{ConfirmActionAlertDialog}from"@vitnode/core/components/confirm-action/confirm-action-alert-dialog";import{Button}from"@vitnode/core/components/ui/button";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{Trash2Icon}from"lucide-react";import{useTranslations}from"next-intl";import{toast}from"sonner";import{mutationApi}from"./mutation-api.js";export const DeleteAction=({title,id})=>{const t=useTranslations("@vitnode/blog.admin.categories.delete");const tGlobal=useTranslations("core.global");return _jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(ConfirmActionAlertDialog,{description:t.rich("desc",{title:()=>_jsx("span",{className:"text-foreground font-bold",children:title})}),onSubmit:async({onClose})=>{const mutation=await mutationApi(id);if(mutation?.error){toast.error(tGlobal("errors.title"),{description:tGlobal("errors.internal_server_error")});return}toast.success(t("success"),{description:title});onClose()},textSubmit:t("confirm"),title:t("title"),children:_jsx(TooltipTrigger,{render:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"destructive",children:_jsx(Trash2Icon,{className:"size-4"})})})}),_jsx(TooltipContent,{children:t("title")})]})})};
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{ConfirmActionAlertDialog}from"@vitnode/core/components/confirm-action/confirm-action-alert-dialog";import{useAdminStaffPermission}from"@vitnode/core/components/staff-permission/provider";import{Button}from"@vitnode/core/components/ui/button";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{Trash2Icon}from"lucide-react";import{useTranslations}from"next-intl";import{toast}from"sonner";import{CONFIG_PLUGIN}from"../../../../../../const.js";import{mutationApi}from"./mutation-api.js";export const DeleteAction=({title,id})=>{const t=useTranslations("@vitnode/blog.admin.categories.delete");const tGlobal=useTranslations("core.global");const canDelete=useAdminStaffPermission({plugin:CONFIG_PLUGIN.pluginId,module:"categories",permission:"can_delete"});if(!canDelete)return null;return _jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(ConfirmActionAlertDialog,{description:t.rich("desc",{title:()=>_jsx("span",{className:"text-foreground font-bold",children:title})}),onSubmit:async({onClose})=>{const mutation=await mutationApi(id);if(mutation?.error){toast.error(tGlobal("errors.title"),{description:tGlobal("errors.internal_server_error")});return}toast.success(t("success"),{description:title});onClose()},textSubmit:t("confirm"),title:t("title"),children:_jsx(TooltipTrigger,{render:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"destructive",children:_jsx(Trash2Icon,{className:"size-4"})})})}),_jsx(TooltipContent,{children:t("title")})]})})};
@@ -4,6 +4,6 @@ declare const CreateEditActionCategoriesAdmin: React.ComponentType<{
4
4
  id: number;
5
5
  };
6
6
  }>;
7
- export declare const EditAction: (props: Required<React.ComponentProps<typeof CreateEditActionCategoriesAdmin>>) => React.JSX.Element;
7
+ export declare const EditAction: (props: Required<React.ComponentProps<typeof CreateEditActionCategoriesAdmin>>) => React.JSX.Element | null;
8
8
  export {};
9
9
  //# sourceMappingURL=edit-action.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"edit-action.d.ts","sourceRoot":"","sources":["../../../../../../../src/views/admin/categories/table/actions/edit-action.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,QAAA,MAAM,+BAA+B;;;;EAIpC,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,OAAO,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,+BAA+B,CAAC,CAAC,sBAiC9E,CAAC"}
1
+ {"version":3,"file":"edit-action.d.ts","sourceRoot":"","sources":["../../../../../../../src/views/admin/categories/table/actions/edit-action.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,QAAA,MAAM,+BAA+B;;;;EAIpC,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,OAAO,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,+BAA+B,CAAC,CAAC,6BA0C9E,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{PencilIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";const CreateEditActionCategoriesAdmin=dynamic(async()=>import("../../actions/create-edit/create-edit.js").then(mod=>({default:mod.CreateEditActionCategoriesAdmin})));export const EditAction=props=>{const t=useTranslations("@vitnode/blog.admin.categories.edit");return _jsxs(Dialog,{children:[_jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(TooltipTrigger,{render:_jsx(DialogTrigger,{asChild:true,children:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"ghost",children:_jsx(PencilIcon,{})})})}),_jsx(TooltipContent,{children:t("title")})]})}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:props.data.title})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionCategoriesAdmin,{...props})})]})]})};
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useAdminStaffPermission}from"@vitnode/core/components/staff-permission/provider";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{PencilIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";import{CONFIG_PLUGIN}from"../../../../../const.js";const CreateEditActionCategoriesAdmin=dynamic(async()=>import("../../actions/create-edit/create-edit.js").then(mod=>({default:mod.CreateEditActionCategoriesAdmin})));export const EditAction=props=>{const t=useTranslations("@vitnode/blog.admin.categories.edit");const canEdit=useAdminStaffPermission({plugin:CONFIG_PLUGIN.pluginId,module:"categories",permission:"can_edit"});if(!canEdit)return null;return _jsxs(Dialog,{children:[_jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(TooltipTrigger,{render:_jsx(DialogTrigger,{render:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"ghost"}),children:_jsx(PencilIcon,{})})}),_jsx(TooltipContent,{children:t("title")})]})}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:props.data.title})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionCategoriesAdmin,{...props})})]})]})};
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../../../src/views/admin/posts/actions/actions.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,eAAO,MAAM,iBAAiB,yBAwB7B,CAAC"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../../../src/views/admin/posts/actions/actions.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,eAAO,MAAM,iBAAiB,yBAsB7B,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{PlusIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";const CreateEditActionPostsAdmin=dynamic(async()=>import("./create-edit/create-edit.js").then(module=>({default:module.CreateEditActionPostsAdmin})));export const ActionsPostsAdmin=()=>{const t=useTranslations("@vitnode/blog.admin.posts.create");return _jsxs(Dialog,{children:[_jsx(DialogTrigger,{asChild:true,children:_jsxs(Button,{children:[_jsx(PlusIcon,{}),t("title")]})}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:t("desc")})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionPostsAdmin,{})})]})]})};
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{PlusIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";const CreateEditActionPostsAdmin=dynamic(async()=>import("./create-edit/create-edit.js").then(module=>({default:module.CreateEditActionPostsAdmin})));export const ActionsPostsAdmin=()=>{const t=useTranslations("@vitnode/blog.admin.posts.create");return _jsxs(Dialog,{children:[_jsxs(DialogTrigger,{render:_jsx(Button,{}),children:[_jsx(PlusIcon,{}),t("title")]}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:t("desc")})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionPostsAdmin,{})})]})]})};
@@ -1,5 +1,5 @@
1
1
  export declare const DeleteAction: ({ title, id }: {
2
2
  id: number;
3
3
  title: string;
4
- }) => import("react").JSX.Element;
4
+ }) => import("react").JSX.Element | null;
5
5
  //# sourceMappingURL=delete-action.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delete-action.d.ts","sourceRoot":"","sources":["../../../../../../../../src/views/admin/posts/table/actions/delete/delete-action.tsx"],"names":[],"mappings":"AAgBA,eAAO,MAAM,YAAY,GAAI,eAAe;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,gCA4CxE,CAAC"}
1
+ {"version":3,"file":"delete-action.d.ts","sourceRoot":"","sources":["../../../../../../../../src/views/admin/posts/table/actions/delete/delete-action.tsx"],"names":[],"mappings":"AAmBA,eAAO,MAAM,YAAY,GAAI,eAAe;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,uCAmDxE,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{ConfirmActionAlertDialog}from"@vitnode/core/components/confirm-action/confirm-action-alert-dialog";import{Button}from"@vitnode/core/components/ui/button";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{Trash2Icon}from"lucide-react";import{useTranslations}from"next-intl";import{toast}from"sonner";import{mutationApi}from"./mutation-api.js";export const DeleteAction=({title,id})=>{const t=useTranslations("@vitnode/blog.admin.posts.delete");const tGlobal=useTranslations("core.global");return _jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(ConfirmActionAlertDialog,{description:t.rich("desc",{title:()=>_jsx("span",{className:"text-foreground font-bold",children:title})}),onSubmit:async({onClose})=>{const mutation=await mutationApi(id);if(mutation?.error){toast.error(tGlobal("errors.title"),{description:tGlobal("errors.internal_server_error")});return}toast.success(t("success"),{description:title});onClose()},textSubmit:t("confirm"),title:t("title"),children:_jsx(TooltipTrigger,{render:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"destructive",children:_jsx(Trash2Icon,{className:"size-4"})})})}),_jsx(TooltipContent,{children:t("title")})]})})};
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{ConfirmActionAlertDialog}from"@vitnode/core/components/confirm-action/confirm-action-alert-dialog";import{useAdminStaffPermission}from"@vitnode/core/components/staff-permission/provider";import{Button}from"@vitnode/core/components/ui/button";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{Trash2Icon}from"lucide-react";import{useTranslations}from"next-intl";import{toast}from"sonner";import{CONFIG_PLUGIN}from"../../../../../../const.js";import{mutationApi}from"./mutation-api.js";export const DeleteAction=({title,id})=>{const t=useTranslations("@vitnode/blog.admin.posts.delete");const tGlobal=useTranslations("core.global");const canDelete=useAdminStaffPermission({plugin:CONFIG_PLUGIN.pluginId,module:"posts",permission:"can_delete"});if(!canDelete)return null;return _jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(ConfirmActionAlertDialog,{description:t.rich("desc",{title:()=>_jsx("span",{className:"text-foreground font-bold",children:title})}),onSubmit:async({onClose})=>{const mutation=await mutationApi(id);if(mutation?.error){toast.error(tGlobal("errors.title"),{description:tGlobal("errors.internal_server_error")});return}toast.success(t("success"),{description:title});onClose()},textSubmit:t("confirm"),title:t("title"),children:_jsx(TooltipTrigger,{render:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"destructive",children:_jsx(Trash2Icon,{className:"size-4"})})})}),_jsx(TooltipContent,{children:t("title")})]})})};
@@ -4,6 +4,6 @@ declare const CreateEditActionPostsAdmin: React.ComponentType<{
4
4
  id?: number;
5
5
  };
6
6
  }>;
7
- export declare const EditAction: (props: Required<React.ComponentProps<typeof CreateEditActionPostsAdmin>>) => React.JSX.Element;
7
+ export declare const EditAction: (props: Required<React.ComponentProps<typeof CreateEditActionPostsAdmin>>) => React.JSX.Element | null;
8
8
  export {};
9
9
  //# sourceMappingURL=edit-action.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"edit-action.d.ts","sourceRoot":"","sources":["../../../../../../../src/views/admin/posts/table/actions/edit-action.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,QAAA,MAAM,0BAA0B;;UActB,CAAC;;EAVV,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,OAAO,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,0BAA0B,CAAC,CAAC,sBAiCzE,CAAC"}
1
+ {"version":3,"file":"edit-action.d.ts","sourceRoot":"","sources":["../../../../../../../src/views/admin/posts/table/actions/edit-action.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,QAAA,MAAM,0BAA0B;;UAOqC,CAAC;;EAHrE,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,OAAO,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,0BAA0B,CAAC,CAAC,6BA0CzE,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{PencilIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";const CreateEditActionPostsAdmin=dynamic(async()=>import("../../actions/create-edit/create-edit.js").then(mod=>({default:mod.CreateEditActionPostsAdmin})));export const EditAction=props=>{const t=useTranslations("@vitnode/blog.admin.posts.edit");return _jsxs(Dialog,{children:[_jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(TooltipTrigger,{render:_jsx(DialogTrigger,{asChild:true,children:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"ghost",children:_jsx(PencilIcon,{})})})}),_jsx(TooltipContent,{children:t("title")})]})}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:props.data.title})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionPostsAdmin,{...props})})]})]})};
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useAdminStaffPermission}from"@vitnode/core/components/staff-permission/provider";import{Button}from"@vitnode/core/components/ui/button";import{Dialog,DialogContent,DialogDescription,DialogHeader,DialogTitle,DialogTrigger}from"@vitnode/core/components/ui/dialog";import{Loader}from"@vitnode/core/components/ui/loader";import{Tooltip,TooltipContent,TooltipProvider,TooltipTrigger}from"@vitnode/core/components/ui/tooltip";import{PencilIcon}from"lucide-react";import{useTranslations}from"next-intl";import dynamic from"next/dynamic";import React from"react";import{CONFIG_PLUGIN}from"../../../../../const.js";const CreateEditActionPostsAdmin=dynamic(async()=>import("../../actions/create-edit/create-edit.js").then(mod=>({default:mod.CreateEditActionPostsAdmin})));export const EditAction=props=>{const t=useTranslations("@vitnode/blog.admin.posts.edit");const canEdit=useAdminStaffPermission({plugin:CONFIG_PLUGIN.pluginId,module:"posts",permission:"can_edit"});if(!canEdit)return null;return _jsxs(Dialog,{children:[_jsx(TooltipProvider,{children:_jsxs(Tooltip,{children:[_jsx(TooltipTrigger,{render:_jsx(DialogTrigger,{render:_jsx(Button,{"aria-label":t("title"),size:"icon",variant:"ghost"}),children:_jsx(PencilIcon,{})})}),_jsx(TooltipContent,{children:t("title")})]})}),_jsxs(DialogContent,{children:[_jsxs(DialogHeader,{children:[_jsx(DialogTitle,{children:t("title")}),_jsx(DialogDescription,{children:props.data.title})]}),_jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(CreateEditActionPostsAdmin,{...props})})]})]})};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitnode/blog",
3
- "version": "1.2.0-canary.74",
3
+ "version": "1.2.0-canary.75",
4
4
  "description": "Blog plugin for VitNode, providing a blogging platform with Next.js and Hono.js.",
5
5
  "author": "VitNode Team",
6
6
  "license": "MIT",
@@ -30,30 +30,29 @@
30
30
  "@hono/zod-openapi": "^1.4.0",
31
31
  "drizzle-kit": "^0.31.10",
32
32
  "drizzle-orm": "^0.45.2",
33
- "hono": "^4.12.25",
34
- "lucide-react": "^1.18.0",
35
- "next": "^16.2.9",
33
+ "hono": "^4.12.27",
34
+ "lucide-react": "^1.21.0",
35
+ "next": "16.3.0-preview.5",
36
36
  "next-intl": "^4.13.0",
37
37
  "react": "^19.2.7",
38
38
  "react-dom": "^19.2.7",
39
- "react-email": "^6.6.0",
40
- "react-hook-form": "^7.79.0",
39
+ "react-email": "^6.6.6",
40
+ "react-hook-form": "^7.80.0",
41
41
  "sonner": "^2.0.7",
42
- "use-intl": "^4.13.0",
43
42
  "zod": "^4.4.3",
44
- "@vitnode/core": "1.2.0-canary.74"
43
+ "@vitnode/core": "1.2.0-canary.75"
45
44
  },
46
45
  "devDependencies": {
47
- "@react-email/components": "^1.0.12",
46
+ "@react-email/ui": "^6.6.6",
48
47
  "@swc/cli": "^0.8.1",
49
- "@swc/core": "^1.15.41",
48
+ "@swc/core": "^1.15.43",
50
49
  "@types/react": "^19.2.17",
51
50
  "@types/react-dom": "^19.2.3",
52
51
  "concurrently": "^10.0.3",
53
52
  "eslint": "^10.5.0",
54
53
  "tsc-alias": "^1.8.17",
55
54
  "typescript": "^6.0.3",
56
- "@vitnode/config": "1.2.0-canary.74"
55
+ "@vitnode/config": "1.2.0-canary.75"
57
56
  },
58
57
  "scripts": {
59
58
  "build:plugins": "tsc && swc src -d dist --config-file .swcrc && tsc-alias -p tsconfig.json",
@@ -66,5 +66,15 @@
66
66
  }
67
67
  }
68
68
  }
69
- }
69
+ },
70
+ "@vitnode/blog:posts": "Posts",
71
+ "@vitnode/blog:posts:can_view": "View posts list",
72
+ "@vitnode/blog:posts:can_create": "Create posts",
73
+ "@vitnode/blog:posts:can_edit": "Edit posts",
74
+ "@vitnode/blog:posts:can_delete": "Delete posts",
75
+ "@vitnode/blog:categories": "Categories",
76
+ "@vitnode/blog:categories:can_view": "View categories list",
77
+ "@vitnode/blog:categories:can_create": "Create categories",
78
+ "@vitnode/blog:categories:can_edit": "Edit categories",
79
+ "@vitnode/blog:categories:can_delete": "Delete categories"
70
80
  }
@@ -3,10 +3,13 @@ import type { Metadata } from "next";
3
3
  import { I18nProvider } from "@vitnode/core/components/i18n-provider";
4
4
  import { DataTableSkeleton } from "@vitnode/core/components/table/data-table";
5
5
  import { HeaderContent } from "@vitnode/core/components/ui/header-content";
6
+ import { checkAdminPermissionApi } from "@vitnode/core/lib/api/get-session-admin-api";
6
7
  import { getTranslations } from "next-intl/server";
7
8
  import dynamic from "next/dynamic";
9
+ import { notFound } from "next/navigation";
8
10
  import React from "react";
9
11
 
12
+ import { CONFIG_PLUGIN } from "@/const";
10
13
  import { ActionsCategoriesAdmin } from "@/views/admin/categories/actions/actions";
11
14
 
12
15
  const CategoriesAdminView = dynamic(async () =>
@@ -26,16 +29,30 @@ export const generateMetadata = async (): Promise<Metadata> => {
26
29
  export default async function CategoriesPage(
27
30
  params: React.ComponentProps<typeof CategoriesAdminView>,
28
31
  ) {
29
- const [t, tNav] = await Promise.all([
32
+ const [t, tNav, canView, canCreate] = await Promise.all([
30
33
  getTranslations("@vitnode/blog.admin.categories"),
31
34
  getTranslations("@vitnode/blog.admin.nav"),
35
+ checkAdminPermissionApi({
36
+ plugin: CONFIG_PLUGIN.pluginId,
37
+ module: "categories",
38
+ permission: "can_view",
39
+ }),
40
+ checkAdminPermissionApi({
41
+ plugin: CONFIG_PLUGIN.pluginId,
42
+ module: "categories",
43
+ permission: "can_create",
44
+ }),
32
45
  ]);
33
46
 
47
+ if (!canView) {
48
+ notFound();
49
+ }
50
+
34
51
  return (
35
52
  <I18nProvider namespaces={["@vitnode/blog.admin.categories"]}>
36
53
  <div className="p-4">
37
54
  <HeaderContent desc={t("desc")} h1={tNav("categories")}>
38
- <ActionsCategoriesAdmin />
55
+ {canCreate && <ActionsCategoriesAdmin />}
39
56
  </HeaderContent>
40
57
 
41
58
  <React.Suspense fallback={<DataTableSkeleton columns={4} />}>
@@ -3,10 +3,13 @@ import type { Metadata } from "next";
3
3
  import { I18nProvider } from "@vitnode/core/components/i18n-provider";
4
4
  import { DataTableSkeleton } from "@vitnode/core/components/table/data-table";
5
5
  import { HeaderContent } from "@vitnode/core/components/ui/header-content";
6
+ import { checkAdminPermissionApi } from "@vitnode/core/lib/api/get-session-admin-api";
6
7
  import { getTranslations } from "next-intl/server";
7
8
  import dynamic from "next/dynamic";
9
+ import { notFound } from "next/navigation";
8
10
  import React from "react";
9
11
 
12
+ import { CONFIG_PLUGIN } from "@/const";
10
13
  import { ActionsPostsAdmin } from "@/views/admin/posts/actions/actions";
11
14
 
12
15
  const PostsAdminView = dynamic(async () =>
@@ -26,16 +29,30 @@ export const generateMetadata = async (): Promise<Metadata> => {
26
29
  export default async function PostsPage(
27
30
  params: React.ComponentProps<typeof PostsAdminView>,
28
31
  ) {
29
- const [t, tNav] = await Promise.all([
32
+ const [t, tNav, canView, canCreate] = await Promise.all([
30
33
  getTranslations("@vitnode/blog.admin.posts"),
31
34
  getTranslations("@vitnode/blog.admin.nav"),
35
+ checkAdminPermissionApi({
36
+ plugin: CONFIG_PLUGIN.pluginId,
37
+ module: "posts",
38
+ permission: "can_view",
39
+ }),
40
+ checkAdminPermissionApi({
41
+ plugin: CONFIG_PLUGIN.pluginId,
42
+ module: "posts",
43
+ permission: "can_create",
44
+ }),
32
45
  ]);
33
46
 
47
+ if (!canView) {
48
+ notFound();
49
+ }
50
+
34
51
  return (
35
52
  <I18nProvider namespaces={["@vitnode/blog.admin.posts"]}>
36
53
  <div className="p-4">
37
54
  <HeaderContent desc={t("desc")} h1={tNav("posts")}>
38
- <ActionsPostsAdmin />
55
+ {canCreate && <ActionsPostsAdmin />}
39
56
  </HeaderContent>
40
57
 
41
58
  <React.Suspense fallback={<DataTableSkeleton columns={5} />}>