powr-sdk-api 4.7.3 → 4.8.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.js CHANGED
@@ -23,7 +23,7 @@ const {
23
23
  executeTasks,
24
24
  executeTool,
25
25
  createTask,
26
- createActivityFeedItem
26
+ emitActivity
27
27
  } = require("./managers");
28
28
  const {
29
29
  verifyToken
@@ -45,6 +45,6 @@ module.exports = {
45
45
  executeTasks,
46
46
  executeTool,
47
47
  createTask,
48
- createActivityFeedItem,
48
+ emitActivity,
49
49
  getPowrDb
50
50
  };
@@ -8,55 +8,50 @@ const {
8
8
  } = require("mongodb");
9
9
 
10
10
  /**
11
- * Create a feed activity entry in the activities collection.
12
- * Used by host apps (e.g. Spriny) in-process and by POST /activities (feed shape).
11
+ * Emit an activity to PowrBase. Inserts one document into the activities collection.
12
+ * Does not send notification; an Atlas trigger on the collection handles that.
13
13
  *
14
- * @param {Object} params - action, userId, projectId?, targetType?, targetId?, metadata?, projectName?, projectSlug?
15
- * @returns {Promise<{ success: boolean, id?: string, message?: string }>}
14
+ * @param {Object} options
15
+ * @param {string} options.projectId - Project context (required)
16
+ * @param {string} options.action - e.g. "task_created", "task_assigned", "enquiry_converted"
17
+ * @param {string|ObjectId} options.userId - Who performed the action
18
+ * @param {string} [options.targetType] - e.g. "task", "project", "enquiry"
19
+ * @param {string|ObjectId} [options.targetId] - ID of the target entity
20
+ * @param {Object} [options.metadata] - Extra payload (e.g. recipientIds, title, body, url for notification)
21
+ * @returns {Promise<{ insertedId: ObjectId }>} The inserted document's _id
16
22
  */
17
- async function createActivityFeedItem(params) {
18
- try {
19
- const {
20
- action,
21
- userId,
22
- projectId,
23
- targetType,
24
- targetId,
25
- metadata = {},
26
- projectName,
27
- projectSlug
28
- } = params;
29
- if (!action || !userId) {
30
- return {
31
- success: false,
32
- message: "action and userId are required"
33
- };
34
- }
35
- const doc = {
36
- action,
37
- userId: new ObjectId(userId.toString()),
38
- projectId: projectId ? new ObjectId(projectId.toString()) : null,
39
- targetType: targetType || null,
40
- targetId: targetId ? new ObjectId(targetId.toString()) : null,
41
- metadata: metadata || {},
42
- projectName: projectName || null,
43
- projectSlug: projectSlug || null,
44
- createdAt: new Date()
45
- };
46
- const db = await getDb();
47
- const result = await db.collection("activities").insertOne(doc);
48
- return {
49
- success: true,
50
- id: result.insertedId.toString()
51
- };
52
- } catch (error) {
53
- console.error("createActivityFeedItem error:", error);
54
- return {
55
- success: false,
56
- message: error.message
57
- };
23
+ async function emitActivity(options) {
24
+ const {
25
+ projectId,
26
+ action,
27
+ userId,
28
+ targetType,
29
+ targetId,
30
+ metadata = {}
31
+ } = options;
32
+ if (!projectId || !action) {
33
+ throw new Error("emitActivity: projectId and action are required");
58
34
  }
35
+ const normalizeId = id => {
36
+ if (id == null) return null;
37
+ if (typeof id === "string" && ObjectId.isValid(id)) return new ObjectId(id);
38
+ return id;
39
+ };
40
+ const doc = {
41
+ projectId,
42
+ action,
43
+ userId: normalizeId(userId),
44
+ targetType: targetType || null,
45
+ targetId: normalizeId(targetId),
46
+ metadata,
47
+ createdAt: new Date()
48
+ };
49
+ const db = await getDb();
50
+ const result = await db.collection("activities").insertOne(doc);
51
+ return {
52
+ insertedId: result.insertedId
53
+ };
59
54
  }
60
55
  module.exports = {
61
- createActivityFeedItem
56
+ emitActivity
62
57
  };
@@ -3,9 +3,7 @@
3
3
  const functionsManager = require('./functions');
4
4
  const toolsManager = require('./tools');
5
5
  const scheduledTasksManager = require('./tasks');
6
- const {
7
- createActivityFeedItem
8
- } = require('./activities');
6
+ const activitiesManager = require('./activities');
9
7
 
10
8
  // Async Functions initialization function
11
9
  const initializeFunctions = async (options = {}) => {
@@ -30,12 +28,12 @@ const createTask = async taskData => {
30
28
  // Create a new task/workflow
31
29
  return await scheduledTasksManager.createTask(taskData);
32
30
  };
31
+ const emitActivity = activitiesManager.emitActivity;
33
32
  module.exports = {
34
- // Initialization/Execution methods
35
33
  initializeFunctions,
36
34
  initializeTools,
37
35
  executeTasks,
38
36
  executeTool,
39
37
  createTask,
40
- createActivityFeedItem
38
+ emitActivity
41
39
  };
@@ -5,119 +5,21 @@ const router = express.Router();
5
5
  const {
6
6
  getDb
7
7
  } = require("../services/mongo");
8
- const {
9
- ObjectId
10
- } = require("mongodb");
11
- const {
12
- createActivityFeedItem
13
- } = require("../managers/activities");
14
8
 
15
- /**
16
- * GET /activities
17
- * - Content-scoped (existing): ?contentId= → returns docs with projectId + contentId (shape: activity, createdAt).
18
- * - Feed: ?projectId=...&from=&to=&action=&limit= → returns feed docs (action, userId, metadata, etc.) from same collection.
19
- * Feed docs have "action" field; content-scoped docs have "contentId" and "activity".
20
- */
9
+ // Get all activities
21
10
  router.get("/", async (req, res) => {
22
11
  try {
23
12
  const {
24
- contentId,
25
- from,
26
- to,
27
- action,
28
- limit
13
+ contentId
29
14
  } = req.query;
30
- const projectId = req.projectId;
31
- const isFeedRequest = from !== undefined || to !== undefined || req.query.projectId && contentId === undefined;
32
- if (isFeedRequest) {
33
- const projectIds = [].concat(req.query.projectId || []).filter(Boolean);
34
- if (projectIds.length === 0) {
35
- return res.json({
36
- success: true,
37
- activities: []
38
- });
39
- }
40
- const query = {
41
- projectId: {
42
- $in: projectIds.map(id => new ObjectId(id))
43
- },
44
- action: {
45
- $exists: true
46
- }
47
- };
48
- if (from || to) {
49
- query.createdAt = {};
50
- if (from) query.createdAt.$gte = new Date(from);
51
- if (to) query.createdAt.$lte = new Date(to);
52
- }
53
- if (action) query.action = action;
54
- const db = await getDb();
55
- const activities = await db.collection("activities").find(query).sort({
56
- createdAt: -1
57
- }).limit(Math.min(parseInt(limit, 10) || 50, 100)).toArray();
58
- const actorIds = [...new Set(activities.map(a => {
59
- var _a$userId;
60
- return (_a$userId = a.userId) === null || _a$userId === void 0 ? void 0 : _a$userId.toString();
61
- }).filter(Boolean))];
62
- let actorDetails = {};
63
- if (actorIds.length > 0) {
64
- const actors = await db.collection("users").find({
65
- _id: {
66
- $in: actorIds.map(id => new ObjectId(id))
67
- }
68
- }).project({
69
- _id: 1,
70
- fullName: 1
71
- }).toArray();
72
- actorDetails = actors.reduce((acc, u) => {
73
- acc[u._id.toString()] = u.fullName || "Unknown";
74
- return acc;
75
- }, {});
76
- }
77
- const assigneeIds = activities.filter(a => {
78
- var _a$metadata;
79
- return (_a$metadata = a.metadata) === null || _a$metadata === void 0 ? void 0 : _a$metadata.assigneeId;
80
- }).map(a => a.metadata.assigneeId);
81
- let assigneeDetails = {};
82
- if (assigneeIds.length > 0) {
83
- const assignees = await db.collection("users").find({
84
- _id: {
85
- $in: assigneeIds.map(id => new ObjectId(id))
86
- }
87
- }).project({
88
- _id: 1,
89
- fullName: 1
90
- }).toArray();
91
- assigneeDetails = assignees.reduce((acc, u) => {
92
- acc[u._id.toString()] = u.fullName || "Unknown";
93
- return acc;
94
- }, {});
95
- }
96
- const enriched = activities.map(a => {
97
- var _a$userId2, _a$projectId, _a$userId3, _a$metadata2;
98
- return {
99
- ...a,
100
- _id: a._id.toString(),
101
- userId: (_a$userId2 = a.userId) === null || _a$userId2 === void 0 ? void 0 : _a$userId2.toString(),
102
- projectId: (_a$projectId = a.projectId) === null || _a$projectId === void 0 ? void 0 : _a$projectId.toString(),
103
- actorName: actorDetails[(_a$userId3 = a.userId) === null || _a$userId3 === void 0 ? void 0 : _a$userId3.toString()] || "Unknown",
104
- assigneeName: (_a$metadata2 = a.metadata) !== null && _a$metadata2 !== void 0 && _a$metadata2.assigneeId ? assigneeDetails[a.metadata.assigneeId] || "Unknown" : null,
105
- projectName: a.projectName || null,
106
- projectSlug: a.projectSlug || null
107
- };
108
- });
109
- return res.json({
110
- success: true,
111
- activities: enriched
112
- });
113
- }
15
+ const projectId = req.projectId; // Use middleware-injected projectId
16
+
114
17
  const query = {
115
- activity: {
116
- $exists: true
117
- }
18
+ projectId
118
19
  };
119
- if (projectId) query.projectId = new ObjectId(projectId);
120
- if (contentId) query.contentId = contentId;
20
+ if (contentId) {
21
+ query.contentId = contentId;
22
+ }
121
23
  const db = await getDb();
122
24
  const activities = await db.collection("activities").find(query).toArray();
123
25
  return res.json({
@@ -133,36 +35,15 @@ router.get("/", async (req, res) => {
133
35
  }
134
36
  });
135
37
 
136
- /**
137
- * POST /activities
138
- * - Feed: body has action, userId → insert feed doc into activities collection.
139
- * - Content-scoped (existing): body has contentId, activity → insert content-scoped doc.
140
- */
38
+ // Create new activity
141
39
  router.post("/", async (req, res) => {
142
40
  try {
143
- const body = req.body;
144
- const projectId = req.projectId;
145
- if (body.action && body.userId) {
146
- const payload = {
147
- ...body,
148
- projectId: body.projectId || projectId
149
- };
150
- const result = await createActivityFeedItem(payload);
151
- if (!result.success) {
152
- return res.status(400).json({
153
- success: false,
154
- message: result.message
155
- });
156
- }
157
- return res.status(201).json({
158
- success: true,
159
- id: result.id
160
- });
161
- }
162
41
  const {
163
42
  contentId,
164
43
  activity
165
- } = body;
44
+ } = req.body;
45
+ const projectId = req.projectId; // Use middleware-injected projectId
46
+
166
47
  if (!contentId || !activity) {
167
48
  return res.status(400).json({
168
49
  success: false,
@@ -170,7 +51,7 @@ router.post("/", async (req, res) => {
170
51
  });
171
52
  }
172
53
  const activityData = {
173
- projectId: projectId ? new ObjectId(projectId) : undefined,
54
+ projectId,
174
55
  contentId,
175
56
  activity,
176
57
  createdAt: new Date()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powr-sdk-api",
3
- "version": "4.7.3",
3
+ "version": "4.8.0",
4
4
  "description": "Shared API core library for PowrStack projects. Zero dependencies - works with Express, Next.js API routes, and other frameworks. All features are optional and install only what you need.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",