@newcms/database 0.2.0 → 0.3.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.
- package/dist/index.cjs +155 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CommentRepository: () => CommentRepository,
|
|
33
34
|
MetaRepository: () => MetaRepository,
|
|
34
35
|
ObjectCache: () => ObjectCache,
|
|
35
36
|
OptionsRepository: () => OptionsRepository,
|
|
@@ -1500,8 +1501,162 @@ var RevisionRepository = class {
|
|
|
1500
1501
|
return false;
|
|
1501
1502
|
}
|
|
1502
1503
|
};
|
|
1504
|
+
|
|
1505
|
+
// src/repositories/comment-repository.ts
|
|
1506
|
+
var import_drizzle_orm6 = require("drizzle-orm");
|
|
1507
|
+
var CommentRepository = class {
|
|
1508
|
+
constructor(db) {
|
|
1509
|
+
this.db = db;
|
|
1510
|
+
const metaCols = {
|
|
1511
|
+
metaId: commentmeta.metaId,
|
|
1512
|
+
objectId: commentmeta.commentId,
|
|
1513
|
+
metaKey: commentmeta.metaKey,
|
|
1514
|
+
metaValue: commentmeta.metaValue,
|
|
1515
|
+
metaValueJson: commentmeta.metaValueJson
|
|
1516
|
+
};
|
|
1517
|
+
const colNames = {
|
|
1518
|
+
table: "commentmeta",
|
|
1519
|
+
sql: { metaId: "meta_id", objectId: "comment_id", metaKey: "meta_key", metaValue: "meta_value", metaValueJson: "meta_value_json" },
|
|
1520
|
+
ts: { metaId: "metaId", objectId: "commentId", metaKey: "metaKey", metaValue: "metaValue", metaValueJson: "metaValueJson" }
|
|
1521
|
+
};
|
|
1522
|
+
this.meta = new MetaRepository(db, commentmeta, metaCols, colNames);
|
|
1523
|
+
}
|
|
1524
|
+
db;
|
|
1525
|
+
meta;
|
|
1526
|
+
async create(input) {
|
|
1527
|
+
const now = /* @__PURE__ */ new Date();
|
|
1528
|
+
const [row] = await this.db.insert(comments).values({
|
|
1529
|
+
commentPostId: input.commentPostId,
|
|
1530
|
+
commentAuthor: input.commentAuthor,
|
|
1531
|
+
commentAuthorEmail: input.commentAuthorEmail ?? "",
|
|
1532
|
+
commentAuthorUrl: input.commentAuthorUrl ?? "",
|
|
1533
|
+
commentAuthorIp: input.commentAuthorIp ?? "",
|
|
1534
|
+
commentContent: input.commentContent,
|
|
1535
|
+
commentType: input.commentType ?? "comment",
|
|
1536
|
+
commentParent: input.commentParent ?? 0,
|
|
1537
|
+
userId: input.userId ?? 0,
|
|
1538
|
+
commentApproved: input.commentApproved ?? "1",
|
|
1539
|
+
commentDate: now,
|
|
1540
|
+
commentDateGmt: now
|
|
1541
|
+
}).returning();
|
|
1542
|
+
await this.updatePostCommentCount(input.commentPostId);
|
|
1543
|
+
return row;
|
|
1544
|
+
}
|
|
1545
|
+
async getById(id) {
|
|
1546
|
+
const rows = await this.db.select().from(comments).where((0, import_drizzle_orm6.eq)(comments.commentId, id)).limit(1);
|
|
1547
|
+
return rows[0];
|
|
1548
|
+
}
|
|
1549
|
+
async getByPost(postId, status) {
|
|
1550
|
+
const conditions = [(0, import_drizzle_orm6.eq)(comments.commentPostId, postId)];
|
|
1551
|
+
if (status) conditions.push((0, import_drizzle_orm6.eq)(comments.commentApproved, status));
|
|
1552
|
+
return await this.db.select().from(comments).where((0, import_drizzle_orm6.and)(...conditions)).orderBy(comments.commentDate);
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Get threaded comments — returns flat list, client builds the tree
|
|
1556
|
+
* using commentParent references.
|
|
1557
|
+
*/
|
|
1558
|
+
async getThreaded(postId, _depth = 5) {
|
|
1559
|
+
return this.getByPost(postId, "1");
|
|
1560
|
+
}
|
|
1561
|
+
async approve(id) {
|
|
1562
|
+
const comment = await this.getById(id);
|
|
1563
|
+
if (!comment) return false;
|
|
1564
|
+
await this.db.update(comments).set({ commentApproved: "1" }).where((0, import_drizzle_orm6.eq)(comments.commentId, id));
|
|
1565
|
+
await this.updatePostCommentCount(comment.commentPostId);
|
|
1566
|
+
return true;
|
|
1567
|
+
}
|
|
1568
|
+
async unapprove(id) {
|
|
1569
|
+
const comment = await this.getById(id);
|
|
1570
|
+
if (!comment) return false;
|
|
1571
|
+
await this.db.update(comments).set({ commentApproved: "0" }).where((0, import_drizzle_orm6.eq)(comments.commentId, id));
|
|
1572
|
+
await this.updatePostCommentCount(comment.commentPostId);
|
|
1573
|
+
return true;
|
|
1574
|
+
}
|
|
1575
|
+
async spam(id) {
|
|
1576
|
+
const comment = await this.getById(id);
|
|
1577
|
+
if (!comment) return false;
|
|
1578
|
+
await this.db.update(comments).set({ commentApproved: "spam" }).where((0, import_drizzle_orm6.eq)(comments.commentId, id));
|
|
1579
|
+
await this.updatePostCommentCount(comment.commentPostId);
|
|
1580
|
+
return true;
|
|
1581
|
+
}
|
|
1582
|
+
async trash(id) {
|
|
1583
|
+
const comment = await this.getById(id);
|
|
1584
|
+
if (!comment) return false;
|
|
1585
|
+
await this.meta.update(id, "_trash_status", comment.commentApproved);
|
|
1586
|
+
await this.db.update(comments).set({ commentApproved: "trash" }).where((0, import_drizzle_orm6.eq)(comments.commentId, id));
|
|
1587
|
+
await this.updatePostCommentCount(comment.commentPostId);
|
|
1588
|
+
return true;
|
|
1589
|
+
}
|
|
1590
|
+
async deletePermanently(id) {
|
|
1591
|
+
const comment = await this.getById(id);
|
|
1592
|
+
if (!comment) return false;
|
|
1593
|
+
await this.meta.deleteAllForObject(id);
|
|
1594
|
+
const result = await this.db.delete(comments).where((0, import_drizzle_orm6.eq)(comments.commentId, id)).returning({ commentId: comments.commentId });
|
|
1595
|
+
if (result.length > 0) await this.updatePostCommentCount(comment.commentPostId);
|
|
1596
|
+
return result.length > 0;
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Check moderation rules before approving a comment.
|
|
1600
|
+
*/
|
|
1601
|
+
moderate(content, _authorEmail, rules) {
|
|
1602
|
+
const lower = content.toLowerCase();
|
|
1603
|
+
if (rules.blockedWords) {
|
|
1604
|
+
for (const word of rules.blockedWords) {
|
|
1605
|
+
if (lower.includes(word.toLowerCase())) return "spam";
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
if (rules.moderationWords) {
|
|
1609
|
+
for (const word of rules.moderationWords) {
|
|
1610
|
+
if (lower.includes(word.toLowerCase())) return "hold";
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
if (rules.maxLinks !== void 0) {
|
|
1614
|
+
const linkCount = (content.match(/https?:\/\//g) ?? []).length;
|
|
1615
|
+
if (linkCount > rules.maxLinks) return "hold";
|
|
1616
|
+
}
|
|
1617
|
+
return "approve";
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Check for duplicate comment.
|
|
1621
|
+
*/
|
|
1622
|
+
async isDuplicate(postId, authorEmail, content) {
|
|
1623
|
+
const rows = await this.db.select({ commentId: comments.commentId }).from(comments).where(
|
|
1624
|
+
(0, import_drizzle_orm6.and)(
|
|
1625
|
+
(0, import_drizzle_orm6.eq)(comments.commentPostId, postId),
|
|
1626
|
+
(0, import_drizzle_orm6.eq)(comments.commentAuthorEmail, authorEmail),
|
|
1627
|
+
(0, import_drizzle_orm6.eq)(comments.commentContent, content)
|
|
1628
|
+
)
|
|
1629
|
+
).limit(1);
|
|
1630
|
+
return rows.length > 0;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Check flood protection — has user commented too recently?
|
|
1634
|
+
*/
|
|
1635
|
+
async isFlooding(authorIp, floodSeconds) {
|
|
1636
|
+
const cutoff = new Date(Date.now() - floodSeconds * 1e3);
|
|
1637
|
+
const rows = await this.db.select({ commentId: comments.commentId }).from(comments).where(
|
|
1638
|
+
(0, import_drizzle_orm6.and)(
|
|
1639
|
+
(0, import_drizzle_orm6.eq)(comments.commentAuthorIp, authorIp),
|
|
1640
|
+
import_drizzle_orm6.sql`${comments.commentDate} > ${cutoff}`
|
|
1641
|
+
)
|
|
1642
|
+
).limit(1);
|
|
1643
|
+
return rows.length > 0;
|
|
1644
|
+
}
|
|
1645
|
+
async countByStatus(postId) {
|
|
1646
|
+
const conditions = postId !== void 0 ? [(0, import_drizzle_orm6.eq)(comments.commentPostId, postId)] : [];
|
|
1647
|
+
const rows = await this.db.select({ status: comments.commentApproved, count: import_drizzle_orm6.sql`count(*)::int` }).from(comments).where(conditions.length > 0 ? (0, import_drizzle_orm6.and)(...conditions) : void 0).groupBy(comments.commentApproved);
|
|
1648
|
+
const result = {};
|
|
1649
|
+
for (const row of rows) result[row.status] = row.count;
|
|
1650
|
+
return result;
|
|
1651
|
+
}
|
|
1652
|
+
async updatePostCommentCount(postId) {
|
|
1653
|
+
const [result] = await this.db.select({ count: import_drizzle_orm6.sql`count(*)::int` }).from(comments).where((0, import_drizzle_orm6.and)((0, import_drizzle_orm6.eq)(comments.commentPostId, postId), (0, import_drizzle_orm6.eq)(comments.commentApproved, "1")));
|
|
1654
|
+
await this.db.update(posts).set({ commentCount: result.count }).where((0, import_drizzle_orm6.eq)(posts.id, postId));
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1503
1657
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1504
1658
|
0 && (module.exports = {
|
|
1659
|
+
CommentRepository,
|
|
1505
1660
|
MetaRepository,
|
|
1506
1661
|
ObjectCache,
|
|
1507
1662
|
OptionsRepository,
|