@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.
@@ -0,0 +1,68 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+
3
+ export class RssFeedsAndArticles1775500000000 implements MigrationInterface {
4
+ name = 'RssFeedsAndArticles1775500000000';
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS "pgcrypto"`);
8
+ await queryRunner.query(`
9
+ CREATE TABLE IF NOT EXISTS "rss_feeds" (
10
+ "id" uuid NOT NULL DEFAULT gen_random_uuid(),
11
+ "name" text NOT NULL,
12
+ "rssUrl" text NOT NULL,
13
+ "websiteUrl" text,
14
+ "isActive" boolean NOT NULL DEFAULT true,
15
+ "fetchFrequencyMinutes" integer NOT NULL DEFAULT 60,
16
+ "lastFetchedAt" TIMESTAMP,
17
+ "lastArticleDate" TIMESTAMP,
18
+ "createdAt" TIMESTAMP NOT NULL DEFAULT now(),
19
+ "updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
20
+ CONSTRAINT "PK_rss_feeds" PRIMARY KEY ("id")
21
+ )`);
22
+ await queryRunner.query(
23
+ `CREATE UNIQUE INDEX IF NOT EXISTS "UQ_rss_feeds_rssUrl" ON "rss_feeds" ("rssUrl")`
24
+ );
25
+
26
+ await queryRunner.query(`
27
+ CREATE TABLE IF NOT EXISTS "rss_articles" (
28
+ "id" uuid NOT NULL DEFAULT gen_random_uuid(),
29
+ "rssFeedId" uuid NOT NULL,
30
+ "externalId" text,
31
+ "title" text NOT NULL,
32
+ "articleUrl" text NOT NULL,
33
+ "summary" text,
34
+ "content" text,
35
+ "author" text,
36
+ "publishedAt" TIMESTAMP,
37
+ "imageUrl" text,
38
+ "rawData" jsonb,
39
+ "contentHash" text,
40
+ "isProcessed" boolean NOT NULL DEFAULT false,
41
+ "createdAt" TIMESTAMP NOT NULL DEFAULT now(),
42
+ CONSTRAINT "PK_rss_articles" PRIMARY KEY ("id")
43
+ )`);
44
+ await queryRunner.query(`
45
+ DO $$ BEGIN
46
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_rss_articles_feed') THEN
47
+ ALTER TABLE "rss_articles"
48
+ ADD CONSTRAINT "FK_rss_articles_feed"
49
+ FOREIGN KEY ("rssFeedId") REFERENCES "rss_feeds"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
50
+ END IF;
51
+ END $$;`);
52
+ await queryRunner.query(
53
+ `CREATE UNIQUE INDEX IF NOT EXISTS "UQ_rss_articles_feed_article_url" ON "rss_articles" ("rssFeedId", "articleUrl")`
54
+ );
55
+ await queryRunner.query(
56
+ `CREATE INDEX IF NOT EXISTS "IDX_rss_articles_feed" ON "rss_articles" ("rssFeedId")`
57
+ );
58
+ }
59
+
60
+ public async down(queryRunner: QueryRunner): Promise<void> {
61
+ await queryRunner.query(`DROP INDEX IF EXISTS "IDX_rss_articles_feed"`);
62
+ await queryRunner.query(`DROP INDEX IF EXISTS "UQ_rss_articles_feed_article_url"`);
63
+ await queryRunner.query(`ALTER TABLE "rss_articles" DROP CONSTRAINT IF EXISTS "FK_rss_articles_feed"`);
64
+ await queryRunner.query(`DROP TABLE IF EXISTS "rss_articles"`);
65
+ await queryRunner.query(`DROP INDEX IF EXISTS "UQ_rss_feeds_rssUrl"`);
66
+ await queryRunner.query(`DROP TABLE IF EXISTS "rss_feeds"`);
67
+ }
68
+ }
@@ -0,0 +1,48 @@
1
+ import type { MigrationInterface, QueryRunner } from 'typeorm';
2
+
3
+ const BLOG_SOCIAL_AGENT_NAME = 'Blog Generator (Social)';
4
+ const BLOG_SOCIAL_AGENT_SLUG = 'blog-generator-social';
5
+
6
+ export class BlogSocialMediaContent1775600000000 implements MigrationInterface {
7
+ name = 'BlogSocialMediaContent1775600000000';
8
+
9
+ public async up(queryRunner: QueryRunner): Promise<void> {
10
+ await queryRunner.query(`
11
+ ALTER TABLE "blogs"
12
+ ADD COLUMN IF NOT EXISTS "socialMediaContent" text
13
+ `);
14
+
15
+ const sys = `You are a social copywriter for LinkedIn-style posts.
16
+
17
+ You receive ONE blog post as HTML. Write a short plain-text post (roughly 600–1300 characters, max 2900) summarizing the article faithfully. Output JSON only: {"socialMediaContent":"..."} — no markdown fences.`;
18
+
19
+ const rules = JSON.stringify(
20
+ {
21
+ maxUserChars: 500000,
22
+ guardrails:
23
+ 'Reply with one valid JSON object only. Key: socialMediaContent (string, plain text).',
24
+ },
25
+ null,
26
+ 2
27
+ );
28
+
29
+ await queryRunner.query(
30
+ `
31
+ INSERT INTO "llm_agents" ("name", "slug", "system_instruction", "model", "temperature", "max_tokens", "validation_rules", "enabled", "createdAt", "updatedAt", "deleted")
32
+ SELECT $1::varchar, $2::varchar, $3::text, NULL, 0.4, 2048, $4::text, true, now(), now(), false
33
+ WHERE NOT EXISTS (
34
+ SELECT 1 FROM "llm_agents" a WHERE a."slug" = $2::varchar AND a."deleted" = false
35
+ )
36
+ `,
37
+ [BLOG_SOCIAL_AGENT_NAME, BLOG_SOCIAL_AGENT_SLUG, sys, rules]
38
+ );
39
+ }
40
+
41
+ public async down(queryRunner: QueryRunner): Promise<void> {
42
+ await queryRunner.query(
43
+ `DELETE FROM "llm_agents" WHERE "slug" = $1 AND "name" = $2`,
44
+ [BLOG_SOCIAL_AGENT_SLUG, BLOG_SOCIAL_AGENT_NAME]
45
+ );
46
+ await queryRunner.query(`ALTER TABLE "blogs" DROP COLUMN IF EXISTS "socialMediaContent"`);
47
+ }
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infuro/cms-core",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -122,6 +122,7 @@
122
122
  "razorpay": "^2.9.6",
123
123
  "react-chartjs-2": "^5.3.0",
124
124
  "reflect-metadata": "^0.2.2",
125
+ "rss-parser": "^3.13.0",
125
126
  "sonner": "^2.0.6",
126
127
  "stripe": "^20.4.1",
127
128
  "tailwind-merge": "^3.0.2",