@vitnode/blog 0.0.1-canary.0

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 (63) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/src/admin/content.d.ts +5 -0
  3. package/dist/src/admin/content.d.ts.map +1 -0
  4. package/dist/src/admin/content.js +1 -0
  5. package/dist/src/admin/nav.d.ts +41 -0
  6. package/dist/src/admin/nav.d.ts.map +1 -0
  7. package/dist/src/admin/nav.js +1 -0
  8. package/dist/src/api/lib/events.d.ts +36 -0
  9. package/dist/src/api/lib/events.d.ts.map +1 -0
  10. package/dist/src/api/lib/events.js +1 -0
  11. package/dist/src/api/modules/admin/admin.module.d.ts +2 -0
  12. package/dist/src/api/modules/admin/admin.module.d.ts.map +1 -0
  13. package/dist/src/api/modules/admin/admin.module.js +1 -0
  14. package/dist/src/config.api.d.ts +2 -0
  15. package/dist/src/config.api.d.ts.map +1 -0
  16. package/dist/src/config.api.js +1 -0
  17. package/dist/src/config.d.ts +2 -0
  18. package/dist/src/config.d.ts.map +1 -0
  19. package/dist/src/config.js +1 -0
  20. package/dist/src/const.d.ts +4 -0
  21. package/dist/src/const.d.ts.map +1 -0
  22. package/dist/src/const.js +1 -0
  23. package/dist/src/content/category.d.ts +5 -0
  24. package/dist/src/content/category.d.ts.map +1 -0
  25. package/dist/src/content/category.js +1 -0
  26. package/dist/src/content/post.d.ts +10 -0
  27. package/dist/src/content/post.d.ts.map +1 -0
  28. package/dist/src/content/post.js +1 -0
  29. package/dist/src/database/categories.d.ts +11 -0
  30. package/dist/src/database/categories.d.ts.map +1 -0
  31. package/dist/src/database/categories.js +1 -0
  32. package/dist/src/database/posts.d.ts +23 -0
  33. package/dist/src/database/posts.d.ts.map +1 -0
  34. package/dist/src/database/posts.js +1 -0
  35. package/dist/src/emails/test-template.d.ts +23 -0
  36. package/dist/src/emails/test-template.d.ts.map +1 -0
  37. package/dist/src/emails/test-template.js +1 -0
  38. package/dist/src/globals.css +44 -0
  39. package/dist/src/locales/en.json +69 -0
  40. package/dist/src/locales/index.d.ts +4 -0
  41. package/dist/src/locales/index.d.ts.map +1 -0
  42. package/dist/src/locales/index.js +1 -0
  43. package/dist/src/locales/pl.json +69 -0
  44. package/dist/src/views/admin/article/editor-field.d.ts +4 -0
  45. package/dist/src/views/admin/article/editor-field.d.ts.map +1 -0
  46. package/dist/src/views/admin/article/editor-field.js +1 -0
  47. package/dist/src/views/admin/article/form-layout.d.ts +3 -0
  48. package/dist/src/views/admin/article/form-layout.d.ts.map +1 -0
  49. package/dist/src/views/admin/article/form-layout.js +1 -0
  50. package/dist/src/views/admin/category/color-cell.d.ts +4 -0
  51. package/dist/src/views/admin/category/color-cell.d.ts.map +1 -0
  52. package/dist/src/views/admin/category/color-cell.js +1 -0
  53. package/dist/src/views/admin/category/color-field.d.ts +3 -0
  54. package/dist/src/views/admin/category/color-field.d.ts.map +1 -0
  55. package/dist/src/views/admin/category/color-field.js +1 -0
  56. package/dist/vitest.config.d.ts +3 -0
  57. package/dist/vitest.config.d.ts.map +1 -0
  58. package/eslint.config.mjs +19 -0
  59. package/package.json +70 -0
  60. package/src/locales/en.json +69 -0
  61. package/src/locales/index.ts +12 -0
  62. package/src/locales/pl.json +69 -0
  63. package/tsconfig.build.json +10 -0
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 aXenDev Maciej Balcerzak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ export declare const adminContent: {
2
+ pluginId: "@vitnode/blog";
3
+ contentTypes: import("@vitnode/core/lib/plugin").ContentTypeFrontendRegistration[];
4
+ };
5
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../src/admin/content.tsx"],"names":[],"mappings":"AA8CA,eAAO,MAAM,YAAY;;;CAyBc,CAAC"}
@@ -0,0 +1 @@
1
+ import{contentTypeAdmin}from"@vitnode/core/lib/plugin";import{CONFIG_PLUGIN}from"../const.js";import{BlogArticleEditorField}from"../views/admin/article/editor-field.js";import{BlogArticleFormLayout}from"../views/admin/article/form-layout.js";import{BlogCategoryColorCell}from"../views/admin/category/color-cell.js";import{BlogCategoryColorField}from"../views/admin/category/color-field.js";import{blogCategoryNav,blogPostNav}from"./nav.js";export const adminContent={pluginId:CONFIG_PLUGIN.pluginId,contentTypes:[contentTypeAdmin({...blogPostNav,fields:{content:{component:BlogArticleEditorField}},forms:{layout:BlogArticleFormLayout}}),contentTypeAdmin({...blogCategoryNav,fields:{color:{component:BlogCategoryColorField}},columns:{color:{cell:BlogCategoryColorCell}}})]};
@@ -0,0 +1,41 @@
1
+ export declare const blogPostNav: {
2
+ definition: import("@vitnode/core/content").ContentTypeDefinition<"blog.post", {
3
+ categoryId: import("@vitnode/core/content").ContentRelationField<false, false, true, false, false>;
4
+ authorId: import("@vitnode/core/content").ContentUserField<false, false, true, true>;
5
+ title: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
6
+ friendlyUrl: import("@vitnode/core/content").ContentSlugField<"title", true>;
7
+ content: import("@vitnode/core/content").ContentTextareaField<true, false, undefined, true>;
8
+ coverImage: import("@vitnode/core/content/types").ContentFileField<false, true, false, false>;
9
+ coverImageAlt: import("@vitnode/core/content").ContentTextField<false, true, undefined, true>;
10
+ }, true, "id" | "publishedAt" | "categoryId" | "title" | "friendlyUrl" | "content" | "coverImage" | "coverImageAlt", true, true, true, true, true, true, true>;
11
+ icon: import("react").JSX.Element;
12
+ };
13
+ export declare const blogCategoryNav: {
14
+ definition: import("@vitnode/core/content").ContentTypeDefinition<"blog.category", {
15
+ name: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
16
+ color: import("@vitnode/core/content").ContentTextField<false, true, undefined, false>;
17
+ }, false, never, false, false, false, false, false, true, false>;
18
+ icon: import("react").JSX.Element;
19
+ };
20
+ export declare const adminNav: {
21
+ pluginId: "@vitnode/blog";
22
+ contentTypes: ({
23
+ definition: import("@vitnode/core/content").ContentTypeDefinition<"blog.post", {
24
+ categoryId: import("@vitnode/core/content").ContentRelationField<false, false, true, false, false>;
25
+ authorId: import("@vitnode/core/content").ContentUserField<false, false, true, true>;
26
+ title: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
27
+ friendlyUrl: import("@vitnode/core/content").ContentSlugField<"title", true>;
28
+ content: import("@vitnode/core/content").ContentTextareaField<true, false, undefined, true>;
29
+ coverImage: import("@vitnode/core/content/types").ContentFileField<false, true, false, false>;
30
+ coverImageAlt: import("@vitnode/core/content").ContentTextField<false, true, undefined, true>;
31
+ }, true, "id" | "publishedAt" | "categoryId" | "title" | "friendlyUrl" | "content" | "coverImage" | "coverImageAlt", true, true, true, true, true, true, true>;
32
+ icon: import("react").JSX.Element;
33
+ } | {
34
+ definition: import("@vitnode/core/content").ContentTypeDefinition<"blog.category", {
35
+ name: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
36
+ color: import("@vitnode/core/content").ContentTextField<false, true, undefined, false>;
37
+ }, false, never, false, false, false, false, false, true, false>;
38
+ icon: import("react").JSX.Element;
39
+ })[];
40
+ };
41
+ //# sourceMappingURL=nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav.d.ts","sourceRoot":"","sources":["../../../src/admin/nav.tsx"],"names":[],"mappings":"AAsCA,eAAO,MAAM,WAAW;;;;;;;;;;;CAGvB,CAAC;AAGF,eAAO,MAAM,eAAe;;;;;;CAG3B,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;CAGW,CAAC"}
@@ -0,0 +1 @@
1
+ import{jsx as _jsx}from"react/jsx-runtime";import{ListIcon,NotebookPenIcon}from"lucide-react";import{CONFIG_PLUGIN}from"../const.js";import{blogCategoryContentType}from"../content/category.js";import{blogPostContentType}from"../content/post.js";export const blogPostNav={definition:blogPostContentType,icon:_jsx(NotebookPenIcon,{})};export const blogCategoryNav={definition:blogCategoryContentType,icon:_jsx(ListIcon,{})};export const adminNav={pluginId:CONFIG_PLUGIN.pluginId,contentTypes:[blogPostNav,blogCategoryNav]};
@@ -0,0 +1,36 @@
1
+ import type { ContentEventsFor } from "@vitnode/core/content";
2
+ import type { blogCategoryContentType } from "../../content/category";
3
+ import { blogPostContentType } from "../../content/post";
4
+ declare module "@vitnode/core/api/models/events" {
5
+ interface VitNodeEvents extends ContentEventsFor<typeof blogCategoryContentType>, ContentEventsFor<typeof blogPostContentType> {
6
+ "blog.category.created": {
7
+ categoryId: number;
8
+ };
9
+ "blog.category.deleted": {
10
+ categoryId: number;
11
+ postIds: number[];
12
+ };
13
+ "blog.category.updated": {
14
+ categoryId: number;
15
+ };
16
+ "blog.post.created": {
17
+ categoryId: number;
18
+ postId: number;
19
+ };
20
+ "blog.post.deleted": {
21
+ postId: number;
22
+ };
23
+ "blog.post.updated": {
24
+ categoryId: number;
25
+ postId: number;
26
+ };
27
+ }
28
+ }
29
+ export declare const legacyPostCreatedListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
30
+ export declare const legacyPostUpdatedListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
31
+ export declare const legacyPostDeletedListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
32
+ export declare const legacyCategoryCreatedListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
33
+ export declare const legacyCategoryUpdatedListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
34
+ export declare const legacyCategoryDeletedListener: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>;
35
+ export declare const blogLegacyEventListeners: import("@vitnode/core/api/lib/events").BuildEventListenerReturn<keyof import("@vitnode/core/api/models/events").VitNodeEvents>[];
36
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/api/lib/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAM9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAgBrD,OAAO,QAAQ,iCAAiC,CAAC;IAC/C,UAAU,aACR,SACE,gBAAgB,CAAC,OAAO,uBAAuB,CAAC,EAChD,gBAAgB,CAAC,OAAO,mBAAmB,CAAC;QAC9C,uBAAuB,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,uBAAuB,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC;YASnB,OAAO,EAAE,MAAM,EAAE,CAAC;SACnB,CAAC;QACF,uBAAuB,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,mBAAmB,EAAE;YAUnB,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QASF,mBAAmB,EAAE;YACnB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,mBAAmB,EAAE;YACnB,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH;CACF;AAqBD,eAAO,MAAM,yBAAyB,gIAapC,CAAC;AAEH,eAAO,MAAM,yBAAyB,gIAapC,CAAC;AAEH,eAAO,MAAM,yBAAyB,gIASpC,CAAC;AAEH,eAAO,MAAM,6BAA6B,gIASxC,CAAC;AAEH,eAAO,MAAM,6BAA6B,gIASxC,CAAC;AAEH,eAAO,MAAM,6BAA6B,gIAYxC,CAAC;AAEH,eAAO,MAAM,wBAAwB,kIAOpC,CAAC"}
@@ -0,0 +1 @@
1
+ import{buildEventListener}from"@vitnode/core/api/lib/events";import{contentEventName}from"@vitnode/core/content";import{blogPostContentType}from"../../content/post.js";import{postContent}from"../../database/posts.js";const POST=blogPostContentType.id;const CATEGORY="blog.category";const categoryOf=async(c,postId)=>{const[first]=await postContent.service(c).relations.categoryId.get(postId);return first??null};export const legacyPostCreatedListener=buildEventListener({event:contentEventName(POST,"created"),name:"legacy-blog-post-created",description:"Re-emits the blog's own blog.post.created event",handler:async(c,payload)=>{const categoryId=await categoryOf(c,payload.contentId);if(categoryId===null)return;await c.get("events").emit("blog.post.created",{categoryId,postId:payload.contentId})}});export const legacyPostUpdatedListener=buildEventListener({event:contentEventName(POST,"updated"),name:"legacy-blog-post-updated",description:"Re-emits the blog's own blog.post.updated event",handler:async(c,payload)=>{const categoryId=await categoryOf(c,payload.contentId);if(categoryId===null)return;await c.get("events").emit("blog.post.updated",{categoryId,postId:payload.contentId})}});export const legacyPostDeletedListener=buildEventListener({event:contentEventName(POST,"deleted"),name:"legacy-blog-post-deleted",description:"Re-emits the blog's own blog.post.deleted event",handler:async(c,payload)=>{await c.get("events").emit("blog.post.deleted",{postId:payload.contentId})}});export const legacyCategoryCreatedListener=buildEventListener({event:contentEventName(CATEGORY,"created"),name:"legacy-blog-category-created",description:"Re-emits the blog's own blog.category.created event",handler:async(c,payload)=>{await c.get("events").emit("blog.category.created",{categoryId:payload.contentId})}});export const legacyCategoryUpdatedListener=buildEventListener({event:contentEventName(CATEGORY,"updated"),name:"legacy-blog-category-updated",description:"Re-emits the blog's own blog.category.updated event",handler:async(c,payload)=>{await c.get("events").emit("blog.category.updated",{categoryId:payload.contentId})}});export const legacyCategoryDeletedListener=buildEventListener({event:contentEventName(CATEGORY,"deleted"),name:"legacy-blog-category-deleted",description:"Re-emits the blog's own blog.category.deleted event",handler:async(c,payload)=>{await c.get("events").emit("blog.category.deleted",{categoryId:payload.contentId,postIds:[]})}});export const blogLegacyEventListeners=[legacyCategoryCreatedListener,legacyCategoryDeletedListener,legacyCategoryUpdatedListener,legacyPostCreatedListener,legacyPostDeletedListener,legacyPostUpdatedListener];
@@ -0,0 +1,2 @@
1
+ export declare const adminModule: import("@vitnode/core/api/lib/module").BuildModuleReturn<"@vitnode/blog", "admin", [], import("@vitnode/core/api/lib/module").BuildModuleReturn<"@vitnode/blog", "content", import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", import("@hono/zod-openapi").RouteConfig>[], import("@vitnode/core/api/lib/module").BaseBuildModuleReturn<"@vitnode/blog", string, import("@vitnode/core/api/lib/route").Route<"@vitnode/blog", import("@hono/zod-openapi").RouteConfig>[]>[]>[]>;
2
+ //# sourceMappingURL=admin.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.module.d.ts","sourceRoot":"","sources":["../../../../../src/api/modules/admin/admin.module.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,WAAW,2dAatB,CAAC"}
@@ -0,0 +1 @@
1
+ import{buildModule}from"@vitnode/core/api/lib/module";import{buildContentAdminModule}from"@vitnode/core/content/server";import{blogLegacyEventListeners}from"../../lib/events.js";import{CONFIG_PLUGIN}from"../../../const.js";import{categoryContent}from"../../../database/categories.js";import{postContent}from"../../../database/posts.js";export const adminModule=buildModule({pluginId:CONFIG_PLUGIN.pluginId,name:"admin",routes:[],modules:[buildContentAdminModule({pluginId:CONFIG_PLUGIN.pluginId,contentTypes:[categoryContent,postContent]})],events:blogLegacyEventListeners});
@@ -0,0 +1,2 @@
1
+ export declare const blogApiPlugin: () => import("@vitnode/core/api/lib/plugin").BuildPluginApiReturn;
2
+ //# sourceMappingURL=config.api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.api.d.ts","sourceRoot":"","sources":["../../src/config.api.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,aAAa,mEAYtB,CAAC"}
@@ -0,0 +1 @@
1
+ import{buildApiPlugin}from"@vitnode/core/api/lib/plugin";import{buildContentPublicModule}from"@vitnode/core/content/server";import{adminModule}from"./api/modules/admin/admin.module.js";import{CONFIG_PLUGIN}from"./const.js";import{categoryContent}from"./database/categories.js";import{postContent}from"./database/posts.js";export const blogApiPlugin=()=>buildApiPlugin({pluginId:CONFIG_PLUGIN.pluginId,modules:[adminModule,buildContentPublicModule({pluginId:CONFIG_PLUGIN.pluginId,contentTypes:[categoryContent,postContent]})]});
@@ -0,0 +1,2 @@
1
+ export declare const blogPlugin: () => import("@vitnode/core/lib/plugin").BuildPluginReturn<"@vitnode/blog">;
2
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.tsx"],"names":[],"mappings":"AA0BA,eAAO,MAAM,UAAU,6EAInB,CAAC"}
@@ -0,0 +1 @@
1
+ import{buildPlugin}from"@vitnode/core/lib/plugin";import{adminContent}from"./admin/content.js";import messages from"./locales/index.js";export const blogPlugin=()=>buildPlugin({...adminContent,messages});
@@ -0,0 +1,4 @@
1
+ export declare const CONFIG_PLUGIN: {
2
+ pluginId: "@vitnode/blog";
3
+ };
4
+ //# sourceMappingURL=const.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../src/const.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;CAEzB,CAAC"}
@@ -0,0 +1 @@
1
+ export const CONFIG_PLUGIN={pluginId:"@vitnode/blog"};
@@ -0,0 +1,5 @@
1
+ export declare const blogCategoryContentType: import("@vitnode/core/content").ContentTypeDefinition<"blog.category", {
2
+ name: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
3
+ color: import("@vitnode/core/content").ContentTextField<false, true, undefined, false>;
4
+ }, false, never, false, false, false, false, false, true, false>;
5
+ //# sourceMappingURL=category.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"category.d.ts","sourceRoot":"","sources":["../../../src/content/category.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,uBAAuB;;;gEAwClC,CAAC"}
@@ -0,0 +1 @@
1
+ import{defineContentType,field}from"@vitnode/core/content";export const blogCategoryContentType=defineContentType({id:"blog.category",tableName:"blog_categories",localization:{enabled:true,defaultLocale:"en",fallback:"default"},fields:{name:field.text({localized:true,required:true,minLength:1,maxLength:100}),color:field.text({maxLength:50,nullable:true})},admin:{permissionModule:"categories",path:"blog/categories",colorField:"color",titleField:"name",create:{mode:"dialog"},edit:{mode:"dialog"},list:{columns:["name","color","updatedAt"]}}});
@@ -0,0 +1,10 @@
1
+ export declare const blogPostContentType: import("@vitnode/core/content").ContentTypeDefinition<"blog.post", {
2
+ categoryId: import("@vitnode/core/content").ContentRelationField<false, false, true, false, false>;
3
+ authorId: import("@vitnode/core/content").ContentUserField<false, false, true, true>;
4
+ title: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
5
+ friendlyUrl: import("@vitnode/core/content").ContentSlugField<"title", true>;
6
+ content: import("@vitnode/core/content").ContentTextareaField<true, false, undefined, true>;
7
+ coverImage: import("@vitnode/core/content/types").ContentFileField<false, true, false, false>;
8
+ coverImageAlt: import("@vitnode/core/content").ContentTextField<false, true, undefined, true>;
9
+ }, true, "id" | "publishedAt" | "categoryId" | "title" | "friendlyUrl" | "content" | "coverImage" | "coverImageAlt", true, true, true, true, true, true, true>;
10
+ //# sourceMappingURL=post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../src/content/post.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,mBAAmB;;;;;;;;8JAoP9B,CAAC"}
@@ -0,0 +1 @@
1
+ import{defineContentType,field}from"@vitnode/core/content";import{blogCategoryContentType}from"./category.js";export const blogPostContentType=defineContentType({id:"blog.post",tableName:"blog_posts",localization:{enabled:true,defaultLocale:"en",fallback:"default"},publication:{enabled:true},editorial:{enabled:true,revisions:{retention:20},preview:{enabled:true,expiresInMinutes:30},scheduling:{enabled:true}},fields:{categoryId:field.relation({min:1,multiple:true,onDelete:"restrict",target:()=>blogCategoryContentType}),authorId:field.user({min:1,multiple:true,ordered:true}),title:field.text({localized:true,required:true,minLength:3,maxLength:255}),friendlyUrl:field.slug({localized:true,maxLength:255,source:"title"}),content:field.textarea({localized:true,required:true}),coverImage:field.file({maxBytes:5*1024*1024,allowedExtensions:[".jpg",".jpeg",".png",".webp",".avif"],allowedMimeTypes:["image/jpeg","image/png","image/webp","image/avif"]}),coverImageAlt:field.text({localized:true,nullable:true,maxLength:255})},publicApi:{enabled:true,path:"blog",fields:["id","title","friendlyUrl","content","categoryId","coverImage","coverImageAlt","publishedAt"],searchableFields:["title","content"],orderableFields:["publishedAt"],filterableFields:["categoryId","friendlyUrl"],defaultOrderBy:"publishedAt",defaultOrder:"desc"},search:{enabled:true,titleField:"title",contentFields:["title","content"],pathTemplate:"/{locale}/blog/{slug}"},delivery:{enabled:true,redirects:{enabled:true},seo:{titleField:"title",descriptionField:"content"},sitemap:{enabled:true,changeFrequency:"weekly",priority:.7},hreflang:{xDefault:"defaultLocale"}},indexes:[{on:["status","createdAt"]}],admin:{permissionModule:"posts",path:"blog/articles",titleField:"title",create:{mode:"page"},edit:{mode:"page"},list:{columns:["title","coverImage","status","publishedAt","updatedAt"]}}});
@@ -0,0 +1,11 @@
1
+ export declare const categoryContent: import("@vitnode/core/content/server").ContentModel<import("@vitnode/core/content").ContentTypeDefinition<"blog.category", {
2
+ name: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
3
+ color: import("@vitnode/core/content").ContentTextField<false, true, undefined, false>;
4
+ }, false, never, false, false, false, false, false, true, false>>;
5
+ export declare const blog_categories: import("@vitnode/core/content/server").ContentTable<string, import("@vitnode/core/content/server/types").ContentStorageFields<{
6
+ color: import("@vitnode/core/content").ContentTextField<false, true, undefined, false>;
7
+ }>, false, false>;
8
+ export declare const blog_categories_translations: import("@vitnode/core/content/server").ContentTranslationTable<string, {} & {
9
+ name: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
10
+ }, false> | null;
11
+ //# sourceMappingURL=categories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../../src/database/categories.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe;;;iEAA8C,CAAC;AAK3E,eAAO,MAAM,eAAe;;iBAAwB,CAAC;AACrD,eAAO,MAAM,4BAA4B;;gBAAmC,CAAC"}
@@ -0,0 +1 @@
1
+ import{createContentModel}from"@vitnode/core/content/server";import{blogCategoryContentType}from"../content/category.js";export const categoryContent=createContentModel(blogCategoryContentType);export const blog_categories=categoryContent.table;export const blog_categories_translations=categoryContent.translationTable;
@@ -0,0 +1,23 @@
1
+ export declare const postContent: import("@vitnode/core/content/server").ContentModel<import("@vitnode/core/content").ContentTypeDefinition<"blog.post", {
2
+ categoryId: import("@vitnode/core/content").ContentRelationField<false, false, true, false, false>;
3
+ authorId: import("@vitnode/core/content").ContentUserField<false, false, true, true>;
4
+ title: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
5
+ friendlyUrl: import("@vitnode/core/content").ContentSlugField<"title", true>;
6
+ content: import("@vitnode/core/content").ContentTextareaField<true, false, undefined, true>;
7
+ coverImage: import("@vitnode/core/content/types").ContentFileField<false, true, false, false>;
8
+ coverImageAlt: import("@vitnode/core/content").ContentTextField<false, true, undefined, true>;
9
+ }, true, "id" | "publishedAt" | "categoryId" | "title" | "friendlyUrl" | "content" | "coverImage" | "coverImageAlt", true, true, true, true, true, true, true>>;
10
+ export declare const blog_posts: import("@vitnode/core/content/server").ContentTable<string, import("@vitnode/core/content/server/types").ContentStorageFields<{
11
+ categoryId: import("@vitnode/core/content").ContentRelationField<false, false, true, false, false>;
12
+ authorId: import("@vitnode/core/content").ContentUserField<false, false, true, true>;
13
+ coverImage: import("@vitnode/core/content/types").ContentFileField<false, true, false, false>;
14
+ }>, true, true>;
15
+ export declare const blog_posts_translations: import("@vitnode/core/content/server").ContentTranslationTable<string, {} & {
16
+ title: import("@vitnode/core/content").ContentTextField<true, false, undefined, true>;
17
+ friendlyUrl: import("@vitnode/core/content").ContentSlugField<"title", true>;
18
+ content: import("@vitnode/core/content").ContentTextareaField<true, false, undefined, true>;
19
+ coverImageAlt: import("@vitnode/core/content").ContentTextField<false, true, undefined, true>;
20
+ }, true> | null;
21
+ export declare const blog_posts_category_id: import("@vitnode/core/content/server/types").ContentJunctionTable;
22
+ export declare const blog_posts_author_id: import("@vitnode/core/content/server/types").ContentJunctionTable;
23
+ //# sourceMappingURL=posts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posts.d.ts","sourceRoot":"","sources":["../../../src/database/posts.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW;;;;;;;;+JAEtB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;eAAoB,CAAC;AAC5C,eAAO,MAAM,uBAAuB;;;;;eAA+B,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mEACc,CAAC;AAClD,eAAO,MAAM,oBAAoB,mEACc,CAAC"}
@@ -0,0 +1 @@
1
+ import{createContentModel}from"@vitnode/core/content/server";import{blogPostContentType}from"../content/post.js";import{blog_categories}from"./categories.js";export const postContent=createContentModel(blogPostContentType,{references:{categoryId:()=>blog_categories.id}});export const blog_posts=postContent.table;export const blog_posts_translations=postContent.translationTable;export const blog_posts_category_id=postContent.advancedTables.junctions.categoryId;export const blog_posts_author_id=postContent.advancedTables.junctions.authorId;
@@ -0,0 +1,23 @@
1
+ import { type DefaultTemplateEmailProps } from "@vitnode/core/emails/default-template";
2
+ declare function TestTemplateEmail({ user, ...props }: DefaultTemplateEmailProps): import("react").JSX.Element | null;
3
+ declare namespace TestTemplateEmail {
4
+ var PreviewProps: {
5
+ children: string;
6
+ templateProps: {
7
+ metadata: {
8
+ title: string;
9
+ shortTitle: string;
10
+ url: string;
11
+ };
12
+ logo: {
13
+ src: string;
14
+ };
15
+ };
16
+ i18n: {
17
+ messages: {};
18
+ locale: string;
19
+ };
20
+ };
21
+ }
22
+ export default TestTemplateEmail;
23
+ //# sourceMappingURL=test-template.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1 @@
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]})})}
@@ -0,0 +1,44 @@
1
+ @import "tailwindcss";
2
+
3
+ @custom-variant dark (&:is(.dark *));
4
+
5
+ @import "tw-animate-css";
6
+
7
+ @theme inline {
8
+ --radius-sm: calc(var(--radius) - 4px);
9
+ --radius-md: calc(var(--radius) - 2px);
10
+ --radius-lg: var(--radius);
11
+ --radius-xl: calc(var(--radius) + 4px);
12
+ --color-background: var(--background);
13
+ --color-foreground: var(--foreground);
14
+ --color-card: var(--card);
15
+ --color-card-foreground: var(--card-foreground);
16
+ --color-popover: var(--popover);
17
+ --color-popover-foreground: var(--popover-foreground);
18
+ --color-primary: var(--primary);
19
+ --color-primary-foreground: var(--primary-foreground);
20
+ --color-secondary: var(--secondary);
21
+ --color-secondary-foreground: var(--secondary-foreground);
22
+ --color-muted: var(--muted);
23
+ --color-muted-foreground: var(--muted-foreground);
24
+ --color-accent: var(--accent);
25
+ --color-accent-foreground: var(--accent-foreground);
26
+ --color-destructive: var(--destructive);
27
+ --color-warn: var(--warn);
28
+ --color-border: var(--border);
29
+ --color-input: var(--input);
30
+ --color-ring: var(--ring);
31
+ --color-chart-1: var(--chart-1);
32
+ --color-chart-2: var(--chart-2);
33
+ --color-chart-3: var(--chart-3);
34
+ --color-chart-4: var(--chart-4);
35
+ --color-chart-5: var(--chart-5);
36
+ --color-sidebar: var(--sidebar);
37
+ --color-sidebar-foreground: var(--sidebar-foreground);
38
+ --color-sidebar-primary: var(--sidebar-primary);
39
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
40
+ --color-sidebar-accent: var(--sidebar-accent);
41
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
42
+ --color-sidebar-border: var(--sidebar-border);
43
+ --color-sidebar-ring: var(--sidebar-ring);
44
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "@vitnode/blog": {
3
+ "title": "Blog",
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": {
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",
28
+ "color": "Color",
29
+ "updatedAt": "Updated"
30
+ }
31
+ }
32
+ },
33
+ "admin": {
34
+ "article": {
35
+ "content": {
36
+ "label": "Content"
37
+ },
38
+ "form": {
39
+ "publish": "Publish",
40
+ "cover": {
41
+ "title": "Cover image"
42
+ },
43
+ "settings": {
44
+ "title": "Article settings"
45
+ }
46
+ }
47
+ },
48
+ "category": {
49
+ "color": {
50
+ "label": "Color",
51
+ "desc": "Shown next to the category in lists.",
52
+ "none": "No color"
53
+ }
54
+ }
55
+ }
56
+ },
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",
64
+ "@vitnode/blog:categories": "Categories",
65
+ "@vitnode/blog:categories:can_view": "View categories list",
66
+ "@vitnode/blog:categories:can_create": "Create categories",
67
+ "@vitnode/blog:categories:can_edit": "Edit categories",
68
+ "@vitnode/blog:categories:can_delete": "Delete categories"
69
+ }
@@ -0,0 +1,4 @@
1
+ import type { LocaleMessagesMap } from "@vitnode/core/lib/i18n/types";
2
+ declare const messages: LocaleMessagesMap;
3
+ export default messages;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/locales/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAMtE,QAAA,MAAM,QAAQ,EAAE,iBAGf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1 @@
1
+ const messages={en:async()=>await import("./en.json",{with:{type:"json"}}),pl:async()=>await import("./pl.json",{with:{type:"json"}})};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
+ }
@@ -0,0 +1,4 @@
1
+ import type { ItemAutoFormComponentProps } from "@vitnode/core/components/form/auto-form";
2
+ import React from "react";
3
+ export declare const BlogArticleEditorField: (props: ItemAutoFormComponentProps) => React.JSX.Element;
4
+ //# sourceMappingURL=editor-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-field.d.ts","sourceRoot":"","sources":["../../../../../src/views/admin/article/editor-field.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAG1F,OAAO,KAAK,MAAM,OAAO,CAAC;AA8B1B,eAAO,MAAM,sBAAsB,GAAI,OAAO,0BAA0B,sBAQvE,CAAC"}
@@ -0,0 +1 @@
1
+ "use client";import{jsx as _jsx}from"react/jsx-runtime";import{Loader}from"@vitnode/core/components/ui/loader";import React from"react";import{useTranslations}from"use-intl";const AutoFormEditor=React.lazy(async()=>await import("@vitnode/core/components/form/fields/editor").then(mod=>({default:mod.AutoFormEditor})));export const BlogArticleEditorField=props=>{const t=useTranslations("@vitnode/blog.admin.article");return _jsx(React.Suspense,{fallback:_jsx(Loader,{}),children:_jsx(AutoFormEditor,{label:t("content.label"),...props})})};
@@ -0,0 +1,3 @@
1
+ import type { ContentFormLayoutProps } from "@vitnode/core/lib/plugin";
2
+ export declare const BlogArticleFormLayout: ({ mode }: ContentFormLayoutProps) => import("react").JSX.Element;
3
+ //# sourceMappingURL=form-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-layout.d.ts","sourceRoot":"","sources":["../../../../../src/views/admin/article/form-layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAcvE,eAAO,MAAM,qBAAqB,GAAI,UAAU,sBAAsB,gCAsCrE,CAAC"}
@@ -0,0 +1 @@
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{ContentFormActions,ContentFormField,ContentFormHeader,ContentFormLayoutGrid,ContentFormMain,ContentFormSection,ContentFormSidebar,ContentFormStatus}from"@vitnode/core/content/admin-form";import{useTranslations}from"use-intl";export const BlogArticleFormLayout=({mode})=>{const t=useTranslations("@vitnode/blog.admin.article.form");return _jsxs(_Fragment,{children:[_jsx(ContentFormHeader,{children:_jsx(ContentFormActions,{})}),_jsxs(ContentFormLayoutGrid,{children:[_jsx(ContentFormMain,{children:_jsxs(ContentFormSection,{children:[_jsx(ContentFormField,{name:"title"}),_jsx(ContentFormField,{name:"friendlyUrl"}),_jsx(ContentFormField,{name:"content"})]})}),_jsxs(ContentFormSidebar,{children:[mode==="edit"?_jsx(ContentFormSection,{title:t("publish"),children:_jsx(ContentFormStatus,{})}):null,_jsxs(ContentFormSection,{title:t("cover.title"),children:[_jsx(ContentFormField,{name:"coverImage"}),_jsx(ContentFormField,{name:"coverImageAlt"})]}),_jsxs(ContentFormSection,{title:t("settings.title"),children:[_jsx(ContentFormField,{name:"categoryId"}),_jsx(ContentFormField,{name:"authorId"})]})]})]})]})};
@@ -0,0 +1,4 @@
1
+ import type { ContentCellProps } from "@vitnode/core/lib/plugin";
2
+ import type { blogCategoryContentType } from "../../../content/category";
3
+ export declare const BlogCategoryColorCell: ({ row, }: ContentCellProps<typeof blogCategoryContentType>) => import("react").JSX.Element;
4
+ //# sourceMappingURL=color-cell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-cell.d.ts","sourceRoot":"","sources":["../../../../../src/views/admin/category/color-cell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,eAAO,MAAM,qBAAqB,GAAI,UAEnC,gBAAgB,CAAC,OAAO,uBAAuB,CAAC,gCAkBlD,CAAC"}
@@ -0,0 +1 @@
1
+ "use client";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useTranslations}from"use-intl";export const BlogCategoryColorCell=({row})=>{const t=useTranslations("@vitnode/blog.admin.category");const color=row.color;if(!color){return _jsx("span",{className:"text-muted-foreground",children:t("color.none")})}return _jsxs("div",{className:"flex items-center gap-2",children:[_jsx("span",{"aria-hidden":true,className:"size-4 shrink-0 rounded-full border",style:{backgroundColor:color}}),_jsx("span",{className:"text-muted-foreground truncate text-sm",children:color})]})};
@@ -0,0 +1,3 @@
1
+ import type { ItemAutoFormComponentProps } from "@vitnode/core/components/form/auto-form";
2
+ export declare const BlogCategoryColorField: (props: ItemAutoFormComponentProps) => import("react").JSX.Element;
3
+ //# sourceMappingURL=color-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-field.d.ts","sourceRoot":"","sources":["../../../../../src/views/admin/category/color-field.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAK1F,eAAO,MAAM,sBAAsB,GAAI,OAAO,0BAA0B,gCAWvE,CAAC"}
@@ -0,0 +1 @@
1
+ "use client";import{jsx as _jsx}from"react/jsx-runtime";import{AutoFormColor}from"@vitnode/core/components/form/fields/color";import{useTranslations}from"use-intl";export const BlogCategoryColorField=props=>{const t=useTranslations("@vitnode/blog.admin.category");return _jsx(AutoFormColor,{allowRemoveColor:true,description:t("color.desc"),label:t("color.label"),...props})};
@@ -0,0 +1,3 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
3
+ //# sourceMappingURL=vitest.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":";AAIA,wBAgBG"}
@@ -0,0 +1,19 @@
1
+ import eslintVitNode from "@vitnode/config/eslint";
2
+ import eslintVitNodeReact from "@vitnode/config/eslint.react";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname } from "node:path";
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+
8
+ export default [
9
+ ...eslintVitNode,
10
+ ...eslintVitNodeReact,
11
+ {
12
+ languageOptions: {
13
+ parserOptions: {
14
+ project: "./tsconfig.json",
15
+ tsconfigRootDir: __dirname,
16
+ },
17
+ },
18
+ },
19
+ ];
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@vitnode/blog",
3
+ "version": "0.0.1-canary.0",
4
+ "description": "Blog plugin for VitNode, providing a blogging platform on Hono.js.",
5
+ "author": "VitNode Team",
6
+ "license": "MIT",
7
+ "homepage": "https://vitnode.com",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/aXenDeveloper/vitnode.git",
11
+ "directory": "plugins/blog"
12
+ },
13
+ "keywords": [
14
+ "vitnode",
15
+ "react",
16
+ "hono.js",
17
+ "typescript",
18
+ "blog"
19
+ ],
20
+ "type": "module",
21
+ "exports": {
22
+ "./locales/*.json": "./src/locales/*.json",
23
+ "./*": {
24
+ "import": "./dist/src/*.js",
25
+ "types": "./dist/src/*.d.ts",
26
+ "default": "./dist/src/*.js"
27
+ }
28
+ },
29
+ "dependencies": {
30
+ "@hono/zod-openapi": "^1.5.1",
31
+ "ai": "^7.0.37",
32
+ "drizzle-kit": "1.0.0-rc.4",
33
+ "drizzle-orm": "1.0.0-rc.4",
34
+ "hono": "^4.12.31",
35
+ "lucide-react": "^1.25.0",
36
+ "react": "^19.2.8",
37
+ "react-dom": "^19.2.8",
38
+ "react-email": "^6.9.0",
39
+ "react-hook-form": "^7.82.0",
40
+ "sonner": "^2.0.7",
41
+ "use-intl": "^4.13.7",
42
+ "zod": "^4.4.3",
43
+ "@vitnode/core": "0.0.1-canary.0"
44
+ },
45
+ "devDependencies": {
46
+ "@react-email/ui": "^6.9.0",
47
+ "@swc/cli": "^0.8.1",
48
+ "@swc/core": "^1.15.46",
49
+ "@types/react": "^19.2.17",
50
+ "@types/react-dom": "^19.2.3",
51
+ "@vitejs/plugin-react": "^6.0.4",
52
+ "eslint": "^10.7.0",
53
+ "jsdom": "^29.1.1",
54
+ "postgres": "^3.4.9",
55
+ "tsc-alias": "^1.9.1",
56
+ "typescript": "^6.0.3",
57
+ "vitest": "^4.1.10",
58
+ "@vitnode/config": "0.0.1-canary.0"
59
+ },
60
+ "scripts": {
61
+ "build:plugins": "vitnode build",
62
+ "dev": "vitnode dev",
63
+ "dev:email": "email dev --dir src/emails",
64
+ "lint": "eslint .",
65
+ "lint:fix": "eslint . --fix",
66
+ "test": "vitest run",
67
+ "test:watch": "vitest",
68
+ "test:types": "vitest run --typecheck.only"
69
+ }
70
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "@vitnode/blog": {
3
+ "title": "Blog",
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": {
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",
28
+ "color": "Color",
29
+ "updatedAt": "Updated"
30
+ }
31
+ }
32
+ },
33
+ "admin": {
34
+ "article": {
35
+ "content": {
36
+ "label": "Content"
37
+ },
38
+ "form": {
39
+ "publish": "Publish",
40
+ "cover": {
41
+ "title": "Cover image"
42
+ },
43
+ "settings": {
44
+ "title": "Article settings"
45
+ }
46
+ }
47
+ },
48
+ "category": {
49
+ "color": {
50
+ "label": "Color",
51
+ "desc": "Shown next to the category in lists.",
52
+ "none": "No color"
53
+ }
54
+ }
55
+ }
56
+ },
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",
64
+ "@vitnode/blog:categories": "Categories",
65
+ "@vitnode/blog:categories:can_view": "View categories list",
66
+ "@vitnode/blog:categories:can_create": "Create categories",
67
+ "@vitnode/blog:categories:can_edit": "Edit categories",
68
+ "@vitnode/blog:categories:can_delete": "Delete categories"
69
+ }
@@ -0,0 +1,12 @@
1
+ import type { LocaleMessagesMap } from "@vitnode/core/lib/i18n/types";
2
+
3
+ /**
4
+ * Every language this plugin ships. Add a file next to this one and a line
5
+ * here to add another; apps pick it up with no copy step.
6
+ */
7
+ const messages: LocaleMessagesMap = {
8
+ en: async () => await import("./en.json", { with: { type: "json" } }),
9
+ pl: async () => await import("./pl.json", { with: { type: "json" } }),
10
+ };
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
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.json",
4
+ "exclude": [
5
+ "node_modules",
6
+ "**/*.test.ts",
7
+ "**/*.test.tsx",
8
+ "**/*.test-d.ts"
9
+ ]
10
+ }