@objectstack/service-feed 4.0.3 → 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/README.md +378 -0
- package/dist/index.cjs +12 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1674 -865
- package/dist/index.d.ts +1674 -865
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/package.json +31 -6
- package/.turbo/turbo-build.log +0 -22
- package/CHANGELOG.md +0 -160
- 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 -162
- package/src/objects/feed-reaction.object.ts +0 -66
- package/src/objects/index.ts +0 -13
- package/src/objects/record-subscription.object.ts +0 -80
- package/tsconfig.json +0 -17
package/dist/index.js
CHANGED
|
@@ -224,7 +224,7 @@ 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
|
-
name: "
|
|
227
|
+
name: "feed_item",
|
|
228
228
|
label: "Feed Item",
|
|
229
229
|
pluralLabel: "Feed Items",
|
|
230
230
|
icon: "message-square",
|
|
@@ -302,8 +302,8 @@ var FeedItem = ObjectSchema.create({
|
|
|
302
302
|
label: "Reactions",
|
|
303
303
|
description: "Array of emoji reaction objects (JSON)"
|
|
304
304
|
}),
|
|
305
|
-
parent_id: Field.
|
|
306
|
-
label: "Parent Feed Item
|
|
305
|
+
parent_id: Field.lookup("feed_item", {
|
|
306
|
+
label: "Parent Feed Item",
|
|
307
307
|
description: "For threaded replies"
|
|
308
308
|
}),
|
|
309
309
|
reply_count: Field.number({
|
|
@@ -356,7 +356,7 @@ var FeedItem = ObjectSchema.create({
|
|
|
356
356
|
// src/objects/feed-reaction.object.ts
|
|
357
357
|
import { ObjectSchema as ObjectSchema2, Field as Field2 } from "@objectstack/spec/data";
|
|
358
358
|
var FeedReaction = ObjectSchema2.create({
|
|
359
|
-
name: "
|
|
359
|
+
name: "feed_reaction",
|
|
360
360
|
label: "Feed Reaction",
|
|
361
361
|
pluralLabel: "Feed Reactions",
|
|
362
362
|
icon: "smile",
|
|
@@ -369,8 +369,8 @@ var FeedReaction = ObjectSchema2.create({
|
|
|
369
369
|
required: true,
|
|
370
370
|
readonly: true
|
|
371
371
|
}),
|
|
372
|
-
feed_item_id: Field2.
|
|
373
|
-
label: "Feed Item
|
|
372
|
+
feed_item_id: Field2.lookup("feed_item", {
|
|
373
|
+
label: "Feed Item",
|
|
374
374
|
required: true
|
|
375
375
|
}),
|
|
376
376
|
emoji: Field2.text({
|
|
@@ -378,8 +378,8 @@ var FeedReaction = ObjectSchema2.create({
|
|
|
378
378
|
required: true,
|
|
379
379
|
description: 'Emoji character or shortcode (e.g., "\u{1F44D}", ":thumbsup:")'
|
|
380
380
|
}),
|
|
381
|
-
user_id: Field2.
|
|
382
|
-
label: "User
|
|
381
|
+
user_id: Field2.lookup("sys_user", {
|
|
382
|
+
label: "User",
|
|
383
383
|
required: true
|
|
384
384
|
}),
|
|
385
385
|
created_at: Field2.datetime({
|
|
@@ -406,7 +406,7 @@ var FeedReaction = ObjectSchema2.create({
|
|
|
406
406
|
// src/objects/record-subscription.object.ts
|
|
407
407
|
import { ObjectSchema as ObjectSchema3, Field as Field3 } from "@objectstack/spec/data";
|
|
408
408
|
var RecordSubscription = ObjectSchema3.create({
|
|
409
|
-
name: "
|
|
409
|
+
name: "record_subscription",
|
|
410
410
|
label: "Record Subscription",
|
|
411
411
|
pluralLabel: "Record Subscriptions",
|
|
412
412
|
icon: "bell",
|
|
@@ -427,8 +427,8 @@ var RecordSubscription = ObjectSchema3.create({
|
|
|
427
427
|
label: "Record ID",
|
|
428
428
|
required: true
|
|
429
429
|
}),
|
|
430
|
-
user_id: Field3.
|
|
431
|
-
label: "User
|
|
430
|
+
user_id: Field3.lookup("sys_user", {
|
|
431
|
+
label: "User",
|
|
432
432
|
required: true
|
|
433
433
|
}),
|
|
434
434
|
events: Field3.textarea({
|
|
@@ -481,6 +481,7 @@ var FeedServicePlugin = class {
|
|
|
481
481
|
name: "Feed Service",
|
|
482
482
|
version: "1.0.0",
|
|
483
483
|
type: "plugin",
|
|
484
|
+
scope: "project",
|
|
484
485
|
objects: [FeedItem, FeedReaction, RecordSubscription]
|
|
485
486
|
});
|
|
486
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 name: 'sys_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 name: 'sys_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 name: 'sys_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.3 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
|
-
[32mCJS[39m [1mdist/index.cjs [22m[32m16.22 KB[39m
|
|
14
|
-
[32mCJS[39m [1mdist/index.cjs.map [22m[32m31.55 KB[39m
|
|
15
|
-
[32mCJS[39m ⚡️ Build success in 104ms
|
|
16
|
-
[32mESM[39m [1mdist/index.js [22m[32m14.72 KB[39m
|
|
17
|
-
[32mESM[39m [1mdist/index.js.map [22m[32m31.02 KB[39m
|
|
18
|
-
[32mESM[39m ⚡️ Build success in 104ms
|
|
19
|
-
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in 17078ms
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m281.01 KB[39m
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.cts [22m[32m281.01 KB[39m
|
package/CHANGELOG.md
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# @objectstack/service-feed
|
|
2
|
-
|
|
3
|
-
## 4.0.3
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- @objectstack/spec@4.0.3
|
|
8
|
-
- @objectstack/core@4.0.3
|
|
9
|
-
|
|
10
|
-
## 4.0.2
|
|
11
|
-
|
|
12
|
-
### Patch Changes
|
|
13
|
-
|
|
14
|
-
- Updated dependencies [5f659e9]
|
|
15
|
-
- @objectstack/spec@4.0.2
|
|
16
|
-
- @objectstack/core@4.0.2
|
|
17
|
-
|
|
18
|
-
## 4.0.0
|
|
19
|
-
|
|
20
|
-
### Patch Changes
|
|
21
|
-
|
|
22
|
-
- Updated dependencies [f08ffc3]
|
|
23
|
-
- Updated dependencies [e0b0a78]
|
|
24
|
-
- @objectstack/spec@4.0.0
|
|
25
|
-
- @objectstack/core@4.0.0
|
|
26
|
-
|
|
27
|
-
## 3.3.1
|
|
28
|
-
|
|
29
|
-
### Patch Changes
|
|
30
|
-
|
|
31
|
-
- @objectstack/spec@3.3.1
|
|
32
|
-
- @objectstack/core@3.3.1
|
|
33
|
-
|
|
34
|
-
## 3.3.0
|
|
35
|
-
|
|
36
|
-
### Patch Changes
|
|
37
|
-
|
|
38
|
-
- @objectstack/spec@3.3.0
|
|
39
|
-
- @objectstack/core@3.3.0
|
|
40
|
-
|
|
41
|
-
## 3.2.9
|
|
42
|
-
|
|
43
|
-
### Patch Changes
|
|
44
|
-
|
|
45
|
-
- @objectstack/spec@3.2.9
|
|
46
|
-
- @objectstack/core@3.2.9
|
|
47
|
-
|
|
48
|
-
## 3.2.8
|
|
49
|
-
|
|
50
|
-
### Patch Changes
|
|
51
|
-
|
|
52
|
-
- @objectstack/spec@3.2.8
|
|
53
|
-
- @objectstack/core@3.2.8
|
|
54
|
-
|
|
55
|
-
## 3.2.7
|
|
56
|
-
|
|
57
|
-
### Patch Changes
|
|
58
|
-
|
|
59
|
-
- @objectstack/spec@3.2.7
|
|
60
|
-
- @objectstack/core@3.2.7
|
|
61
|
-
|
|
62
|
-
## 3.2.6
|
|
63
|
-
|
|
64
|
-
### Patch Changes
|
|
65
|
-
|
|
66
|
-
- @objectstack/spec@3.2.6
|
|
67
|
-
- @objectstack/core@3.2.6
|
|
68
|
-
|
|
69
|
-
## 3.2.5
|
|
70
|
-
|
|
71
|
-
### Patch Changes
|
|
72
|
-
|
|
73
|
-
- @objectstack/spec@3.2.5
|
|
74
|
-
- @objectstack/core@3.2.5
|
|
75
|
-
|
|
76
|
-
## 3.2.4
|
|
77
|
-
|
|
78
|
-
### Patch Changes
|
|
79
|
-
|
|
80
|
-
- @objectstack/spec@3.2.4
|
|
81
|
-
- @objectstack/core@3.2.4
|
|
82
|
-
|
|
83
|
-
## 3.2.3
|
|
84
|
-
|
|
85
|
-
### Patch Changes
|
|
86
|
-
|
|
87
|
-
- @objectstack/spec@3.2.3
|
|
88
|
-
- @objectstack/core@3.2.3
|
|
89
|
-
|
|
90
|
-
## 3.2.2
|
|
91
|
-
|
|
92
|
-
### Patch Changes
|
|
93
|
-
|
|
94
|
-
- Updated dependencies [46defbb]
|
|
95
|
-
- @objectstack/spec@3.2.2
|
|
96
|
-
- @objectstack/core@3.2.2
|
|
97
|
-
|
|
98
|
-
## 3.2.1
|
|
99
|
-
|
|
100
|
-
### Patch Changes
|
|
101
|
-
|
|
102
|
-
- Updated dependencies [850b546]
|
|
103
|
-
- @objectstack/spec@3.2.1
|
|
104
|
-
- @objectstack/core@3.2.1
|
|
105
|
-
|
|
106
|
-
## 3.2.0
|
|
107
|
-
|
|
108
|
-
### Patch Changes
|
|
109
|
-
|
|
110
|
-
- Updated dependencies [5901c29]
|
|
111
|
-
- @objectstack/spec@3.2.0
|
|
112
|
-
- @objectstack/core@3.2.0
|
|
113
|
-
|
|
114
|
-
## 3.1.1
|
|
115
|
-
|
|
116
|
-
### Patch Changes
|
|
117
|
-
|
|
118
|
-
- Updated dependencies [953d667]
|
|
119
|
-
- @objectstack/spec@3.1.1
|
|
120
|
-
- @objectstack/core@3.1.1
|
|
121
|
-
|
|
122
|
-
## 3.1.0
|
|
123
|
-
|
|
124
|
-
### Patch Changes
|
|
125
|
-
|
|
126
|
-
- Updated dependencies [0088830]
|
|
127
|
-
- @objectstack/spec@3.1.0
|
|
128
|
-
- @objectstack/core@3.1.0
|
|
129
|
-
|
|
130
|
-
## 3.0.11
|
|
131
|
-
|
|
132
|
-
### Patch Changes
|
|
133
|
-
|
|
134
|
-
- Updated dependencies [92d9d99]
|
|
135
|
-
- @objectstack/spec@3.0.11
|
|
136
|
-
- @objectstack/core@3.0.11
|
|
137
|
-
|
|
138
|
-
## 3.0.10
|
|
139
|
-
|
|
140
|
-
### Patch Changes
|
|
141
|
-
|
|
142
|
-
- Updated dependencies [d1e5d31]
|
|
143
|
-
- @objectstack/spec@3.0.10
|
|
144
|
-
- @objectstack/core@3.0.10
|
|
145
|
-
|
|
146
|
-
## 3.0.9
|
|
147
|
-
|
|
148
|
-
### Patch Changes
|
|
149
|
-
|
|
150
|
-
- Updated dependencies [15e0df6]
|
|
151
|
-
- @objectstack/spec@3.0.9
|
|
152
|
-
- @objectstack/core@3.0.9
|
|
153
|
-
|
|
154
|
-
## 3.0.8
|
|
155
|
-
|
|
156
|
-
### Patch Changes
|
|
157
|
-
|
|
158
|
-
- Updated dependencies [5a968a2]
|
|
159
|
-
- @objectstack/spec@3.0.8
|
|
160
|
-
- @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
|
-
}
|