@objectstack/service-feed 4.0.4 → 4.0.5
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 +9 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1671 -865
- package/dist/index.d.ts +1671 -865
- package/dist/index.js +9 -11
- package/dist/index.js.map +1 -1
- package/package.json +31 -6
- package/.turbo/turbo-build.log +0 -22
- package/CHANGELOG.md +0 -168
- package/src/feed-service-plugin.ts +0 -70
- package/src/in-memory-feed-adapter.test.ts +0 -507
- package/src/in-memory-feed-adapter.ts +0 -323
- package/src/index.ts +0 -9
- package/src/objects/feed-item.object.ts +0 -163
- package/src/objects/feed-reaction.object.ts +0 -67
- package/src/objects/index.ts +0 -13
- package/src/objects/record-subscription.object.ts +0 -81
- package/tsconfig.json +0 -17
package/dist/index.js
CHANGED
|
@@ -224,7 +224,6 @@ var InMemoryFeedAdapter = class {
|
|
|
224
224
|
// src/objects/feed-item.object.ts
|
|
225
225
|
import { ObjectSchema, Field } from "@objectstack/spec/data";
|
|
226
226
|
var FeedItem = ObjectSchema.create({
|
|
227
|
-
namespace: "sys",
|
|
228
227
|
name: "feed_item",
|
|
229
228
|
label: "Feed Item",
|
|
230
229
|
pluralLabel: "Feed Items",
|
|
@@ -303,8 +302,8 @@ var FeedItem = ObjectSchema.create({
|
|
|
303
302
|
label: "Reactions",
|
|
304
303
|
description: "Array of emoji reaction objects (JSON)"
|
|
305
304
|
}),
|
|
306
|
-
parent_id: Field.
|
|
307
|
-
label: "Parent Feed Item
|
|
305
|
+
parent_id: Field.lookup("feed_item", {
|
|
306
|
+
label: "Parent Feed Item",
|
|
308
307
|
description: "For threaded replies"
|
|
309
308
|
}),
|
|
310
309
|
reply_count: Field.number({
|
|
@@ -357,7 +356,6 @@ var FeedItem = ObjectSchema.create({
|
|
|
357
356
|
// src/objects/feed-reaction.object.ts
|
|
358
357
|
import { ObjectSchema as ObjectSchema2, Field as Field2 } from "@objectstack/spec/data";
|
|
359
358
|
var FeedReaction = ObjectSchema2.create({
|
|
360
|
-
namespace: "sys",
|
|
361
359
|
name: "feed_reaction",
|
|
362
360
|
label: "Feed Reaction",
|
|
363
361
|
pluralLabel: "Feed Reactions",
|
|
@@ -371,8 +369,8 @@ var FeedReaction = ObjectSchema2.create({
|
|
|
371
369
|
required: true,
|
|
372
370
|
readonly: true
|
|
373
371
|
}),
|
|
374
|
-
feed_item_id: Field2.
|
|
375
|
-
label: "Feed Item
|
|
372
|
+
feed_item_id: Field2.lookup("feed_item", {
|
|
373
|
+
label: "Feed Item",
|
|
376
374
|
required: true
|
|
377
375
|
}),
|
|
378
376
|
emoji: Field2.text({
|
|
@@ -380,8 +378,8 @@ var FeedReaction = ObjectSchema2.create({
|
|
|
380
378
|
required: true,
|
|
381
379
|
description: 'Emoji character or shortcode (e.g., "\u{1F44D}", ":thumbsup:")'
|
|
382
380
|
}),
|
|
383
|
-
user_id: Field2.
|
|
384
|
-
label: "User
|
|
381
|
+
user_id: Field2.lookup("sys_user", {
|
|
382
|
+
label: "User",
|
|
385
383
|
required: true
|
|
386
384
|
}),
|
|
387
385
|
created_at: Field2.datetime({
|
|
@@ -408,7 +406,6 @@ var FeedReaction = ObjectSchema2.create({
|
|
|
408
406
|
// src/objects/record-subscription.object.ts
|
|
409
407
|
import { ObjectSchema as ObjectSchema3, Field as Field3 } from "@objectstack/spec/data";
|
|
410
408
|
var RecordSubscription = ObjectSchema3.create({
|
|
411
|
-
namespace: "sys",
|
|
412
409
|
name: "record_subscription",
|
|
413
410
|
label: "Record Subscription",
|
|
414
411
|
pluralLabel: "Record Subscriptions",
|
|
@@ -430,8 +427,8 @@ var RecordSubscription = ObjectSchema3.create({
|
|
|
430
427
|
label: "Record ID",
|
|
431
428
|
required: true
|
|
432
429
|
}),
|
|
433
|
-
user_id: Field3.
|
|
434
|
-
label: "User
|
|
430
|
+
user_id: Field3.lookup("sys_user", {
|
|
431
|
+
label: "User",
|
|
435
432
|
required: true
|
|
436
433
|
}),
|
|
437
434
|
events: Field3.textarea({
|
|
@@ -484,6 +481,7 @@ var FeedServicePlugin = class {
|
|
|
484
481
|
name: "Feed Service",
|
|
485
482
|
version: "1.0.0",
|
|
486
483
|
type: "plugin",
|
|
484
|
+
scope: "project",
|
|
487
485
|
objects: [FeedItem, FeedReaction, RecordSubscription]
|
|
488
486
|
});
|
|
489
487
|
ctx.logger.info("FeedServicePlugin: registered in-memory feed adapter");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/in-memory-feed-adapter.ts","../src/objects/feed-item.object.ts","../src/objects/feed-reaction.object.ts","../src/objects/record-subscription.object.ts","../src/feed-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n IFeedService,\n CreateFeedItemInput,\n UpdateFeedItemInput,\n ListFeedOptions,\n FeedListResult,\n SubscribeInput,\n} from '@objectstack/spec/contracts';\nimport type { FeedItem, Reaction } from '@objectstack/spec/data';\nimport type { RecordSubscription } from '@objectstack/spec/data';\n\n/**\n * Configuration options for InMemoryFeedAdapter.\n */\nexport interface InMemoryFeedAdapterOptions {\n /** Maximum number of feed items to store (0 = unlimited) */\n maxItems?: number;\n}\n\n/**\n * In-memory Feed/Chatter adapter implementing IFeedService.\n *\n * Uses Map-backed stores for feed items, reactions, and subscriptions.\n * Supports feed CRUD, emoji reactions, threaded replies, and record subscriptions.\n *\n * Suitable for single-process environments, development, and testing.\n * For production deployments, use a database-backed adapter.\n *\n * @example\n * ```ts\n * const feed = new InMemoryFeedAdapter();\n *\n * const item = await feed.createFeedItem({\n * object: 'account',\n * recordId: 'rec_123',\n * type: 'comment',\n * actor: { type: 'user', id: 'user_1', name: 'Alice' },\n * body: 'Great progress!',\n * });\n *\n * const list = await feed.listFeed({ object: 'account', recordId: 'rec_123' });\n * ```\n */\nexport class InMemoryFeedAdapter implements IFeedService {\n private readonly items = new Map<string, FeedItem>();\n private counter = 0;\n private readonly subscriptions = new Map<string, RecordSubscription>();\n private readonly maxItems: number;\n\n constructor(options: InMemoryFeedAdapterOptions = {}) {\n this.maxItems = options.maxItems ?? 0;\n }\n\n async listFeed(options: ListFeedOptions): Promise<FeedListResult> {\n let items = Array.from(this.items.values()).filter(\n (item) => item.object === options.object && item.recordId === options.recordId,\n );\n\n // Apply filter\n if (options.filter && options.filter !== 'all') {\n items = items.filter((item) => {\n switch (options.filter) {\n case 'comments_only':\n return item.type === 'comment';\n case 'changes_only':\n return item.type === 'field_change';\n case 'tasks_only':\n return item.type === 'task';\n default:\n return true;\n }\n });\n }\n\n // Sort reverse chronological (stable: break ties by ID descending)\n items.sort((a, b) => {\n const timeDiff = new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n if (timeDiff !== 0) return timeDiff;\n return b.id < a.id ? -1 : b.id > a.id ? 1 : 0;\n });\n\n const total = items.length;\n const limit = options.limit ?? 20;\n\n // Cursor-based pagination\n let startIndex = 0;\n if (options.cursor) {\n const cursorIndex = items.findIndex((item) => item.id === options.cursor);\n if (cursorIndex >= 0) {\n startIndex = cursorIndex + 1;\n }\n }\n\n const page = items.slice(startIndex, startIndex + limit);\n const hasMore = startIndex + limit < total;\n\n return {\n items: page,\n total,\n nextCursor: hasMore && page.length > 0 ? page[page.length - 1].id : undefined,\n hasMore,\n };\n }\n\n async createFeedItem(input: CreateFeedItemInput): Promise<FeedItem> {\n if (this.maxItems > 0 && this.items.size >= this.maxItems) {\n throw new Error(\n `Maximum feed item limit reached (${this.maxItems}). ` +\n 'Delete existing items before adding new ones.',\n );\n }\n\n const id = `feed_${++this.counter}`;\n const now = new Date().toISOString();\n\n // Increment parent reply count if threading\n if (input.parentId) {\n const parent = this.items.get(input.parentId);\n if (!parent) {\n throw new Error(`Parent feed item not found: ${input.parentId}`);\n }\n const updatedParent: FeedItem = {\n ...parent,\n replyCount: (parent.replyCount ?? 0) + 1,\n updatedAt: now,\n };\n this.items.set(parent.id, updatedParent);\n }\n\n const item: FeedItem = {\n id,\n type: input.type as FeedItem['type'],\n object: input.object,\n recordId: input.recordId,\n actor: {\n type: input.actor.type,\n id: input.actor.id,\n ...(input.actor.name ? { name: input.actor.name } : {}),\n ...(input.actor.avatarUrl ? { avatarUrl: input.actor.avatarUrl } : {}),\n },\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(input.mentions ? { mentions: input.mentions } : {}),\n ...(input.changes ? { changes: input.changes } : {}),\n ...(input.parentId ? { parentId: input.parentId } : {}),\n visibility: input.visibility ?? 'public',\n replyCount: 0,\n isEdited: false,\n pinned: false,\n starred: false,\n createdAt: now,\n };\n\n this.items.set(id, item);\n return item;\n }\n\n async updateFeedItem(feedId: string, input: UpdateFeedItemInput): Promise<FeedItem> {\n const existing = this.items.get(feedId);\n if (!existing) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n const now = new Date().toISOString();\n const updated: FeedItem = {\n ...existing,\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(input.mentions !== undefined ? { mentions: input.mentions } : {}),\n ...(input.visibility !== undefined ? { visibility: input.visibility } : {}),\n updatedAt: now,\n editedAt: now,\n isEdited: true,\n };\n\n this.items.set(feedId, updated);\n return updated;\n }\n\n async deleteFeedItem(feedId: string): Promise<void> {\n const item = this.items.get(feedId);\n if (!item) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n // Decrement parent reply count if threaded\n if (item.parentId) {\n const parent = this.items.get(item.parentId);\n if (parent) {\n const updatedParent: FeedItem = {\n ...parent,\n replyCount: Math.max(0, (parent.replyCount ?? 0) - 1),\n };\n this.items.set(parent.id, updatedParent);\n }\n }\n\n this.items.delete(feedId);\n }\n\n async getFeedItem(feedId: string): Promise<FeedItem | null> {\n return this.items.get(feedId) ?? null;\n }\n\n async addReaction(feedId: string, emoji: string, userId: string): Promise<Reaction[]> {\n const item = this.items.get(feedId);\n if (!item) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n const reactions = [...(item.reactions ?? [])];\n const existing = reactions.find((r) => r.emoji === emoji);\n\n if (existing) {\n if (existing.userIds.includes(userId)) {\n throw new Error(`Reaction already exists: ${emoji} by ${userId}`);\n }\n existing.userIds = [...existing.userIds, userId];\n existing.count = existing.userIds.length;\n } else {\n reactions.push({ emoji, userIds: [userId], count: 1 });\n }\n\n const updated: FeedItem = { ...item, reactions };\n this.items.set(feedId, updated);\n return reactions;\n }\n\n async removeReaction(feedId: string, emoji: string, userId: string): Promise<Reaction[]> {\n const item = this.items.get(feedId);\n if (!item) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n let reactions = [...(item.reactions ?? [])];\n const existing = reactions.find((r) => r.emoji === emoji);\n\n if (!existing || !existing.userIds.includes(userId)) {\n throw new Error(`Reaction not found: ${emoji} by ${userId}`);\n }\n\n existing.userIds = existing.userIds.filter((id) => id !== userId);\n existing.count = existing.userIds.length;\n\n // Remove reaction entry if no users left\n reactions = reactions.filter((r) => r.count > 0);\n\n const updated: FeedItem = { ...item, reactions };\n this.items.set(feedId, updated);\n return reactions;\n }\n\n async subscribe(input: SubscribeInput): Promise<RecordSubscription> {\n const key = this.subscriptionKey(input.object, input.recordId, input.userId);\n const existing = this.findSubscription(input.object, input.recordId, input.userId);\n\n if (existing) {\n // Update existing subscription\n const updated: RecordSubscription = {\n ...existing,\n events: input.events ?? existing.events,\n channels: input.channels ?? existing.channels,\n active: true,\n };\n this.subscriptions.set(key, updated);\n return updated;\n }\n\n const now = new Date().toISOString();\n const subscription: RecordSubscription = {\n object: input.object,\n recordId: input.recordId,\n userId: input.userId,\n events: input.events ?? ['all'],\n channels: input.channels ?? ['in_app'],\n active: true,\n createdAt: now,\n };\n\n this.subscriptions.set(key, subscription);\n return subscription;\n }\n\n async unsubscribe(object: string, recordId: string, userId: string): Promise<boolean> {\n const key = this.subscriptionKey(object, recordId, userId);\n return this.subscriptions.delete(key);\n }\n\n async getSubscription(\n object: string,\n recordId: string,\n userId: string,\n ): Promise<RecordSubscription | null> {\n return this.findSubscription(object, recordId, userId);\n }\n\n /**\n * Get the total number of feed items stored.\n */\n getItemCount(): number {\n return this.items.size;\n }\n\n /**\n * Get the total number of subscriptions stored.\n */\n getSubscriptionCount(): number {\n return this.subscriptions.size;\n }\n\n private subscriptionKey(object: string, recordId: string, userId: string): string {\n return `${object}:${recordId}:${userId}`;\n }\n\n private findSubscription(\n object: string,\n recordId: string,\n userId: string,\n ): RecordSubscription | null {\n const key = this.subscriptionKey(object, recordId, userId);\n return this.subscriptions.get(key) ?? null;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * Feed Item Object\n *\n * System object for storing feed/chatter items including comments,\n * field changes, tasks, events, and system activities.\n *\n * Belongs to `service-feed` package per \"protocol + service ownership\" pattern.\n */\nexport const FeedItem = ObjectSchema.create({\n namespace: 'sys',\n name: 'feed_item',\n label: 'Feed Item',\n pluralLabel: 'Feed Items',\n icon: 'message-square',\n description: 'Unified activity timeline entries (comments, field changes, tasks, events)',\n titleFormat: '{type}: {body}',\n compactLayout: ['type', 'object', 'record_id', 'created_at'],\n\n fields: {\n id: Field.text({\n label: 'Feed Item ID',\n required: true,\n readonly: true,\n }),\n\n type: Field.select({\n label: 'Type',\n required: true,\n options: [\n { label: 'Comment', value: 'comment' },\n { label: 'Field Change', value: 'field_change' },\n { label: 'Task', value: 'task' },\n { label: 'Event', value: 'event' },\n { label: 'Email', value: 'email' },\n { label: 'Call', value: 'call' },\n { label: 'Note', value: 'note' },\n { label: 'File', value: 'file' },\n { label: 'Record Create', value: 'record_create' },\n { label: 'Record Delete', value: 'record_delete' },\n { label: 'Approval', value: 'approval' },\n { label: 'Sharing', value: 'sharing' },\n { label: 'System', value: 'system' },\n ],\n }),\n\n object: Field.text({\n label: 'Object Name',\n required: true,\n searchable: true,\n }),\n\n record_id: Field.text({\n label: 'Record ID',\n required: true,\n searchable: true,\n }),\n\n actor_type: Field.select({\n label: 'Actor Type',\n required: true,\n options: [\n { label: 'User', value: 'user' },\n { label: 'System', value: 'system' },\n { label: 'Service', value: 'service' },\n { label: 'Automation', value: 'automation' },\n ],\n }),\n\n actor_id: Field.text({\n label: 'Actor ID',\n required: true,\n }),\n\n actor_name: Field.text({\n label: 'Actor Name',\n }),\n\n actor_avatar_url: Field.url({\n label: 'Actor Avatar URL',\n }),\n\n body: Field.textarea({\n label: 'Body',\n description: 'Rich text body (Markdown supported)',\n }),\n\n mentions: Field.textarea({\n label: 'Mentions',\n description: 'Array of @mention objects (JSON)',\n }),\n\n changes: Field.textarea({\n label: 'Field Changes',\n description: 'Array of field change entries (JSON)',\n }),\n\n reactions: Field.textarea({\n label: 'Reactions',\n description: 'Array of emoji reaction objects (JSON)',\n }),\n\n parent_id: Field.text({\n label: 'Parent Feed Item ID',\n description: 'For threaded replies',\n }),\n\n reply_count: Field.number({\n label: 'Reply Count',\n defaultValue: 0,\n }),\n\n visibility: Field.select({\n label: 'Visibility',\n defaultValue: 'public',\n options: [\n { label: 'Public', value: 'public' },\n { label: 'Internal', value: 'internal' },\n { label: 'Private', value: 'private' },\n ],\n }),\n\n is_edited: Field.boolean({\n label: 'Is Edited',\n defaultValue: false,\n }),\n\n edited_at: Field.datetime({\n label: 'Edited At',\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n\n updated_at: Field.datetime({\n label: 'Updated At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['object', 'record_id'], unique: false },\n { fields: ['actor_id'], unique: false },\n { fields: ['parent_id'], unique: false },\n { fields: ['created_at'], unique: false },\n ],\n\n enable: {\n trackHistory: false,\n searchable: true,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'update', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * Feed Reaction Object\n *\n * System object for storing individual emoji reactions on feed items.\n * Each row represents one user's reaction on one feed item.\n *\n * Belongs to `service-feed` package per \"protocol + service ownership\" pattern.\n */\nexport const FeedReaction = ObjectSchema.create({\n namespace: 'sys',\n name: 'feed_reaction',\n label: 'Feed Reaction',\n pluralLabel: 'Feed Reactions',\n icon: 'smile',\n description: 'Emoji reactions on feed items',\n titleFormat: '{emoji} by {user_id}',\n compactLayout: ['feed_item_id', 'emoji', 'user_id'],\n\n fields: {\n id: Field.text({\n label: 'Reaction ID',\n required: true,\n readonly: true,\n }),\n\n feed_item_id: Field.text({\n label: 'Feed Item ID',\n required: true,\n }),\n\n emoji: Field.text({\n label: 'Emoji',\n required: true,\n description: 'Emoji character or shortcode (e.g., \"👍\", \":thumbsup:\")',\n }),\n\n user_id: Field.text({\n label: 'User ID',\n required: true,\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['feed_item_id', 'emoji', 'user_id'], unique: true },\n { fields: ['feed_item_id'], unique: false },\n { fields: ['user_id'], unique: false },\n ],\n\n enable: {\n trackHistory: false,\n searchable: false,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * Record Subscription Object\n *\n * System object for storing record-level notification subscriptions.\n * Enables Airtable-style bell icon for record change notifications.\n *\n * Belongs to `service-feed` package per \"protocol + service ownership\" pattern.\n */\nexport const RecordSubscription = ObjectSchema.create({\n namespace: 'sys',\n name: 'record_subscription',\n label: 'Record Subscription',\n pluralLabel: 'Record Subscriptions',\n icon: 'bell',\n description: 'Record-level notification subscriptions for feed events',\n titleFormat: '{object}/{record_id} — {user_id}',\n compactLayout: ['object', 'record_id', 'user_id', 'active'],\n\n fields: {\n id: Field.text({\n label: 'Subscription ID',\n required: true,\n readonly: true,\n }),\n\n object: Field.text({\n label: 'Object Name',\n required: true,\n }),\n\n record_id: Field.text({\n label: 'Record ID',\n required: true,\n }),\n\n user_id: Field.text({\n label: 'User ID',\n required: true,\n }),\n\n events: Field.textarea({\n label: 'Subscribed Events',\n description: 'Array of event types: comment, mention, field_change, task, approval, all (JSON)',\n }),\n\n channels: Field.textarea({\n label: 'Notification Channels',\n description: 'Array of channels: in_app, email, push, slack (JSON)',\n }),\n\n active: Field.boolean({\n label: 'Active',\n defaultValue: true,\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['object', 'record_id', 'user_id'], unique: true },\n { fields: ['user_id'], unique: false },\n { fields: ['object', 'record_id'], unique: false },\n ],\n\n enable: {\n trackHistory: false,\n searchable: false,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'update', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { InMemoryFeedAdapter } from './in-memory-feed-adapter.js';\nimport type { InMemoryFeedAdapterOptions } from './in-memory-feed-adapter.js';\nimport { FeedItem, FeedReaction, RecordSubscription } from './objects/index.js';\n\n/**\n * Configuration options for the FeedServicePlugin.\n */\nexport interface FeedServicePluginOptions {\n /** Feed adapter type (default: 'memory') */\n adapter?: 'memory';\n /** Options for the in-memory adapter */\n memory?: InMemoryFeedAdapterOptions;\n}\n\n/**\n * FeedServicePlugin — Production IFeedService implementation.\n *\n * Registers a Feed/Chatter service with the kernel during the init phase.\n * Currently supports in-memory storage for single-process environments.\n *\n * @example\n * ```ts\n * import { ObjectKernel } from '@objectstack/core';\n * import { FeedServicePlugin } from '@objectstack/service-feed';\n *\n * const kernel = new ObjectKernel();\n * kernel.use(new FeedServicePlugin());\n * await kernel.bootstrap();\n *\n * const feed = kernel.getService('feed');\n * const item = await feed.createFeedItem({\n * object: 'account',\n * recordId: 'rec_123',\n * type: 'comment',\n * actor: { type: 'user', id: 'user_1', name: 'Alice' },\n * body: 'Great progress!',\n * });\n * ```\n */\nexport class FeedServicePlugin implements Plugin {\n name = 'com.objectstack.service.feed';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: FeedServicePluginOptions;\n\n constructor(options: FeedServicePluginOptions = {}) {\n this.options = { adapter: 'memory', ...options };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const feed = new InMemoryFeedAdapter(this.options.memory);\n ctx.registerService('feed', feed);\n\n // Register feed system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.service.feed',\n name: 'Feed Service',\n version: '1.0.0',\n type: 'plugin',\n objects: [FeedItem, FeedReaction, RecordSubscription],\n });\n\n ctx.logger.info('FeedServicePlugin: registered in-memory feed adapter');\n }\n}\n"],"mappings":"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","names":["ObjectSchema","Field","ObjectSchema","Field"]}
|
|
1
|
+
{"version":3,"sources":["../src/in-memory-feed-adapter.ts","../src/objects/feed-item.object.ts","../src/objects/feed-reaction.object.ts","../src/objects/record-subscription.object.ts","../src/feed-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n IFeedService,\n CreateFeedItemInput,\n UpdateFeedItemInput,\n ListFeedOptions,\n FeedListResult,\n SubscribeInput,\n} from '@objectstack/spec/contracts';\nimport type { FeedItem, Reaction } from '@objectstack/spec/data';\nimport type { RecordSubscription } from '@objectstack/spec/data';\n\n/**\n * Configuration options for InMemoryFeedAdapter.\n */\nexport interface InMemoryFeedAdapterOptions {\n /** Maximum number of feed items to store (0 = unlimited) */\n maxItems?: number;\n}\n\n/**\n * In-memory Feed/Chatter adapter implementing IFeedService.\n *\n * Uses Map-backed stores for feed items, reactions, and subscriptions.\n * Supports feed CRUD, emoji reactions, threaded replies, and record subscriptions.\n *\n * Suitable for single-process environments, development, and testing.\n * For production deployments, use a database-backed adapter.\n *\n * @example\n * ```ts\n * const feed = new InMemoryFeedAdapter();\n *\n * const item = await feed.createFeedItem({\n * object: 'account',\n * recordId: 'rec_123',\n * type: 'comment',\n * actor: { type: 'user', id: 'user_1', name: 'Alice' },\n * body: 'Great progress!',\n * });\n *\n * const list = await feed.listFeed({ object: 'account', recordId: 'rec_123' });\n * ```\n */\nexport class InMemoryFeedAdapter implements IFeedService {\n private readonly items = new Map<string, FeedItem>();\n private counter = 0;\n private readonly subscriptions = new Map<string, RecordSubscription>();\n private readonly maxItems: number;\n\n constructor(options: InMemoryFeedAdapterOptions = {}) {\n this.maxItems = options.maxItems ?? 0;\n }\n\n async listFeed(options: ListFeedOptions): Promise<FeedListResult> {\n let items = Array.from(this.items.values()).filter(\n (item) => item.object === options.object && item.recordId === options.recordId,\n );\n\n // Apply filter\n if (options.filter && options.filter !== 'all') {\n items = items.filter((item) => {\n switch (options.filter) {\n case 'comments_only':\n return item.type === 'comment';\n case 'changes_only':\n return item.type === 'field_change';\n case 'tasks_only':\n return item.type === 'task';\n default:\n return true;\n }\n });\n }\n\n // Sort reverse chronological (stable: break ties by ID descending)\n items.sort((a, b) => {\n const timeDiff = new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n if (timeDiff !== 0) return timeDiff;\n return b.id < a.id ? -1 : b.id > a.id ? 1 : 0;\n });\n\n const total = items.length;\n const limit = options.limit ?? 20;\n\n // Cursor-based pagination\n let startIndex = 0;\n if (options.cursor) {\n const cursorIndex = items.findIndex((item) => item.id === options.cursor);\n if (cursorIndex >= 0) {\n startIndex = cursorIndex + 1;\n }\n }\n\n const page = items.slice(startIndex, startIndex + limit);\n const hasMore = startIndex + limit < total;\n\n return {\n items: page,\n total,\n nextCursor: hasMore && page.length > 0 ? page[page.length - 1].id : undefined,\n hasMore,\n };\n }\n\n async createFeedItem(input: CreateFeedItemInput): Promise<FeedItem> {\n if (this.maxItems > 0 && this.items.size >= this.maxItems) {\n throw new Error(\n `Maximum feed item limit reached (${this.maxItems}). ` +\n 'Delete existing items before adding new ones.',\n );\n }\n\n const id = `feed_${++this.counter}`;\n const now = new Date().toISOString();\n\n // Increment parent reply count if threading\n if (input.parentId) {\n const parent = this.items.get(input.parentId);\n if (!parent) {\n throw new Error(`Parent feed item not found: ${input.parentId}`);\n }\n const updatedParent: FeedItem = {\n ...parent,\n replyCount: (parent.replyCount ?? 0) + 1,\n updatedAt: now,\n };\n this.items.set(parent.id, updatedParent);\n }\n\n const item: FeedItem = {\n id,\n type: input.type as FeedItem['type'],\n object: input.object,\n recordId: input.recordId,\n actor: {\n type: input.actor.type,\n id: input.actor.id,\n ...(input.actor.name ? { name: input.actor.name } : {}),\n ...(input.actor.avatarUrl ? { avatarUrl: input.actor.avatarUrl } : {}),\n },\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(input.mentions ? { mentions: input.mentions } : {}),\n ...(input.changes ? { changes: input.changes } : {}),\n ...(input.parentId ? { parentId: input.parentId } : {}),\n visibility: input.visibility ?? 'public',\n replyCount: 0,\n isEdited: false,\n pinned: false,\n starred: false,\n createdAt: now,\n };\n\n this.items.set(id, item);\n return item;\n }\n\n async updateFeedItem(feedId: string, input: UpdateFeedItemInput): Promise<FeedItem> {\n const existing = this.items.get(feedId);\n if (!existing) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n const now = new Date().toISOString();\n const updated: FeedItem = {\n ...existing,\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(input.mentions !== undefined ? { mentions: input.mentions } : {}),\n ...(input.visibility !== undefined ? { visibility: input.visibility } : {}),\n updatedAt: now,\n editedAt: now,\n isEdited: true,\n };\n\n this.items.set(feedId, updated);\n return updated;\n }\n\n async deleteFeedItem(feedId: string): Promise<void> {\n const item = this.items.get(feedId);\n if (!item) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n // Decrement parent reply count if threaded\n if (item.parentId) {\n const parent = this.items.get(item.parentId);\n if (parent) {\n const updatedParent: FeedItem = {\n ...parent,\n replyCount: Math.max(0, (parent.replyCount ?? 0) - 1),\n };\n this.items.set(parent.id, updatedParent);\n }\n }\n\n this.items.delete(feedId);\n }\n\n async getFeedItem(feedId: string): Promise<FeedItem | null> {\n return this.items.get(feedId) ?? null;\n }\n\n async addReaction(feedId: string, emoji: string, userId: string): Promise<Reaction[]> {\n const item = this.items.get(feedId);\n if (!item) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n const reactions = [...(item.reactions ?? [])];\n const existing = reactions.find((r) => r.emoji === emoji);\n\n if (existing) {\n if (existing.userIds.includes(userId)) {\n throw new Error(`Reaction already exists: ${emoji} by ${userId}`);\n }\n existing.userIds = [...existing.userIds, userId];\n existing.count = existing.userIds.length;\n } else {\n reactions.push({ emoji, userIds: [userId], count: 1 });\n }\n\n const updated: FeedItem = { ...item, reactions };\n this.items.set(feedId, updated);\n return reactions;\n }\n\n async removeReaction(feedId: string, emoji: string, userId: string): Promise<Reaction[]> {\n const item = this.items.get(feedId);\n if (!item) {\n throw new Error(`Feed item not found: ${feedId}`);\n }\n\n let reactions = [...(item.reactions ?? [])];\n const existing = reactions.find((r) => r.emoji === emoji);\n\n if (!existing || !existing.userIds.includes(userId)) {\n throw new Error(`Reaction not found: ${emoji} by ${userId}`);\n }\n\n existing.userIds = existing.userIds.filter((id) => id !== userId);\n existing.count = existing.userIds.length;\n\n // Remove reaction entry if no users left\n reactions = reactions.filter((r) => r.count > 0);\n\n const updated: FeedItem = { ...item, reactions };\n this.items.set(feedId, updated);\n return reactions;\n }\n\n async subscribe(input: SubscribeInput): Promise<RecordSubscription> {\n const key = this.subscriptionKey(input.object, input.recordId, input.userId);\n const existing = this.findSubscription(input.object, input.recordId, input.userId);\n\n if (existing) {\n // Update existing subscription\n const updated: RecordSubscription = {\n ...existing,\n events: input.events ?? existing.events,\n channels: input.channels ?? existing.channels,\n active: true,\n };\n this.subscriptions.set(key, updated);\n return updated;\n }\n\n const now = new Date().toISOString();\n const subscription: RecordSubscription = {\n object: input.object,\n recordId: input.recordId,\n userId: input.userId,\n events: input.events ?? ['all'],\n channels: input.channels ?? ['in_app'],\n active: true,\n createdAt: now,\n };\n\n this.subscriptions.set(key, subscription);\n return subscription;\n }\n\n async unsubscribe(object: string, recordId: string, userId: string): Promise<boolean> {\n const key = this.subscriptionKey(object, recordId, userId);\n return this.subscriptions.delete(key);\n }\n\n async getSubscription(\n object: string,\n recordId: string,\n userId: string,\n ): Promise<RecordSubscription | null> {\n return this.findSubscription(object, recordId, userId);\n }\n\n /**\n * Get the total number of feed items stored.\n */\n getItemCount(): number {\n return this.items.size;\n }\n\n /**\n * Get the total number of subscriptions stored.\n */\n getSubscriptionCount(): number {\n return this.subscriptions.size;\n }\n\n private subscriptionKey(object: string, recordId: string, userId: string): string {\n return `${object}:${recordId}:${userId}`;\n }\n\n private findSubscription(\n object: string,\n recordId: string,\n userId: string,\n ): RecordSubscription | null {\n const key = this.subscriptionKey(object, recordId, userId);\n return this.subscriptions.get(key) ?? null;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * Feed Item Object\n *\n * System object for storing feed/chatter items including comments,\n * field changes, tasks, events, and system activities.\n *\n * Belongs to `service-feed` package per \"protocol + service ownership\" pattern.\n */\nexport const FeedItem = ObjectSchema.create({\n name: 'feed_item',\n label: 'Feed Item',\n pluralLabel: 'Feed Items',\n icon: 'message-square',\n description: 'Unified activity timeline entries (comments, field changes, tasks, events)',\n titleFormat: '{type}: {body}',\n compactLayout: ['type', 'object', 'record_id', 'created_at'],\n\n fields: {\n id: Field.text({\n label: 'Feed Item ID',\n required: true,\n readonly: true,\n }),\n\n type: Field.select({\n label: 'Type',\n required: true,\n options: [\n { label: 'Comment', value: 'comment' },\n { label: 'Field Change', value: 'field_change' },\n { label: 'Task', value: 'task' },\n { label: 'Event', value: 'event' },\n { label: 'Email', value: 'email' },\n { label: 'Call', value: 'call' },\n { label: 'Note', value: 'note' },\n { label: 'File', value: 'file' },\n { label: 'Record Create', value: 'record_create' },\n { label: 'Record Delete', value: 'record_delete' },\n { label: 'Approval', value: 'approval' },\n { label: 'Sharing', value: 'sharing' },\n { label: 'System', value: 'system' },\n ],\n }),\n\n object: Field.text({\n label: 'Object Name',\n required: true,\n searchable: true,\n }),\n\n record_id: Field.text({\n label: 'Record ID',\n required: true,\n searchable: true,\n }),\n\n actor_type: Field.select({\n label: 'Actor Type',\n required: true,\n options: [\n { label: 'User', value: 'user' },\n { label: 'System', value: 'system' },\n { label: 'Service', value: 'service' },\n { label: 'Automation', value: 'automation' },\n ],\n }),\n\n actor_id: Field.text({\n label: 'Actor ID',\n required: true,\n }),\n\n actor_name: Field.text({\n label: 'Actor Name',\n }),\n\n actor_avatar_url: Field.url({\n label: 'Actor Avatar URL',\n }),\n\n body: Field.textarea({\n label: 'Body',\n description: 'Rich text body (Markdown supported)',\n }),\n\n mentions: Field.textarea({\n label: 'Mentions',\n description: 'Array of @mention objects (JSON)',\n }),\n\n changes: Field.textarea({\n label: 'Field Changes',\n description: 'Array of field change entries (JSON)',\n }),\n\n reactions: Field.textarea({\n label: 'Reactions',\n description: 'Array of emoji reaction objects (JSON)',\n }),\n\n parent_id: Field.lookup('feed_item', {\n label: 'Parent Feed Item',\n description: 'For threaded replies',\n }),\n\n reply_count: Field.number({\n label: 'Reply Count',\n defaultValue: 0,\n }),\n\n visibility: Field.select({\n label: 'Visibility',\n defaultValue: 'public',\n options: [\n { label: 'Public', value: 'public' },\n { label: 'Internal', value: 'internal' },\n { label: 'Private', value: 'private' },\n ],\n }),\n\n is_edited: Field.boolean({\n label: 'Is Edited',\n defaultValue: false,\n }),\n\n edited_at: Field.datetime({\n label: 'Edited At',\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n\n updated_at: Field.datetime({\n label: 'Updated At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['object', 'record_id'], unique: false },\n { fields: ['actor_id'], unique: false },\n { fields: ['parent_id'], unique: false },\n { fields: ['created_at'], unique: false },\n ],\n\n enable: {\n trackHistory: false,\n searchable: true,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'update', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * Feed Reaction Object\n *\n * System object for storing individual emoji reactions on feed items.\n * Each row represents one user's reaction on one feed item.\n *\n * Belongs to `service-feed` package per \"protocol + service ownership\" pattern.\n */\nexport const FeedReaction = ObjectSchema.create({\n name: 'feed_reaction',\n label: 'Feed Reaction',\n pluralLabel: 'Feed Reactions',\n icon: 'smile',\n description: 'Emoji reactions on feed items',\n titleFormat: '{emoji} by {user_id}',\n compactLayout: ['feed_item_id', 'emoji', 'user_id'],\n\n fields: {\n id: Field.text({\n label: 'Reaction ID',\n required: true,\n readonly: true,\n }),\n\n feed_item_id: Field.lookup('feed_item', {\n label: 'Feed Item',\n required: true,\n }),\n\n emoji: Field.text({\n label: 'Emoji',\n required: true,\n description: 'Emoji character or shortcode (e.g., \"👍\", \":thumbsup:\")',\n }),\n\n user_id: Field.lookup('sys_user', {\n label: 'User',\n required: true,\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['feed_item_id', 'emoji', 'user_id'], unique: true },\n { fields: ['feed_item_id'], unique: false },\n { fields: ['user_id'], unique: false },\n ],\n\n enable: {\n trackHistory: false,\n searchable: false,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * Record Subscription Object\n *\n * System object for storing record-level notification subscriptions.\n * Enables Airtable-style bell icon for record change notifications.\n *\n * Belongs to `service-feed` package per \"protocol + service ownership\" pattern.\n */\nexport const RecordSubscription = ObjectSchema.create({\n name: 'record_subscription',\n label: 'Record Subscription',\n pluralLabel: 'Record Subscriptions',\n icon: 'bell',\n description: 'Record-level notification subscriptions for feed events',\n titleFormat: '{object}/{record_id} — {user_id}',\n compactLayout: ['object', 'record_id', 'user_id', 'active'],\n\n fields: {\n id: Field.text({\n label: 'Subscription ID',\n required: true,\n readonly: true,\n }),\n\n object: Field.text({\n label: 'Object Name',\n required: true,\n }),\n\n record_id: Field.text({\n label: 'Record ID',\n required: true,\n }),\n\n user_id: Field.lookup('sys_user', {\n label: 'User',\n required: true,\n }),\n\n events: Field.textarea({\n label: 'Subscribed Events',\n description: 'Array of event types: comment, mention, field_change, task, approval, all (JSON)',\n }),\n\n channels: Field.textarea({\n label: 'Notification Channels',\n description: 'Array of channels: in_app, email, push, slack (JSON)',\n }),\n\n active: Field.boolean({\n label: 'Active',\n defaultValue: true,\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n defaultValue: 'NOW()',\n readonly: true,\n }),\n },\n\n indexes: [\n { fields: ['object', 'record_id', 'user_id'], unique: true },\n { fields: ['user_id'], unique: false },\n { fields: ['object', 'record_id'], unique: false },\n ],\n\n enable: {\n trackHistory: false,\n searchable: false,\n apiEnabled: true,\n apiMethods: ['get', 'list', 'create', 'update', 'delete'],\n trash: false,\n mru: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { InMemoryFeedAdapter } from './in-memory-feed-adapter.js';\nimport type { InMemoryFeedAdapterOptions } from './in-memory-feed-adapter.js';\nimport { FeedItem, FeedReaction, RecordSubscription } from './objects/index.js';\n\n/**\n * Configuration options for the FeedServicePlugin.\n */\nexport interface FeedServicePluginOptions {\n /** Feed adapter type (default: 'memory') */\n adapter?: 'memory';\n /** Options for the in-memory adapter */\n memory?: InMemoryFeedAdapterOptions;\n}\n\n/**\n * FeedServicePlugin — Production IFeedService implementation.\n *\n * Registers a Feed/Chatter service with the kernel during the init phase.\n * Currently supports in-memory storage for single-process environments.\n *\n * @example\n * ```ts\n * import { ObjectKernel } from '@objectstack/core';\n * import { FeedServicePlugin } from '@objectstack/service-feed';\n *\n * const kernel = new ObjectKernel();\n * kernel.use(new FeedServicePlugin());\n * await kernel.bootstrap();\n *\n * const feed = kernel.getService('feed');\n * const item = await feed.createFeedItem({\n * object: 'account',\n * recordId: 'rec_123',\n * type: 'comment',\n * actor: { type: 'user', id: 'user_1', name: 'Alice' },\n * body: 'Great progress!',\n * });\n * ```\n */\nexport class FeedServicePlugin implements Plugin {\n name = 'com.objectstack.service.feed';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: FeedServicePluginOptions;\n\n constructor(options: FeedServicePluginOptions = {}) {\n this.options = { adapter: 'memory', ...options };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const feed = new InMemoryFeedAdapter(this.options.memory);\n ctx.registerService('feed', feed);\n\n // Register feed system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.service.feed',\n name: 'Feed Service',\n version: '1.0.0',\n type: 'plugin',\n scope: 'project',\n objects: [FeedItem, FeedReaction, RecordSubscription],\n });\n\n ctx.logger.info('FeedServicePlugin: registered in-memory feed adapter');\n }\n}\n"],"mappings":"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","names":["ObjectSchema","Field","ObjectSchema","Field"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/service-feed",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Feed/Chatter Service for ObjectStack — implements IFeedService with in-memory adapter for comments, reactions, field changes, and record subscriptions",
|
|
6
6
|
"type": "module",
|
|
@@ -14,13 +14,38 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@objectstack/core": "4.0.
|
|
18
|
-
"@objectstack/spec": "4.0.
|
|
17
|
+
"@objectstack/core": "4.0.5",
|
|
18
|
+
"@objectstack/spec": "4.0.5"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@types/node": "^25.6.
|
|
22
|
-
"typescript": "^6.0.
|
|
23
|
-
"vitest": "^4.1.
|
|
21
|
+
"@types/node": "^25.6.2",
|
|
22
|
+
"typescript": "^6.0.3",
|
|
23
|
+
"vitest": "^4.1.5"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"objectstack",
|
|
27
|
+
"service",
|
|
28
|
+
"feed",
|
|
29
|
+
"activity",
|
|
30
|
+
"chatter"
|
|
31
|
+
],
|
|
32
|
+
"author": "ObjectStack",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/objectstack-ai/framework.git",
|
|
36
|
+
"directory": "packages/services/service-feed"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://objectstack.ai/docs",
|
|
39
|
+
"bugs": "https://github.com/objectstack-ai/framework/issues",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
24
49
|
},
|
|
25
50
|
"scripts": {
|
|
26
51
|
"build": "tsup --config ../../../tsup.config.ts",
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @objectstack/service-feed@4.0.4 build /home/runner/work/framework/framework/packages/services/service-feed
|
|
3
|
-
> tsup --config ../../../tsup.config.ts
|
|
4
|
-
|
|
5
|
-
[34mCLI[39m Building entry: src/index.ts
|
|
6
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
-
[34mCLI[39m tsup v8.5.1
|
|
8
|
-
[34mCLI[39m Using tsup config: /home/runner/work/framework/framework/tsup.config.ts
|
|
9
|
-
[34mCLI[39m Target: es2020
|
|
10
|
-
[34mCLI[39m Cleaning output folder
|
|
11
|
-
[34mESM[39m Build start
|
|
12
|
-
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.js [22m[32m14.76 KB[39m
|
|
14
|
-
[32mESM[39m [1mdist/index.js.map [22m[32m31.12 KB[39m
|
|
15
|
-
[32mESM[39m ⚡️ Build success in 148ms
|
|
16
|
-
[32mCJS[39m [1mdist/index.cjs [22m[32m16.27 KB[39m
|
|
17
|
-
[32mCJS[39m [1mdist/index.cjs.map [22m[32m31.65 KB[39m
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in 131ms
|
|
19
|
-
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in 20999ms
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m281.09 KB[39m
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.cts [22m[32m281.09 KB[39m
|
package/CHANGELOG.md
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
# @objectstack/service-feed
|
|
2
|
-
|
|
3
|
-
## 4.0.4
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies [326b66b]
|
|
8
|
-
- @objectstack/spec@4.0.4
|
|
9
|
-
- @objectstack/core@4.0.4
|
|
10
|
-
|
|
11
|
-
## 4.0.3
|
|
12
|
-
|
|
13
|
-
### Patch Changes
|
|
14
|
-
|
|
15
|
-
- @objectstack/spec@4.0.3
|
|
16
|
-
- @objectstack/core@4.0.3
|
|
17
|
-
|
|
18
|
-
## 4.0.2
|
|
19
|
-
|
|
20
|
-
### Patch Changes
|
|
21
|
-
|
|
22
|
-
- Updated dependencies [5f659e9]
|
|
23
|
-
- @objectstack/spec@4.0.2
|
|
24
|
-
- @objectstack/core@4.0.2
|
|
25
|
-
|
|
26
|
-
## 4.0.0
|
|
27
|
-
|
|
28
|
-
### Patch Changes
|
|
29
|
-
|
|
30
|
-
- Updated dependencies [f08ffc3]
|
|
31
|
-
- Updated dependencies [e0b0a78]
|
|
32
|
-
- @objectstack/spec@4.0.0
|
|
33
|
-
- @objectstack/core@4.0.0
|
|
34
|
-
|
|
35
|
-
## 3.3.1
|
|
36
|
-
|
|
37
|
-
### Patch Changes
|
|
38
|
-
|
|
39
|
-
- @objectstack/spec@3.3.1
|
|
40
|
-
- @objectstack/core@3.3.1
|
|
41
|
-
|
|
42
|
-
## 3.3.0
|
|
43
|
-
|
|
44
|
-
### Patch Changes
|
|
45
|
-
|
|
46
|
-
- @objectstack/spec@3.3.0
|
|
47
|
-
- @objectstack/core@3.3.0
|
|
48
|
-
|
|
49
|
-
## 3.2.9
|
|
50
|
-
|
|
51
|
-
### Patch Changes
|
|
52
|
-
|
|
53
|
-
- @objectstack/spec@3.2.9
|
|
54
|
-
- @objectstack/core@3.2.9
|
|
55
|
-
|
|
56
|
-
## 3.2.8
|
|
57
|
-
|
|
58
|
-
### Patch Changes
|
|
59
|
-
|
|
60
|
-
- @objectstack/spec@3.2.8
|
|
61
|
-
- @objectstack/core@3.2.8
|
|
62
|
-
|
|
63
|
-
## 3.2.7
|
|
64
|
-
|
|
65
|
-
### Patch Changes
|
|
66
|
-
|
|
67
|
-
- @objectstack/spec@3.2.7
|
|
68
|
-
- @objectstack/core@3.2.7
|
|
69
|
-
|
|
70
|
-
## 3.2.6
|
|
71
|
-
|
|
72
|
-
### Patch Changes
|
|
73
|
-
|
|
74
|
-
- @objectstack/spec@3.2.6
|
|
75
|
-
- @objectstack/core@3.2.6
|
|
76
|
-
|
|
77
|
-
## 3.2.5
|
|
78
|
-
|
|
79
|
-
### Patch Changes
|
|
80
|
-
|
|
81
|
-
- @objectstack/spec@3.2.5
|
|
82
|
-
- @objectstack/core@3.2.5
|
|
83
|
-
|
|
84
|
-
## 3.2.4
|
|
85
|
-
|
|
86
|
-
### Patch Changes
|
|
87
|
-
|
|
88
|
-
- @objectstack/spec@3.2.4
|
|
89
|
-
- @objectstack/core@3.2.4
|
|
90
|
-
|
|
91
|
-
## 3.2.3
|
|
92
|
-
|
|
93
|
-
### Patch Changes
|
|
94
|
-
|
|
95
|
-
- @objectstack/spec@3.2.3
|
|
96
|
-
- @objectstack/core@3.2.3
|
|
97
|
-
|
|
98
|
-
## 3.2.2
|
|
99
|
-
|
|
100
|
-
### Patch Changes
|
|
101
|
-
|
|
102
|
-
- Updated dependencies [46defbb]
|
|
103
|
-
- @objectstack/spec@3.2.2
|
|
104
|
-
- @objectstack/core@3.2.2
|
|
105
|
-
|
|
106
|
-
## 3.2.1
|
|
107
|
-
|
|
108
|
-
### Patch Changes
|
|
109
|
-
|
|
110
|
-
- Updated dependencies [850b546]
|
|
111
|
-
- @objectstack/spec@3.2.1
|
|
112
|
-
- @objectstack/core@3.2.1
|
|
113
|
-
|
|
114
|
-
## 3.2.0
|
|
115
|
-
|
|
116
|
-
### Patch Changes
|
|
117
|
-
|
|
118
|
-
- Updated dependencies [5901c29]
|
|
119
|
-
- @objectstack/spec@3.2.0
|
|
120
|
-
- @objectstack/core@3.2.0
|
|
121
|
-
|
|
122
|
-
## 3.1.1
|
|
123
|
-
|
|
124
|
-
### Patch Changes
|
|
125
|
-
|
|
126
|
-
- Updated dependencies [953d667]
|
|
127
|
-
- @objectstack/spec@3.1.1
|
|
128
|
-
- @objectstack/core@3.1.1
|
|
129
|
-
|
|
130
|
-
## 3.1.0
|
|
131
|
-
|
|
132
|
-
### Patch Changes
|
|
133
|
-
|
|
134
|
-
- Updated dependencies [0088830]
|
|
135
|
-
- @objectstack/spec@3.1.0
|
|
136
|
-
- @objectstack/core@3.1.0
|
|
137
|
-
|
|
138
|
-
## 3.0.11
|
|
139
|
-
|
|
140
|
-
### Patch Changes
|
|
141
|
-
|
|
142
|
-
- Updated dependencies [92d9d99]
|
|
143
|
-
- @objectstack/spec@3.0.11
|
|
144
|
-
- @objectstack/core@3.0.11
|
|
145
|
-
|
|
146
|
-
## 3.0.10
|
|
147
|
-
|
|
148
|
-
### Patch Changes
|
|
149
|
-
|
|
150
|
-
- Updated dependencies [d1e5d31]
|
|
151
|
-
- @objectstack/spec@3.0.10
|
|
152
|
-
- @objectstack/core@3.0.10
|
|
153
|
-
|
|
154
|
-
## 3.0.9
|
|
155
|
-
|
|
156
|
-
### Patch Changes
|
|
157
|
-
|
|
158
|
-
- Updated dependencies [15e0df6]
|
|
159
|
-
- @objectstack/spec@3.0.9
|
|
160
|
-
- @objectstack/core@3.0.9
|
|
161
|
-
|
|
162
|
-
## 3.0.8
|
|
163
|
-
|
|
164
|
-
### Patch Changes
|
|
165
|
-
|
|
166
|
-
- Updated dependencies [5a968a2]
|
|
167
|
-
- @objectstack/spec@3.0.8
|
|
168
|
-
- @objectstack/core@3.0.8
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
-
|
|
3
|
-
import type { Plugin, PluginContext } from '@objectstack/core';
|
|
4
|
-
import { InMemoryFeedAdapter } from './in-memory-feed-adapter.js';
|
|
5
|
-
import type { InMemoryFeedAdapterOptions } from './in-memory-feed-adapter.js';
|
|
6
|
-
import { FeedItem, FeedReaction, RecordSubscription } from './objects/index.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Configuration options for the FeedServicePlugin.
|
|
10
|
-
*/
|
|
11
|
-
export interface FeedServicePluginOptions {
|
|
12
|
-
/** Feed adapter type (default: 'memory') */
|
|
13
|
-
adapter?: 'memory';
|
|
14
|
-
/** Options for the in-memory adapter */
|
|
15
|
-
memory?: InMemoryFeedAdapterOptions;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* FeedServicePlugin — Production IFeedService implementation.
|
|
20
|
-
*
|
|
21
|
-
* Registers a Feed/Chatter service with the kernel during the init phase.
|
|
22
|
-
* Currently supports in-memory storage for single-process environments.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```ts
|
|
26
|
-
* import { ObjectKernel } from '@objectstack/core';
|
|
27
|
-
* import { FeedServicePlugin } from '@objectstack/service-feed';
|
|
28
|
-
*
|
|
29
|
-
* const kernel = new ObjectKernel();
|
|
30
|
-
* kernel.use(new FeedServicePlugin());
|
|
31
|
-
* await kernel.bootstrap();
|
|
32
|
-
*
|
|
33
|
-
* const feed = kernel.getService('feed');
|
|
34
|
-
* const item = await feed.createFeedItem({
|
|
35
|
-
* object: 'account',
|
|
36
|
-
* recordId: 'rec_123',
|
|
37
|
-
* type: 'comment',
|
|
38
|
-
* actor: { type: 'user', id: 'user_1', name: 'Alice' },
|
|
39
|
-
* body: 'Great progress!',
|
|
40
|
-
* });
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
export class FeedServicePlugin implements Plugin {
|
|
44
|
-
name = 'com.objectstack.service.feed';
|
|
45
|
-
version = '1.0.0';
|
|
46
|
-
type = 'standard';
|
|
47
|
-
dependencies = ['com.objectstack.engine.objectql'];
|
|
48
|
-
|
|
49
|
-
private readonly options: FeedServicePluginOptions;
|
|
50
|
-
|
|
51
|
-
constructor(options: FeedServicePluginOptions = {}) {
|
|
52
|
-
this.options = { adapter: 'memory', ...options };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async init(ctx: PluginContext): Promise<void> {
|
|
56
|
-
const feed = new InMemoryFeedAdapter(this.options.memory);
|
|
57
|
-
ctx.registerService('feed', feed);
|
|
58
|
-
|
|
59
|
-
// Register feed system objects via the manifest service.
|
|
60
|
-
ctx.getService<{ register(m: any): void }>('manifest').register({
|
|
61
|
-
id: 'com.objectstack.service.feed',
|
|
62
|
-
name: 'Feed Service',
|
|
63
|
-
version: '1.0.0',
|
|
64
|
-
type: 'plugin',
|
|
65
|
-
objects: [FeedItem, FeedReaction, RecordSubscription],
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
ctx.logger.info('FeedServicePlugin: registered in-memory feed adapter');
|
|
69
|
-
}
|
|
70
|
-
}
|