@infuro/cms-core 1.0.26 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.cjs +3997 -2719
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +3 -1
- package/dist/admin.d.ts +3 -1
- package/dist/admin.js +3801 -2522
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +1922 -136
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1928 -129
- package/dist/api.js.map +1 -1
- package/dist/cli.cjs +23 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +23 -5
- package/dist/cli.js.map +1 -1
- package/dist/{index--vbixpxE.d.cts → index-CI6J9dxr.d.cts} +3 -1
- package/dist/{index-DMJgi-fy.d.ts → index-CMJZ5Fpr.d.ts} +3 -1
- package/dist/index.cjs +3538 -1057
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +333 -4
- package/dist/index.d.ts +333 -4
- package/dist/index.js +3499 -1031
- package/dist/index.js.map +1 -1
- package/dist/migrations/1775500000000-RssFeedsAndArticles.ts +68 -0
- package/dist/migrations/1775600000000-BlogSocialMediaContent.ts +48 -0
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-
|
|
2
|
-
export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as ChatPublicConfig, f as CmsApiHandlerConfig, g as CmsGetter, h as CrudHandlerOptions, D as DashboardStatsConfig, i as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, j as FormBySlugConfig, G as GetPublicSettingsGroupConfig, k as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, L as LlmAgentKnowledgeApiConfig, l as LlmAgentValidationRulesJson, P as ParsedLlmAgentValidation, m as SetPasswordConfig, n as SettingsApiConfig, o as SocialLinkItem, p as StorefrontApiConfig, q as StorefrontOtpFlags, U as UploadHandlerConfig, r as UserAuthApiConfig, s as UserAvatarConfig, t as UserProfileConfig, u as UsersApiConfig, v as createAnalyticsHandlers, w as createBlogBySlugHandler, x as createChangePasswordHandler, y as createCmsApiHandler, z as createCrudByIdHandler, H as createCrudHandler, J as createDashboardStatsHandler, K as createEcommerceAnalyticsHandler, M as createForgotPasswordHandler, N as createFormBySlugHandler, Q as createInviteAcceptHandler, R as createLlmAgentKnowledgeHandlers, V as createMediaZipExtractHandler, W as createSetPasswordHandler, X as createSettingsApiHandlers, Y as createStorefrontApiHandler, Z as createUploadHandler, _ as createUserAuthApiRouter, $ as createUserAvatarHandler, a0 as createUserProfileHandler, a1 as createUsersApiHandlers, a2 as getCompanyDetailsFromSettings, a3 as getPublicSettingsGroup, a4 as mergeEmailLayoutCompanyDetails, a5 as mergeGuardrailsIntoSystemPrompt, a6 as parseLlmAgentValidationRules, a7 as
|
|
1
|
+
import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-CMJZ5Fpr.js';
|
|
2
|
+
export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as ChatPublicConfig, f as CmsApiHandlerConfig, g as CmsGetter, h as CrudHandlerOptions, D as DashboardStatsConfig, i as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, j as FormBySlugConfig, G as GetPublicSettingsGroupConfig, k as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, L as LlmAgentKnowledgeApiConfig, l as LlmAgentValidationRulesJson, P as ParsedLlmAgentValidation, m as SetPasswordConfig, n as SettingsApiConfig, o as SocialLinkItem, p as StorefrontApiConfig, q as StorefrontOtpFlags, U as UploadHandlerConfig, r as UserAuthApiConfig, s as UserAvatarConfig, t as UserProfileConfig, u as UsersApiConfig, v as createAnalyticsHandlers, w as createBlogBySlugHandler, x as createChangePasswordHandler, y as createCmsApiHandler, z as createCrudByIdHandler, H as createCrudHandler, J as createDashboardStatsHandler, K as createEcommerceAnalyticsHandler, M as createForgotPasswordHandler, N as createFormBySlugHandler, Q as createInviteAcceptHandler, R as createLlmAgentKnowledgeHandlers, V as createMediaZipExtractHandler, W as createSetPasswordHandler, X as createSettingsApiHandlers, Y as createStorefrontApiHandler, Z as createUploadHandler, _ as createUserAuthApiRouter, $ as createUserAvatarHandler, a0 as createUserProfileHandler, a1 as createUsersApiHandlers, a2 as getCompanyDetailsFromSettings, a3 as getPublicSettingsGroup, a4 as mergeEmailLayoutCompanyDetails, a5 as mergeGuardrailsIntoSystemPrompt, a6 as parseLlmAgentValidationRules, a7 as simpleDecrypt, a8 as simpleEncrypt, a9 as validateUserMessageAgainstAgentRules, aa as validateUserMessageAgainstStructuredRules } from './index-CMJZ5Fpr.js';
|
|
3
3
|
import { ClassValue } from 'clsx';
|
|
4
4
|
import * as typeorm from 'typeorm';
|
|
5
5
|
import { DataSource, EntityTarget, ObjectLiteral } from 'typeorm';
|
|
6
6
|
import { Metadata } from 'next';
|
|
7
7
|
import { N as NavbarConfig, F as FooterConfig } from './types-D34wmivy.js';
|
|
8
|
-
|
|
8
|
+
import { E as EntityCrudAction } from './helpers-dlrF_49e.js';
|
|
9
|
+
export { A as ADMIN_GROUP_NAME, a as AuthHelpers, b as EntityPermissionFlags, G as GetSession, O as OPEN_ENDPOINTS, P as PERMISSION_REQUIRED_ENDPOINTS, R as RBAC_ADMIN_ONLY_ENTITIES, S as SessionUser, c as canManageRoles, d as createAuthHelpers, g as getPermissionableEntityKeys, e as getRequiredPermission, h as hasEntityPermission, i as isOpenEndpoint, f as isPublicMethod, j as isSuperAdminGroupName, p as permissionRowsToRecord, s as sessionHasEntityAccess } from './helpers-dlrF_49e.js';
|
|
9
10
|
export { AuthorizeOtpInput, CmsMiddlewareConfig, NextAuthOptionsConfig, NextAuthUser, createCmsMiddleware, defaultPublicApiMethods, getNextAuthOptions, seedAdministratorPermissions } from './auth.js';
|
|
10
11
|
export { A as AdminNavItem, D as DEFAULT_ADMIN_NAV } from './config-DJ5CmQvS.js';
|
|
11
12
|
import 'next-auth';
|
|
@@ -689,6 +690,300 @@ declare function assertCaptchaOk(getCms: (() => Promise<{
|
|
|
689
690
|
getPlugin: (name: string) => unknown;
|
|
690
691
|
}>) | undefined, body: Record<string, unknown>, req: Request, json: JsonResponse): Promise<Response | null>;
|
|
691
692
|
|
|
693
|
+
interface LatestArticleFromFeed {
|
|
694
|
+
title?: string;
|
|
695
|
+
link?: string;
|
|
696
|
+
/** Short excerpt */
|
|
697
|
+
summary?: string;
|
|
698
|
+
/** Full content if available */
|
|
699
|
+
content?: string;
|
|
700
|
+
date: Date;
|
|
701
|
+
creator?: string;
|
|
702
|
+
categories?: string[];
|
|
703
|
+
}
|
|
704
|
+
type RssItem = {
|
|
705
|
+
title?: string;
|
|
706
|
+
link?: string;
|
|
707
|
+
pubDate?: string;
|
|
708
|
+
isoDate?: string;
|
|
709
|
+
contentSnippet?: string;
|
|
710
|
+
summary?: string;
|
|
711
|
+
description?: string;
|
|
712
|
+
content?: string;
|
|
713
|
+
creator?: string;
|
|
714
|
+
'dc:creator'?: string;
|
|
715
|
+
'content:encoded'?: string;
|
|
716
|
+
categories?: string[];
|
|
717
|
+
guid?: string | {
|
|
718
|
+
_: string;
|
|
719
|
+
};
|
|
720
|
+
};
|
|
721
|
+
declare function getRssArticleSummaryFromItem(item: RssItem): {
|
|
722
|
+
summary: string;
|
|
723
|
+
fullContent: string;
|
|
724
|
+
};
|
|
725
|
+
type BlogGeneratorDraftParseMode = 'json' | 'plaintext';
|
|
726
|
+
interface BlogGeneratorSeoDraft {
|
|
727
|
+
title: string | null;
|
|
728
|
+
description: string | null;
|
|
729
|
+
keywords: string | null;
|
|
730
|
+
ogTitle: string | null;
|
|
731
|
+
ogDescription: string | null;
|
|
732
|
+
}
|
|
733
|
+
interface BlogGeneratorBlogDraft {
|
|
734
|
+
title: string;
|
|
735
|
+
slug?: string;
|
|
736
|
+
markdown: string;
|
|
737
|
+
/** Short plain-text copy for social (e.g. LinkedIn); optional until social LLM step runs. */
|
|
738
|
+
socialMediaContent?: string | null;
|
|
739
|
+
categoryName: string | null;
|
|
740
|
+
seo: BlogGeneratorSeoDraft;
|
|
741
|
+
/** Suggested tag labels (may not exist in CMS yet). */
|
|
742
|
+
tags: string[];
|
|
743
|
+
parseMode: BlogGeneratorDraftParseMode;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Parses the LLM reply: prefers a single JSON object with blogTitle, blogHtml/blogMarkdown/content, categoryName, seo, …
|
|
747
|
+
* Falls back to treating the entire string as HTML (or legacy markdown) if JSON parsing fails.
|
|
748
|
+
*/
|
|
749
|
+
declare function parseBlogGeneratorAgentContent(raw: string): BlogGeneratorBlogDraft;
|
|
750
|
+
declare function resolveBlogCategoryIdByName(needle: string | null | undefined, rows: readonly {
|
|
751
|
+
id: number;
|
|
752
|
+
name: string;
|
|
753
|
+
}[]): {
|
|
754
|
+
categoryId: number | null;
|
|
755
|
+
matched: boolean;
|
|
756
|
+
};
|
|
757
|
+
/**
|
|
758
|
+
* Minimal user payload: latest item per feed only (system prompt carries writing rules).
|
|
759
|
+
*/
|
|
760
|
+
declare function buildRssUserPromptFromFeeds(feeds: ReadonlyArray<{
|
|
761
|
+
rssUrl: string;
|
|
762
|
+
article: LatestArticleFromFeed;
|
|
763
|
+
}>): string;
|
|
764
|
+
/**
|
|
765
|
+
* User message for the metadata-only LLM step (one blog at a time).
|
|
766
|
+
*/
|
|
767
|
+
declare function buildBlogMetadataUserPrompt(opts: {
|
|
768
|
+
title: string;
|
|
769
|
+
markdown: string;
|
|
770
|
+
categoryNames: readonly string[];
|
|
771
|
+
tagNames: readonly string[];
|
|
772
|
+
}): string;
|
|
773
|
+
/** Parses JSON from the metadata-enrichment LLM (category, slug, seo, tags). */
|
|
774
|
+
declare function parseBlogMetadataEnrichmentJson(raw: string): {
|
|
775
|
+
categoryName: string | null;
|
|
776
|
+
blogSlug: string | null;
|
|
777
|
+
seo: BlogGeneratorSeoDraft;
|
|
778
|
+
tags: string[];
|
|
779
|
+
};
|
|
780
|
+
/**
|
|
781
|
+
* Parses LLM output: prefers HTML + {@link BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR} for multiple articles.
|
|
782
|
+
* If the model still returns legacy JSON with `blogHtml` / `blogMarkdown`, returns a single draft from that object.
|
|
783
|
+
*/
|
|
784
|
+
declare function parseBlogGeneratorModelOutput(raw: string): BlogGeneratorBlogDraft[];
|
|
785
|
+
declare class BlogGeneratorService {
|
|
786
|
+
readonly version: "1.0.0";
|
|
787
|
+
getLatestArticleFromFeed(rssUrl: string): Promise<LatestArticleFromFeed | null>;
|
|
788
|
+
/** Defaults for the Blog Generator Agent (admin can override per request). */
|
|
789
|
+
getAgentDefaults(): {
|
|
790
|
+
agentName: string;
|
|
791
|
+
systemInstruction: string;
|
|
792
|
+
validationRules: string;
|
|
793
|
+
};
|
|
794
|
+
/**
|
|
795
|
+
* Second LLM call: one draft at a time — category, URL slug, SEO fields, tags (JSON).
|
|
796
|
+
*/
|
|
797
|
+
private enrichBlogDraftWithLlmMetadata;
|
|
798
|
+
/**
|
|
799
|
+
* Third LLM call: one draft at a time — short social copy (JSON `{ socialMediaContent }`).
|
|
800
|
+
*/
|
|
801
|
+
private enrichBlogDraftWithLlmSocial;
|
|
802
|
+
/**
|
|
803
|
+
* Fetches the latest item for each RSS URL, then calls {@link LlmServiceInterface.chatAgent}.
|
|
804
|
+
* `userPrompt` is only per-feed source material; rules live in the system prompt.
|
|
805
|
+
* Expects HTML article fragment(s), optionally separated by {@link BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR}.
|
|
806
|
+
*/
|
|
807
|
+
generateBlogMarkdownFromRss(params: {
|
|
808
|
+
llm: LlmServiceInterface;
|
|
809
|
+
/** Single feed (legacy). */
|
|
810
|
+
rssUrl?: string;
|
|
811
|
+
/** One or more feeds; latest item per URL is sent together. Prefer this when multiple URLs. */
|
|
812
|
+
rssUrls?: readonly string[];
|
|
813
|
+
systemInstruction?: string;
|
|
814
|
+
validationRules?: string;
|
|
815
|
+
/** Reserved for future structured output; writer does not inject categories into the user prompt. */
|
|
816
|
+
categoryNamesHint?: readonly string[];
|
|
817
|
+
/** Names of non-deleted tags in CMS (hint for reuse). */
|
|
818
|
+
tagNamesHint?: readonly string[];
|
|
819
|
+
/** From optional `llm_agents` row (slug `blog-generator`): model / sampling for the writer step. */
|
|
820
|
+
llmAgentChatOptions?: Pick<LlmAgentOptions, 'model' | 'temperature' | 'max_tokens'>;
|
|
821
|
+
/** Optional overrides for the metadata step; defaults live in `blog-generator-metadata-defaults.ts`. */
|
|
822
|
+
metadataSystemInstruction?: string;
|
|
823
|
+
metadataValidationRules?: string;
|
|
824
|
+
/** From optional `llm_agents` row (slug `blog-generator-metadata`): model / sampling for metadata only. */
|
|
825
|
+
metadataLlmAgentChatOptions?: Pick<LlmAgentOptions, 'model' | 'temperature' | 'max_tokens'>;
|
|
826
|
+
/** Optional overrides for the social-summary step; defaults in `blog-generator-social-defaults.ts`. */
|
|
827
|
+
socialSystemInstruction?: string;
|
|
828
|
+
socialValidationRules?: string;
|
|
829
|
+
/** From optional `llm_agents` row (slug `blog-generator-social`): model / sampling for social copy only. */
|
|
830
|
+
socialLlmAgentChatOptions?: Pick<LlmAgentOptions, 'model' | 'temperature' | 'max_tokens'>;
|
|
831
|
+
}): Promise<{
|
|
832
|
+
agentName: string;
|
|
833
|
+
feedArticles: Array<{
|
|
834
|
+
rssUrl: string;
|
|
835
|
+
article: LatestArticleFromFeed;
|
|
836
|
+
}>;
|
|
837
|
+
/** First feed's article (backward compatibility). */
|
|
838
|
+
article: LatestArticleFromFeed;
|
|
839
|
+
/** Raw model reply (HTML body per defaults; legacy markdown or JSON still parsed when present). */
|
|
840
|
+
blogMarkdown: string;
|
|
841
|
+
blogDrafts: BlogGeneratorBlogDraft[];
|
|
842
|
+
/** Same as first draft; backward compatibility. */
|
|
843
|
+
blogDraft: BlogGeneratorBlogDraft;
|
|
844
|
+
}>;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/** Stable display name; not persisted as DB agent row in v1. */
|
|
848
|
+
declare const BLOG_GENERATOR_AGENT_NAME = "Blog Generator Agent";
|
|
849
|
+
/**
|
|
850
|
+
* Optional `llm_agents` row: when present and enabled, model / temperature / max_tokens
|
|
851
|
+
* are applied to {@link LlmServiceInterface.chatAgent} (system + user content still come from blog generator defaults / UI).
|
|
852
|
+
*/
|
|
853
|
+
declare const BLOG_GENERATOR_LLM_AGENT_SLUG = "blog-generator";
|
|
854
|
+
/** Line that separates multiple articles in the model reply (HTML or legacy markdown; must match parser and prompts). */
|
|
855
|
+
declare const BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR = "---BLOG_GENERATOR_NEXT---";
|
|
856
|
+
declare const BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION = "You are a professional financial and business content writer.\n\nYour task is to generate completely original, high-quality blog article(s) from the latest RSS-derived source material in the user message (one block per feed). The user message is factual input only.\n\nIMPORTANT RULES:\n\n1. NEVER copy the RSS article directly.\n2. Rewrite the information into a fresh, human-like article.\n3. Expand the topic with professional insights and explanations.\n4. Maintain a natural editorial tone.\n5. Make the article SEO-friendly.\n6. Use engaging headings and subheadings.\n7. Avoid robotic AI phrasing.\n8. Do not mention that the content came from RSS or feeds.\n9. Preserve factual accuracy from the source material.\n10. The output should feel like a professionally written industry blog.\n\nMULTIPLE FEEDS:\n- If several feeds are provided, compare them: if they largely cover the same story or overlap heavily, produce ONE cohesive article.\n- If they cover clearly different topics or distinct stories, produce MULTIPLE articles (one per distinct story).\n- You may also produce one synthesis plus a short separate angle when that best serves the reader\u2014use your judgment.\n\nWRITING STYLE:\n- Professional\n- Clear\n- Informative\n- Business-focused\n- Human sounding\n- Modern editorial style\n\nARTICLE STRUCTURE (each article \u2014 express in HTML):\n1. Engaging introduction\n2. Industry context\n3. Main developments\n4. Key implications\n5. Expert/business analysis\n6. Conclusion\n\nHTML STRUCTURE (STRICT \u2014 each article must be valid, semantic HTML only):\n- Output HTML only. Do not use Markdown (no # headings, no **bold**, no `code fences`).\n- Wrap each complete article in a single root: <article class=\"blog-post\"> ... </article>\n- Inside <article>, use this outline:\n - <header><h1 class=\"blog-post-title\">\u2026main title\u2026</h1></header> (exactly one h1 per article)\n - <section class=\"blog-post-body\"> for all following content\n - Use <h2> and <h3> for section and subsection titles (never skip levels: h1 \u2192 h2 \u2192 h3).\n - Use <p> for paragraphs; keep paragraphs focused (avoid huge unbroken text).\n - Use <ul>/<ol> with <li> for lists where appropriate.\n - Use <strong> and <em> for emphasis sparingly; use <blockquote> only when quoting or callouts fit.\n- Do not include <html>, <head>, <body>, or document-level wrappers \u2014 only the fragment(s) described above.\n- Do not use <script>, <style>, <iframe>, or inline event handlers. Avoid inline style=\"\" except when essential for accessibility (prefer none).\n- Escape angle brackets in body text if you must mention markup; keep output safe for embedding in a CMS.\n\nCONTENT REQUIREMENTS:\n- Minimum 800 words per article unless source material is very small.\n- Add context around industry trends where appropriate.\n- Explain why the topic matters.\n- Include practical implications for businesses/professionals.\n\nIF RSS CONTENT IS LIMITED:\n- Expand intelligently using general industry knowledge.\n- Keep the article relevant to the original topic.\n- Do not invent fake facts or statistics.\n\nOUTPUT FORMAT (STRICT \u2014 HTML only):\n- Return ONLY the article HTML fragment(s). No JSON, no preamble or postscript (\"Here is your article\u2026\"), no markdown.\n- If you output more than one article, output multiple <article class=\"blog-post\">\u2026</article> blocks in sequence, and between articles put a single line containing exactly this (and nothing else on that line):\n---BLOG_GENERATOR_NEXT---\n- If you output a single article, use one <article> only and do not use that separator line.";
|
|
857
|
+
/**
|
|
858
|
+
* JSON so {@link parseLlmAgentValidationRules} can attach guardrails and allow long source payloads.
|
|
859
|
+
* Edit in the admin UI if needed; defaults match product intent.
|
|
860
|
+
*/
|
|
861
|
+
declare const BLOG_GENERATOR_DEFAULT_VALIDATION_RULES: string;
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Second-step LLM: classifies one finished HTML blog body into CMS fields (category, SEO, tags).
|
|
865
|
+
*
|
|
866
|
+
* Optional `llm_agents` row: slug {@link BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG} — when present and enabled,
|
|
867
|
+
* model / temperature / max_tokens apply to this call only (writer step uses `blog-generator`).
|
|
868
|
+
*
|
|
869
|
+
* To change how metadata is produced, edit the constants in this file (system instruction + validation JSON).
|
|
870
|
+
* No admin UI override is wired yet; add request body fields in `cms-api-handler` if you need runtime overrides later.
|
|
871
|
+
*/
|
|
872
|
+
declare const BLOG_METADATA_ENRICHER_AGENT_NAME = "Blog Generator Metadata";
|
|
873
|
+
/** `llm_agents.slug` for routing model/temperature for the metadata-only chat step. */
|
|
874
|
+
declare const BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG = "blog-generator-metadata";
|
|
875
|
+
declare const BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION = "You are a careful CMS metadata assistant for a publishing system.\n\nYou receive ONE complete blog post as HTML (title is usually in <h1 class=\"blog-post-title\"> or the first <h1>). Your job is to propose structured fields so an editor can save the post: category, URL slug, SEO block, and topical tags.\n\nRULES:\n1. Read the whole article and infer the primary topic and audience.\n2. categoryName must be EXACTLY one string from AVAILABLE_BLOG_CATEGORIES in the user message, or \"\" if none fit.\n3. blogSlug: lowercase kebab-case, ASCII letters/digits/hyphens only, no leading/trailing hyphens, max ~80 chars. Derive from the main topic or title.\n4. seo.title: concise meta title (~50\u201360 characters when reasonable).\n5. seo.description: meta description (~150\u2013160 characters when reasonable), plain text.\n6. seo.keywords: comma-separated phrases, no stuffing.\n7. seo.ogTitle / seo.ogDescription: may mirror title/description or be slightly adapted for social.\n8. tags: 4\u201310 short labels (1\u20133 words each). Prefer exact matches from EXISTING_TAG_NAMES when they truly apply; otherwise invent precise new labels (they may be created in the CMS later).\n9. Do not invent statistics, quotes, or URLs not implied by the article.\n10. Output JSON only \u2014 no markdown outside the JSON, no commentary.\n\nOUTPUT FORMAT (STRICT):\nReturn a single JSON object only. Do not wrap it in a markdown code fence.\n\n{\n \"categoryName\": \"string \u2014 exact match from list or empty string\",\n \"blogSlug\": \"string \u2014 url-safe kebab-case\",\n \"seo\": {\n \"title\": \"string or empty\",\n \"description\": \"string or empty\",\n \"keywords\": \"string or empty\",\n \"ogTitle\": \"string or empty\",\n \"ogDescription\": \"string or empty\"\n },\n \"tags\": [\"tag-one\", \"tag-two\"]\n}";
|
|
876
|
+
declare const BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES: string;
|
|
877
|
+
|
|
878
|
+
interface BlogGeneratorPluginConfig {
|
|
879
|
+
/** Set to false to skip registering the plugin. */
|
|
880
|
+
enabled?: boolean;
|
|
881
|
+
}
|
|
882
|
+
declare function blogGeneratorPlugin(config?: BlogGeneratorPluginConfig): CmsPlugin<BlogGeneratorService | undefined>;
|
|
883
|
+
|
|
884
|
+
interface SocialMediaApiConfig {
|
|
885
|
+
dataSource: DataSource;
|
|
886
|
+
entityMap: EntityMap$2;
|
|
887
|
+
json: (body: unknown, init?: {
|
|
888
|
+
status?: number;
|
|
889
|
+
}) => Response;
|
|
890
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
891
|
+
requireEntityPermission: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
892
|
+
encryptionKey?: string;
|
|
893
|
+
/** Used to resolve relative cover image URLs (e.g. https://mysite.com). */
|
|
894
|
+
publicSiteUrl?: string;
|
|
895
|
+
/**
|
|
896
|
+
* When true (default), `console.info` / `console.warn` lines are emitted for LinkedIn blog publish
|
|
897
|
+
* (text vs image path, sizes, errors). Set false or `CMS_LINKEDIN_PUBLISH_LOG=0` to silence.
|
|
898
|
+
*/
|
|
899
|
+
linkedInPublishLogging?: boolean;
|
|
900
|
+
}
|
|
901
|
+
declare function createSocialMediaHandlers(config: SocialMediaApiConfig): {
|
|
902
|
+
getLinkedInStatus(req: Request): Promise<Response>;
|
|
903
|
+
syncLinkedInProfile(req: Request): Promise<Response>;
|
|
904
|
+
publishBlogToLinkedIn(req: Request, blogId: number): Promise<Response>;
|
|
905
|
+
getFacebookStatus(req: Request): Promise<Response>;
|
|
906
|
+
publishBlogToFacebook(req: Request, blogId: number): Promise<Response>;
|
|
907
|
+
/**
|
|
908
|
+
* POST JSON `{ appId, appSecret, userAccessToken }`. Calls Graph `GET /me/accounts` with the user token.
|
|
909
|
+
* App ID and secret are validated but not used yet (reserved for future token flows).
|
|
910
|
+
* Persist credentials via Plugins → Save: `meta_app_id` (public), `meta_app_secret` and `meta_user_access_token` (encrypted).
|
|
911
|
+
*/
|
|
912
|
+
fetchFacebookManagedPages(req: Request): Promise<Response>;
|
|
913
|
+
};
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Meta (Facebook) Graph API helpers (server-side). Uses fetch — no SDK.
|
|
917
|
+
* @see https://developers.facebook.com/docs/graph-api/reference/user/accounts
|
|
918
|
+
*/
|
|
919
|
+
type FacebookPageAccount = {
|
|
920
|
+
access_token?: string;
|
|
921
|
+
category?: string;
|
|
922
|
+
name?: string;
|
|
923
|
+
id?: string;
|
|
924
|
+
/** Graph may return additional fields */
|
|
925
|
+
[key: string]: unknown;
|
|
926
|
+
};
|
|
927
|
+
type FacebookMeAccountsResponse = {
|
|
928
|
+
data?: FacebookPageAccount[];
|
|
929
|
+
paging?: Record<string, unknown>;
|
|
930
|
+
error?: {
|
|
931
|
+
message?: string;
|
|
932
|
+
type?: string;
|
|
933
|
+
code?: number;
|
|
934
|
+
fbtrace_id?: string;
|
|
935
|
+
};
|
|
936
|
+
};
|
|
937
|
+
/**
|
|
938
|
+
* Lists Facebook Pages the user manages (page access tokens + metadata).
|
|
939
|
+
* Requires a User access token with `pages_show_list` or equivalent page permissions.
|
|
940
|
+
*/
|
|
941
|
+
declare function metaFetchUserManagedPages(userAccessToken: string): Promise<FacebookMeAccountsResponse>;
|
|
942
|
+
type MetaGraphMutationResponse = {
|
|
943
|
+
id?: string;
|
|
944
|
+
post_id?: string;
|
|
945
|
+
error?: {
|
|
946
|
+
message?: string;
|
|
947
|
+
type?: string;
|
|
948
|
+
code?: number;
|
|
949
|
+
fbtrace_id?: string;
|
|
950
|
+
};
|
|
951
|
+
};
|
|
952
|
+
/** Resolves the long-lived page access token for a Page ID from `/me/accounts` data. */
|
|
953
|
+
declare function metaResolvePageAccessToken(accounts: FacebookMeAccountsResponse, pageId: string): string | null;
|
|
954
|
+
/**
|
|
955
|
+
* Upload a photo to a Page timeline (multipart).
|
|
956
|
+
* @see https://developers.facebook.com/docs/graph-api/reference/page/photos#Creating
|
|
957
|
+
*/
|
|
958
|
+
declare function metaPostPagePhoto(opts: {
|
|
959
|
+
pageId: string;
|
|
960
|
+
pageAccessToken: string;
|
|
961
|
+
imageBuffer: Buffer;
|
|
962
|
+
contentType: string;
|
|
963
|
+
caption: string;
|
|
964
|
+
}): Promise<MetaGraphMutationResponse>;
|
|
965
|
+
/**
|
|
966
|
+
* Publish a text-only post to the Page feed (when no JPEG/PNG image is available).
|
|
967
|
+
* @see https://developers.facebook.com/docs/graph-api/reference/page/feed#Creating
|
|
968
|
+
*/
|
|
969
|
+
declare function metaPostPageFeed(opts: {
|
|
970
|
+
pageId: string;
|
|
971
|
+
pageAccessToken: string;
|
|
972
|
+
message: string;
|
|
973
|
+
}): Promise<MetaGraphMutationResponse>;
|
|
974
|
+
|
|
975
|
+
interface SocialMediaPluginConfig {
|
|
976
|
+
/** Set to false to skip registering the plugin instance (API routes still work if wired in the app handler). */
|
|
977
|
+
enabled?: boolean;
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* Optional CMS plugin instance for `getPlugin('social_media')`.
|
|
981
|
+
* LinkedIn publishing is implemented in {@link createSocialMediaHandlers} and mounted from the CMS API handler.
|
|
982
|
+
*/
|
|
983
|
+
declare function socialMediaPlugin(config?: SocialMediaPluginConfig): CmsPlugin<{
|
|
984
|
+
name: string;
|
|
985
|
+
} | undefined>;
|
|
986
|
+
|
|
692
987
|
declare function cn(...inputs: ClassValue[]): string;
|
|
693
988
|
declare function generateSlug(title: string): string;
|
|
694
989
|
declare function validateSlug(slug: string): boolean;
|
|
@@ -990,6 +1285,8 @@ declare class Blog {
|
|
|
990
1285
|
id: number;
|
|
991
1286
|
title: string;
|
|
992
1287
|
content: string;
|
|
1288
|
+
/** LLM-generated short copy for social (e.g. LinkedIn); preferred over scraping full HTML for share text. */
|
|
1289
|
+
socialMediaContent: string | null;
|
|
993
1290
|
coverImage: string | null;
|
|
994
1291
|
authorId: number;
|
|
995
1292
|
categoryId: number | null;
|
|
@@ -1527,7 +1824,39 @@ declare class LlmAgent {
|
|
|
1527
1824
|
/** Partial {@link LlmAgentOptions} for merging with `userPrompt` / `history` / `context`. */
|
|
1528
1825
|
declare function llmAgentToChatAgentOptions(agent: LlmAgent): Pick<LlmAgentOptions, 'systemPrompt' | 'model' | 'temperature' | 'max_tokens'>;
|
|
1529
1826
|
|
|
1827
|
+
declare class RssArticle {
|
|
1828
|
+
id: string;
|
|
1829
|
+
rssFeedId: string;
|
|
1830
|
+
rssFeed: RssFeed;
|
|
1831
|
+
externalId: string | null;
|
|
1832
|
+
title: string;
|
|
1833
|
+
articleUrl: string;
|
|
1834
|
+
summary: string | null;
|
|
1835
|
+
content: string | null;
|
|
1836
|
+
author: string | null;
|
|
1837
|
+
publishedAt: Date | null;
|
|
1838
|
+
imageUrl: string | null;
|
|
1839
|
+
rawData: Record<string, unknown> | null;
|
|
1840
|
+
contentHash: string | null;
|
|
1841
|
+
isProcessed: boolean;
|
|
1842
|
+
createdAt: Date;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
declare class RssFeed {
|
|
1846
|
+
id: string;
|
|
1847
|
+
name: string;
|
|
1848
|
+
rssUrl: string;
|
|
1849
|
+
websiteUrl: string | null;
|
|
1850
|
+
isActive: boolean;
|
|
1851
|
+
fetchFrequencyMinutes: number;
|
|
1852
|
+
lastFetchedAt: Date | null;
|
|
1853
|
+
lastArticleDate: Date | null;
|
|
1854
|
+
articles: RssArticle[];
|
|
1855
|
+
createdAt: Date;
|
|
1856
|
+
updatedAt: Date;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1530
1859
|
/** Map API resource segment (e.g. "blogs", "form_submissions") to entity. Used by CRUD handler. */
|
|
1531
1860
|
declare const CMS_ENTITY_MAP: Record<string, EntityTarget<typeorm.ObjectLiteral>>;
|
|
1532
1861
|
|
|
1533
|
-
export { Address, type AnalyticsPluginConfig, Attribute, Blog, Brand, CMS_ENTITY_MAP, type CachePluginConfig, type CacheService, type CaptchaProviderId, type CaptchaPublicConfig, CaptchaService, type CaptchaVerifyResult, Cart, CartItem, Category, ChatConversation, ChatMessage, type CmsApp, type CmsPlugin, Collection, Comment, CompanyDetails, Config, Contact, type CreateCmsAppOptions, type DataSourceManager, type ERPPluginConfig, type ERPPluginInstance, ERPSubmissionService, type EmailData, type EmailJobPayload, type EmailPluginConfig, EmailService, type EmailServiceInterface, EmailTemplateName, EmailTemplateResult, EntityMap$2 as EntityMap, type ErpContactSyncInput, type ErpCreateContactPayload, type ErpJobPayload, type ErpPaidOrderDataSource, type ErpPaidOrderEntityMap, type ExtraPublicWriteRule, Form, FormField, FormSubmission, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, type LlmAgentOptions, type LlmChatOptions, type LlmEmbeddingProvider, type LlmMessage, type LlmPluginConfig, LlmService, type LlmServiceEmbedOptions, type LlmServiceInterface, type LocalStoragePluginConfig, type Logger, Media, MessageTemplate, Order, OrderItem, type OrderPlacedEmailPayload, OrderPlacedLineItem, OtpChallenge, type OtpChannel, type OtpPurpose, Page, PasswordResetToken, Payment, type PaymentIntent, type PaymentPluginConfig, type PaymentServiceInterface, Permission, type PipelineNames, type PluginContext, Product, ProductAttribute, ProductCategory, ProductTax, type PublicThemeSettingsPayload, type QueuePluginConfig, type QueueService, type RenderEmailOptions, type RenderedEmail, type S3StoragePluginConfig, Seo, type SeoLike, type SeoMetadataOverrides, type SmsJobPayload, type SmsPluginConfig, type SmsProviderChoice, type SmsProviderId, type SmsServiceConfig, type SmsServiceInterface, StorageService, Tag, Tax, TemplateContext, User, UserGroup, Wishlist, WishlistItem, ZIP_MIME_TYPES, allowRateLimit, analyticsPlugin, assertCaptchaOk, buildCaptchaPublicConfig, cachePlugin, captchaPlugin, cn, countRecentOtpSends, createCmsApp, createDataSourceManager, createOtpChallenge, emailPlugin, emailTemplates, erpPlugin, fetchSeoBySlug, formatDate, formatDateOnly, formatDateTime, generateNumericOtp, generateSlug, hashOtpCode, isZipMedia, joinRecipientsForSend, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, llmPlugin, loadPublicThemeSettings, localStoragePlugin, mergeSeoBySlug, normalizePhoneE164, parseEmailRecipientsFromConfig, parseHfInferenceEmbeddingBody, paymentPlugin, queueEmail, queueErp, queueErpCreateContactIfEnabled, queueErpPaidOrderForOrderId, queueOrderPlacedEmails, queuePlugin, queueSms, rateLimitCheckoutPost, rateLimitKeyForApiRequest, rateLimitPublicApiIfNeeded, registerEmailQueueProcessor, registerErpQueueProcessor, registerSmsQueueProcessor, relativePathFromMediaParentId, renderEmail, renderLayout, resolvePublicMetadata, s3StoragePlugin, sanitizeMediaFolderPath, sanitizeStorageSegment, seedDefaultAdmin, sendOrderPlacedEmailsAfterConfirmation, serializeEmailRecipients, shouldRateLimitPublicWrite, smsPlugin, truncateText, validateSlug, verifyAndConsumeOtpChallenge, verifyOtpCodeHash };
|
|
1862
|
+
export { Address, type AnalyticsPluginConfig, Attribute, BLOG_GENERATOR_AGENT_NAME, BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION, BLOG_GENERATOR_DEFAULT_VALIDATION_RULES, BLOG_GENERATOR_LLM_AGENT_SLUG, BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR, BLOG_METADATA_ENRICHER_AGENT_NAME, BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION, BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES, BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG, Blog, type BlogGeneratorBlogDraft, type BlogGeneratorDraftParseMode, type BlogGeneratorPluginConfig, type BlogGeneratorSeoDraft, BlogGeneratorService, Brand, CMS_ENTITY_MAP, type CachePluginConfig, type CacheService, type CaptchaProviderId, type CaptchaPublicConfig, CaptchaService, type CaptchaVerifyResult, Cart, CartItem, Category, ChatConversation, ChatMessage, type CmsApp, type CmsPlugin, Collection, Comment, CompanyDetails, Config, Contact, type CreateCmsAppOptions, type DataSourceManager, type ERPPluginConfig, type ERPPluginInstance, ERPSubmissionService, type EmailData, type EmailJobPayload, type EmailPluginConfig, EmailService, type EmailServiceInterface, EmailTemplateName, EmailTemplateResult, EntityCrudAction, EntityMap$2 as EntityMap, type ErpContactSyncInput, type ErpCreateContactPayload, type ErpJobPayload, type ErpPaidOrderDataSource, type ErpPaidOrderEntityMap, type ExtraPublicWriteRule, type FacebookMeAccountsResponse, type FacebookPageAccount, Form, FormField, FormSubmission, KnowledgeBaseChunk, KnowledgeBaseDocument, type LatestArticleFromFeed, LlmAgent, type LlmAgentOptions, type LlmChatOptions, type LlmEmbeddingProvider, type LlmMessage, type LlmPluginConfig, LlmService, type LlmServiceEmbedOptions, type LlmServiceInterface, type LocalStoragePluginConfig, type Logger, Media, MessageTemplate, type MetaGraphMutationResponse, Order, OrderItem, type OrderPlacedEmailPayload, OrderPlacedLineItem, OtpChallenge, type OtpChannel, type OtpPurpose, Page, PasswordResetToken, Payment, type PaymentIntent, type PaymentPluginConfig, type PaymentServiceInterface, Permission, type PipelineNames, type PluginContext, Product, ProductAttribute, ProductCategory, ProductTax, type PublicThemeSettingsPayload, type QueuePluginConfig, type QueueService, type RenderEmailOptions, type RenderedEmail, RssArticle, RssFeed, type S3StoragePluginConfig, Seo, type SeoLike, type SeoMetadataOverrides, type SmsJobPayload, type SmsPluginConfig, type SmsProviderChoice, type SmsProviderId, type SmsServiceConfig, type SmsServiceInterface, type SocialMediaPluginConfig, StorageService, Tag, Tax, TemplateContext, User, UserGroup, Wishlist, WishlistItem, ZIP_MIME_TYPES, allowRateLimit, analyticsPlugin, assertCaptchaOk, blogGeneratorPlugin, buildBlogMetadataUserPrompt, buildCaptchaPublicConfig, buildRssUserPromptFromFeeds, cachePlugin, captchaPlugin, cn, countRecentOtpSends, createCmsApp, createDataSourceManager, createOtpChallenge, createSocialMediaHandlers, emailPlugin, emailTemplates, erpPlugin, fetchSeoBySlug, formatDate, formatDateOnly, formatDateTime, generateNumericOtp, generateSlug, getRssArticleSummaryFromItem, hashOtpCode, isZipMedia, joinRecipientsForSend, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, llmPlugin, loadPublicThemeSettings, localStoragePlugin, mergeSeoBySlug, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, normalizePhoneE164, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseEmailRecipientsFromConfig, parseHfInferenceEmbeddingBody, paymentPlugin, queueEmail, queueErp, queueErpCreateContactIfEnabled, queueErpPaidOrderForOrderId, queueOrderPlacedEmails, queuePlugin, queueSms, rateLimitCheckoutPost, rateLimitKeyForApiRequest, rateLimitPublicApiIfNeeded, registerEmailQueueProcessor, registerErpQueueProcessor, registerSmsQueueProcessor, relativePathFromMediaParentId, renderEmail, renderLayout, resolveBlogCategoryIdByName, resolvePublicMetadata, s3StoragePlugin, sanitizeMediaFolderPath, sanitizeStorageSegment, seedDefaultAdmin, sendOrderPlacedEmailsAfterConfirmation, serializeEmailRecipients, shouldRateLimitPublicWrite, smsPlugin, socialMediaPlugin, truncateText, validateSlug, verifyAndConsumeOtpChallenge, verifyOtpCodeHash };
|