@objectstack/service-feed 7.1.0 → 7.2.1
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 +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -9
- package/dist/index.d.ts +45 -9
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -511,7 +511,7 @@ var FeedServicePlugin = class {
|
|
|
511
511
|
name: "Feed Service",
|
|
512
512
|
version: "1.0.0",
|
|
513
513
|
type: "plugin",
|
|
514
|
-
scope: "
|
|
514
|
+
scope: "system",
|
|
515
515
|
objects: [FeedItem, FeedReaction, RecordSubscription]
|
|
516
516
|
});
|
|
517
517
|
ctx.logger.info("FeedServicePlugin: registered in-memory feed adapter");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../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\nexport { FeedServicePlugin } from './feed-service-plugin.js';\nexport type { FeedServicePluginOptions } from './feed-service-plugin.js';\nexport { InMemoryFeedAdapter } from './in-memory-feed-adapter.js';\nexport type { InMemoryFeedAdapterOptions } from './in-memory-feed-adapter.js';\n\n// Feed Service Objects (metadata definitions)\nexport { FeedItem, FeedReaction, RecordSubscription } from './objects/index.js';\n","// 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":["import_data","import_data"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../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\nexport { FeedServicePlugin } from './feed-service-plugin.js';\nexport type { FeedServicePluginOptions } from './feed-service-plugin.js';\nexport { InMemoryFeedAdapter } from './in-memory-feed-adapter.js';\nexport type { InMemoryFeedAdapterOptions } from './in-memory-feed-adapter.js';\n\n// Feed Service Objects (metadata definitions)\nexport { FeedItem, FeedReaction, RecordSubscription } from './objects/index.js';\n","// 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: 'system',\n objects: [FeedItem, FeedReaction, RecordSubscription],\n });\n\n ctx.logger.info('FeedServicePlugin: registered in-memory feed adapter');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC6CO,IAAM,sBAAN,MAAkD;AAAA,EAMvD,YAAY,UAAsC,CAAC,GAAG;AALtD,SAAiB,QAAQ,oBAAI,IAAsB;AACnD,SAAQ,UAAU;AAClB,SAAiB,gBAAgB,oBAAI,IAAgC;AAInE,SAAK,WAAW,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,MAAM,SAAS,SAAmD;AAChE,QAAI,QAAQ,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE;AAAA,MAC1C,CAAC,SAAS,KAAK,WAAW,QAAQ,UAAU,KAAK,aAAa,QAAQ;AAAA,IACxE;AAGA,QAAI,QAAQ,UAAU,QAAQ,WAAW,OAAO;AAC9C,cAAQ,MAAM,OAAO,CAAC,SAAS;AAC7B,gBAAQ,QAAQ,QAAQ;AAAA,UACtB,KAAK;AACH,mBAAO,KAAK,SAAS;AAAA,UACvB,KAAK;AACH,mBAAO,KAAK,SAAS;AAAA,UACvB,KAAK;AACH,mBAAO,KAAK,SAAS;AAAA,UACvB;AACE,mBAAO;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,KAAK,CAAC,GAAG,MAAM;AACnB,YAAM,WAAW,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AACjF,UAAI,aAAa,EAAG,QAAO;AAC3B,aAAO,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI;AAAA,IAC9C,CAAC;AAED,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,QAAQ,SAAS;AAG/B,QAAI,aAAa;AACjB,QAAI,QAAQ,QAAQ;AAClB,YAAM,cAAc,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,QAAQ,MAAM;AACxE,UAAI,eAAe,GAAG;AACpB,qBAAa,cAAc;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,MAAM,YAAY,aAAa,KAAK;AACvD,UAAM,UAAU,aAAa,QAAQ;AAErC,WAAO;AAAA,MACL,OAAO;AAAA,MACP;AAAA,MACA,YAAY,WAAW,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,CAAC,EAAE,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,OAA+C;AAClE,QAAI,KAAK,WAAW,KAAK,KAAK,MAAM,QAAQ,KAAK,UAAU;AACzD,YAAM,IAAI;AAAA,QACR,oCAAoC,KAAK,QAAQ;AAAA,MAEnD;AAAA,IACF;AAEA,UAAM,KAAK,QAAQ,EAAE,KAAK,OAAO;AACjC,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAGnC,QAAI,MAAM,UAAU;AAClB,YAAM,SAAS,KAAK,MAAM,IAAI,MAAM,QAAQ;AAC5C,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,+BAA+B,MAAM,QAAQ,EAAE;AAAA,MACjE;AACA,YAAM,gBAA0B;AAAA,QAC9B,GAAG;AAAA,QACH,aAAa,OAAO,cAAc,KAAK;AAAA,QACvC,WAAW;AAAA,MACb;AACA,WAAK,MAAM,IAAI,OAAO,IAAI,aAAa;AAAA,IACzC;AAEA,UAAM,OAAiB;AAAA,MACrB;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,UAAU,MAAM;AAAA,MAChB,OAAO;AAAA,QACL,MAAM,MAAM,MAAM;AAAA,QAClB,IAAI,MAAM,MAAM;AAAA,QAChB,GAAI,MAAM,MAAM,OAAO,EAAE,MAAM,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,QACrD,GAAI,MAAM,MAAM,YAAY,EAAE,WAAW,MAAM,MAAM,UAAU,IAAI,CAAC;AAAA,MACtE;AAAA,MACA,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,MACvD,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,MACrD,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,MAClD,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,MACrD,YAAY,MAAM,cAAc;AAAA,MAChC,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,IACb;AAEA,SAAK,MAAM,IAAI,IAAI,IAAI;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,QAAgB,OAA+C;AAClF,UAAM,WAAW,KAAK,MAAM,IAAI,MAAM;AACtC,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,wBAAwB,MAAM,EAAE;AAAA,IAClD;AAEA,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,UAAoB;AAAA,MACxB,GAAG;AAAA,MACH,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,MACvD,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,MACnE,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MACzE,WAAW;AAAA,MACX,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAEA,SAAK,MAAM,IAAI,QAAQ,OAAO;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,QAA+B;AAClD,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,wBAAwB,MAAM,EAAE;AAAA,IAClD;AAGA,QAAI,KAAK,UAAU;AACjB,YAAM,SAAS,KAAK,MAAM,IAAI,KAAK,QAAQ;AAC3C,UAAI,QAAQ;AACV,cAAM,gBAA0B;AAAA,UAC9B,GAAG;AAAA,UACH,YAAY,KAAK,IAAI,IAAI,OAAO,cAAc,KAAK,CAAC;AAAA,QACtD;AACA,aAAK,MAAM,IAAI,OAAO,IAAI,aAAa;AAAA,MACzC;AAAA,IACF;AAEA,SAAK,MAAM,OAAO,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,YAAY,QAA0C;AAC1D,WAAO,KAAK,MAAM,IAAI,MAAM,KAAK;AAAA,EACnC;AAAA,EAEA,MAAM,YAAY,QAAgB,OAAe,QAAqC;AACpF,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,wBAAwB,MAAM,EAAE;AAAA,IAClD;AAEA,UAAM,YAAY,CAAC,GAAI,KAAK,aAAa,CAAC,CAAE;AAC5C,UAAM,WAAW,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AAExD,QAAI,UAAU;AACZ,UAAI,SAAS,QAAQ,SAAS,MAAM,GAAG;AACrC,cAAM,IAAI,MAAM,4BAA4B,KAAK,OAAO,MAAM,EAAE;AAAA,MAClE;AACA,eAAS,UAAU,CAAC,GAAG,SAAS,SAAS,MAAM;AAC/C,eAAS,QAAQ,SAAS,QAAQ;AAAA,IACpC,OAAO;AACL,gBAAU,KAAK,EAAE,OAAO,SAAS,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC;AAAA,IACvD;AAEA,UAAM,UAAoB,EAAE,GAAG,MAAM,UAAU;AAC/C,SAAK,MAAM,IAAI,QAAQ,OAAO;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,QAAgB,OAAe,QAAqC;AACvF,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,wBAAwB,MAAM,EAAE;AAAA,IAClD;AAEA,QAAI,YAAY,CAAC,GAAI,KAAK,aAAa,CAAC,CAAE;AAC1C,UAAM,WAAW,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AAExD,QAAI,CAAC,YAAY,CAAC,SAAS,QAAQ,SAAS,MAAM,GAAG;AACnD,YAAM,IAAI,MAAM,uBAAuB,KAAK,OAAO,MAAM,EAAE;AAAA,IAC7D;AAEA,aAAS,UAAU,SAAS,QAAQ,OAAO,CAAC,OAAO,OAAO,MAAM;AAChE,aAAS,QAAQ,SAAS,QAAQ;AAGlC,gBAAY,UAAU,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;AAE/C,UAAM,UAAoB,EAAE,GAAG,MAAM,UAAU;AAC/C,SAAK,MAAM,IAAI,QAAQ,OAAO;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,OAAoD;AAClE,UAAM,MAAM,KAAK,gBAAgB,MAAM,QAAQ,MAAM,UAAU,MAAM,MAAM;AAC3E,UAAM,WAAW,KAAK,iBAAiB,MAAM,QAAQ,MAAM,UAAU,MAAM,MAAM;AAEjF,QAAI,UAAU;AAEZ,YAAM,UAA8B;AAAA,QAClC,GAAG;AAAA,QACH,QAAQ,MAAM,UAAU,SAAS;AAAA,QACjC,UAAU,MAAM,YAAY,SAAS;AAAA,QACrC,QAAQ;AAAA,MACV;AACA,WAAK,cAAc,IAAI,KAAK,OAAO;AACnC,aAAO;AAAA,IACT;AAEA,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,eAAmC;AAAA,MACvC,QAAQ,MAAM;AAAA,MACd,UAAU,MAAM;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,QAAQ,MAAM,UAAU,CAAC,KAAK;AAAA,MAC9B,UAAU,MAAM,YAAY,CAAC,QAAQ;AAAA,MACrC,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAEA,SAAK,cAAc,IAAI,KAAK,YAAY;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,QAAgB,UAAkB,QAAkC;AACpF,UAAM,MAAM,KAAK,gBAAgB,QAAQ,UAAU,MAAM;AACzD,WAAO,KAAK,cAAc,OAAO,GAAG;AAAA,EACtC;AAAA,EAEA,MAAM,gBACJ,QACA,UACA,QACoC;AACpC,WAAO,KAAK,iBAAiB,QAAQ,UAAU,MAAM;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,eAAuB;AACrB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA+B;AAC7B,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEQ,gBAAgB,QAAgB,UAAkB,QAAwB;AAChF,WAAO,GAAG,MAAM,IAAI,QAAQ,IAAI,MAAM;AAAA,EACxC;AAAA,EAEQ,iBACN,QACA,UACA,QAC2B;AAC3B,UAAM,MAAM,KAAK,gBAAgB,QAAQ,UAAU,MAAM;AACzD,WAAO,KAAK,cAAc,IAAI,GAAG,KAAK;AAAA,EACxC;AACF;;;AChUA,kBAAoC;AAU7B,IAAM,WAAW,yBAAa,OAAO;AAAA,EAC1C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,CAAC,QAAQ,UAAU,aAAa,YAAY;AAAA,EAE3D,QAAQ;AAAA,IACN,IAAI,kBAAM,KAAK;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,MAAM,kBAAM,OAAO;AAAA,MACjB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,SAAS;AAAA,QACP,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,QACrC,EAAE,OAAO,gBAAgB,OAAO,eAAe;AAAA,QAC/C,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,QACjC,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,QACjC,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,iBAAiB,OAAO,gBAAgB;AAAA,QACjD,EAAE,OAAO,iBAAiB,OAAO,gBAAgB;AAAA,QACjD,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,QACvC,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,QACrC,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,IAED,QAAQ,kBAAM,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,IAED,WAAW,kBAAM,KAAK;AAAA,MACpB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,IAED,YAAY,kBAAM,OAAO;AAAA,MACvB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,SAAS;AAAA,QACP,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,QACnC,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,QACrC,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,MAC7C;AAAA,IACF,CAAC;AAAA,IAED,UAAU,kBAAM,KAAK;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,kBAAM,KAAK;AAAA,MACrB,OAAO;AAAA,IACT,CAAC;AAAA,IAED,kBAAkB,kBAAM,IAAI;AAAA,MAC1B,OAAO;AAAA,IACT,CAAC;AAAA,IAED,MAAM,kBAAM,SAAS;AAAA,MACnB,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,UAAU,kBAAM,SAAS;AAAA,MACvB,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,SAAS,kBAAM,SAAS;AAAA,MACtB,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,kBAAM,SAAS;AAAA,MACxB,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,kBAAM,OAAO,aAAa;AAAA,MACnC,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,aAAa,kBAAM,OAAO;AAAA,MACxB,OAAO;AAAA,MACP,cAAc;AAAA,IAChB,CAAC;AAAA,IAED,YAAY,kBAAM,OAAO;AAAA,MACvB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,SAAS;AAAA,QACP,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,QACnC,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,QACvC,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,IAED,WAAW,kBAAM,QAAQ;AAAA,MACvB,OAAO;AAAA,MACP,cAAc;AAAA,IAChB,CAAC;AAAA,IAED,WAAW,kBAAM,SAAS;AAAA,MACxB,OAAO;AAAA,IACT,CAAC;AAAA,IAED,YAAY,kBAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,kBAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AAAA,IACP,EAAE,QAAQ,CAAC,UAAU,WAAW,GAAG,QAAQ,MAAM;AAAA,IACjD,EAAE,QAAQ,CAAC,UAAU,GAAG,QAAQ,MAAM;AAAA,IACtC,EAAE,QAAQ,CAAC,WAAW,GAAG,QAAQ,MAAM;AAAA,IACvC,EAAE,QAAQ,CAAC,YAAY,GAAG,QAAQ,MAAM;AAAA,EAC1C;AAAA,EAEA,QAAQ;AAAA,IACN,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY,CAAC,OAAO,QAAQ,UAAU,UAAU,QAAQ;AAAA,IACxD,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AACF,CAAC;;;AC/JD,IAAAA,eAAoC;AAU7B,IAAM,eAAe,0BAAa,OAAO;AAAA,EAC9C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,CAAC,gBAAgB,SAAS,SAAS;AAAA,EAElD,QAAQ;AAAA,IACN,IAAI,mBAAM,KAAK;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,cAAc,mBAAM,OAAO,aAAa;AAAA,MACtC,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,OAAO,mBAAM,KAAK;AAAA,MAChB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,SAAS,mBAAM,OAAO,YAAY;AAAA,MAChC,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,mBAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AAAA,IACP,EAAE,QAAQ,CAAC,gBAAgB,SAAS,SAAS,GAAG,QAAQ,KAAK;AAAA,IAC7D,EAAE,QAAQ,CAAC,cAAc,GAAG,QAAQ,MAAM;AAAA,IAC1C,EAAE,QAAQ,CAAC,SAAS,GAAG,QAAQ,MAAM;AAAA,EACvC;AAAA,EAEA,QAAQ;AAAA,IACN,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY,CAAC,OAAO,QAAQ,UAAU,QAAQ;AAAA,IAC9C,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AACF,CAAC;;;AC/DD,IAAAC,eAAoC;AAU7B,IAAM,qBAAqB,0BAAa,OAAO;AAAA,EACpD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,CAAC,UAAU,aAAa,WAAW,QAAQ;AAAA,EAE1D,QAAQ;AAAA,IACN,IAAI,mBAAM,KAAK;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,QAAQ,mBAAM,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,WAAW,mBAAM,KAAK;AAAA,MACpB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,SAAS,mBAAM,OAAO,YAAY;AAAA,MAChC,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,QAAQ,mBAAM,SAAS;AAAA,MACrB,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,UAAU,mBAAM,SAAS;AAAA,MACvB,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,IAED,QAAQ,mBAAM,QAAQ;AAAA,MACpB,OAAO;AAAA,MACP,cAAc;AAAA,IAChB,CAAC;AAAA,IAED,YAAY,mBAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AAAA,IACP,EAAE,QAAQ,CAAC,UAAU,aAAa,SAAS,GAAG,QAAQ,KAAK;AAAA,IAC3D,EAAE,QAAQ,CAAC,SAAS,GAAG,QAAQ,MAAM;AAAA,IACrC,EAAE,QAAQ,CAAC,UAAU,WAAW,GAAG,QAAQ,MAAM;AAAA,EACnD;AAAA,EAEA,QAAQ;AAAA,IACN,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY,CAAC,OAAO,QAAQ,UAAU,UAAU,QAAQ;AAAA,IACxD,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AACF,CAAC;;;ACrCM,IAAM,oBAAN,MAA0C;AAAA,EAQ/C,YAAY,UAAoC,CAAC,GAAG;AAPpD,gBAAO;AACP,mBAAU;AACV,gBAAO;AACP,wBAAe,CAAC,iCAAiC;AAK/C,SAAK,UAAU,EAAE,SAAS,UAAU,GAAG,QAAQ;AAAA,EACjD;AAAA,EAEA,MAAM,KAAK,KAAmC;AAC5C,UAAM,OAAO,IAAI,oBAAoB,KAAK,QAAQ,MAAM;AACxD,QAAI,gBAAgB,QAAQ,IAAI;AAGhC,QAAI,WAAuC,UAAU,EAAE,SAAS;AAAA,MAC9D,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,CAAC,UAAU,cAAc,kBAAkB;AAAA,IACtD,CAAC;AAED,QAAI,OAAO,KAAK,sDAAsD;AAAA,EACxE;AACF;","names":["import_data","import_data"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -350,6 +350,13 @@ declare const FeedItem: Omit<{
|
|
|
350
350
|
caseSensitive?: boolean | undefined;
|
|
351
351
|
autonumberFormat?: string | undefined;
|
|
352
352
|
}>;
|
|
353
|
+
_lock?: "full" | "none" | "no-overlay" | "no-delete" | undefined;
|
|
354
|
+
_lockReason?: string | undefined;
|
|
355
|
+
_lockSource?: "artifact" | "package" | "env-forced" | undefined;
|
|
356
|
+
_provenance?: "package" | "env-forced" | "org" | undefined;
|
|
357
|
+
_packageId?: string | undefined;
|
|
358
|
+
_packageVersion?: string | undefined;
|
|
359
|
+
_lockDocsUrl?: string | undefined;
|
|
353
360
|
label?: string | undefined;
|
|
354
361
|
pluralLabel?: string | undefined;
|
|
355
362
|
description?: string | undefined;
|
|
@@ -495,7 +502,7 @@ declare const FeedItem: Omit<{
|
|
|
495
502
|
wrap?: boolean | undefined;
|
|
496
503
|
type?: string | undefined;
|
|
497
504
|
pinned?: "left" | "right" | undefined;
|
|
498
|
-
summary?: "count" | "
|
|
505
|
+
summary?: "count" | "none" | "min" | "max" | "sum" | "avg" | "count_empty" | "count_filled" | "count_unique" | "percent_empty" | "percent_filled" | undefined;
|
|
499
506
|
link?: boolean | undefined;
|
|
500
507
|
action?: string | undefined;
|
|
501
508
|
}[];
|
|
@@ -544,7 +551,7 @@ declare const FeedItem: Omit<{
|
|
|
544
551
|
bordered?: boolean | undefined;
|
|
545
552
|
compactToolbar?: boolean | undefined;
|
|
546
553
|
selection?: {
|
|
547
|
-
type: "
|
|
554
|
+
type: "none" | "multiple" | "single";
|
|
548
555
|
} | undefined;
|
|
549
556
|
navigation?: {
|
|
550
557
|
mode: "none" | "split" | "page" | "modal" | "drawer" | "popover" | "new_window";
|
|
@@ -739,7 +746,7 @@ declare const FeedItem: Omit<{
|
|
|
739
746
|
apiMethods?: ("search" | "create" | "import" | "delete" | "list" | "get" | "update" | "upsert" | "history" | "bulk" | "aggregate" | "restore" | "purge" | "export")[] | undefined;
|
|
740
747
|
} | undefined;
|
|
741
748
|
recordTypes?: string[] | undefined;
|
|
742
|
-
sharingModel?: "private" | "
|
|
749
|
+
sharingModel?: "private" | "full" | "read" | "read_write" | undefined;
|
|
743
750
|
publicSharing?: {
|
|
744
751
|
enabled: boolean;
|
|
745
752
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -842,6 +849,11 @@ declare const FeedItem: Omit<{
|
|
|
842
849
|
role?: string | undefined;
|
|
843
850
|
} | undefined;
|
|
844
851
|
}[] | undefined;
|
|
852
|
+
protection?: {
|
|
853
|
+
lock: "full" | "none" | "no-overlay" | "no-delete";
|
|
854
|
+
reason: string;
|
|
855
|
+
docsUrl?: string | undefined;
|
|
856
|
+
} | undefined;
|
|
845
857
|
}, "fields"> & Pick<{
|
|
846
858
|
readonly name: "feed_item";
|
|
847
859
|
readonly label: "Feed Item";
|
|
@@ -4405,6 +4417,13 @@ declare const FeedReaction: Omit<{
|
|
|
4405
4417
|
caseSensitive?: boolean | undefined;
|
|
4406
4418
|
autonumberFormat?: string | undefined;
|
|
4407
4419
|
}>;
|
|
4420
|
+
_lock?: "full" | "none" | "no-overlay" | "no-delete" | undefined;
|
|
4421
|
+
_lockReason?: string | undefined;
|
|
4422
|
+
_lockSource?: "artifact" | "package" | "env-forced" | undefined;
|
|
4423
|
+
_provenance?: "package" | "env-forced" | "org" | undefined;
|
|
4424
|
+
_packageId?: string | undefined;
|
|
4425
|
+
_packageVersion?: string | undefined;
|
|
4426
|
+
_lockDocsUrl?: string | undefined;
|
|
4408
4427
|
label?: string | undefined;
|
|
4409
4428
|
pluralLabel?: string | undefined;
|
|
4410
4429
|
description?: string | undefined;
|
|
@@ -4550,7 +4569,7 @@ declare const FeedReaction: Omit<{
|
|
|
4550
4569
|
wrap?: boolean | undefined;
|
|
4551
4570
|
type?: string | undefined;
|
|
4552
4571
|
pinned?: "left" | "right" | undefined;
|
|
4553
|
-
summary?: "count" | "
|
|
4572
|
+
summary?: "count" | "none" | "min" | "max" | "sum" | "avg" | "count_empty" | "count_filled" | "count_unique" | "percent_empty" | "percent_filled" | undefined;
|
|
4554
4573
|
link?: boolean | undefined;
|
|
4555
4574
|
action?: string | undefined;
|
|
4556
4575
|
}[];
|
|
@@ -4599,7 +4618,7 @@ declare const FeedReaction: Omit<{
|
|
|
4599
4618
|
bordered?: boolean | undefined;
|
|
4600
4619
|
compactToolbar?: boolean | undefined;
|
|
4601
4620
|
selection?: {
|
|
4602
|
-
type: "
|
|
4621
|
+
type: "none" | "multiple" | "single";
|
|
4603
4622
|
} | undefined;
|
|
4604
4623
|
navigation?: {
|
|
4605
4624
|
mode: "none" | "split" | "page" | "modal" | "drawer" | "popover" | "new_window";
|
|
@@ -4794,7 +4813,7 @@ declare const FeedReaction: Omit<{
|
|
|
4794
4813
|
apiMethods?: ("search" | "create" | "import" | "delete" | "list" | "get" | "update" | "upsert" | "history" | "bulk" | "aggregate" | "restore" | "purge" | "export")[] | undefined;
|
|
4795
4814
|
} | undefined;
|
|
4796
4815
|
recordTypes?: string[] | undefined;
|
|
4797
|
-
sharingModel?: "private" | "
|
|
4816
|
+
sharingModel?: "private" | "full" | "read" | "read_write" | undefined;
|
|
4798
4817
|
publicSharing?: {
|
|
4799
4818
|
enabled: boolean;
|
|
4800
4819
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -4897,6 +4916,11 @@ declare const FeedReaction: Omit<{
|
|
|
4897
4916
|
role?: string | undefined;
|
|
4898
4917
|
} | undefined;
|
|
4899
4918
|
}[] | undefined;
|
|
4919
|
+
protection?: {
|
|
4920
|
+
lock: "full" | "none" | "no-overlay" | "no-delete";
|
|
4921
|
+
reason: string;
|
|
4922
|
+
docsUrl?: string | undefined;
|
|
4923
|
+
} | undefined;
|
|
4900
4924
|
}, "fields"> & Pick<{
|
|
4901
4925
|
readonly name: "feed_reaction";
|
|
4902
4926
|
readonly label: "Feed Reaction";
|
|
@@ -6007,6 +6031,13 @@ declare const RecordSubscription: Omit<{
|
|
|
6007
6031
|
caseSensitive?: boolean | undefined;
|
|
6008
6032
|
autonumberFormat?: string | undefined;
|
|
6009
6033
|
}>;
|
|
6034
|
+
_lock?: "full" | "none" | "no-overlay" | "no-delete" | undefined;
|
|
6035
|
+
_lockReason?: string | undefined;
|
|
6036
|
+
_lockSource?: "artifact" | "package" | "env-forced" | undefined;
|
|
6037
|
+
_provenance?: "package" | "env-forced" | "org" | undefined;
|
|
6038
|
+
_packageId?: string | undefined;
|
|
6039
|
+
_packageVersion?: string | undefined;
|
|
6040
|
+
_lockDocsUrl?: string | undefined;
|
|
6010
6041
|
label?: string | undefined;
|
|
6011
6042
|
pluralLabel?: string | undefined;
|
|
6012
6043
|
description?: string | undefined;
|
|
@@ -6152,7 +6183,7 @@ declare const RecordSubscription: Omit<{
|
|
|
6152
6183
|
wrap?: boolean | undefined;
|
|
6153
6184
|
type?: string | undefined;
|
|
6154
6185
|
pinned?: "left" | "right" | undefined;
|
|
6155
|
-
summary?: "count" | "
|
|
6186
|
+
summary?: "count" | "none" | "min" | "max" | "sum" | "avg" | "count_empty" | "count_filled" | "count_unique" | "percent_empty" | "percent_filled" | undefined;
|
|
6156
6187
|
link?: boolean | undefined;
|
|
6157
6188
|
action?: string | undefined;
|
|
6158
6189
|
}[];
|
|
@@ -6201,7 +6232,7 @@ declare const RecordSubscription: Omit<{
|
|
|
6201
6232
|
bordered?: boolean | undefined;
|
|
6202
6233
|
compactToolbar?: boolean | undefined;
|
|
6203
6234
|
selection?: {
|
|
6204
|
-
type: "
|
|
6235
|
+
type: "none" | "multiple" | "single";
|
|
6205
6236
|
} | undefined;
|
|
6206
6237
|
navigation?: {
|
|
6207
6238
|
mode: "none" | "split" | "page" | "modal" | "drawer" | "popover" | "new_window";
|
|
@@ -6396,7 +6427,7 @@ declare const RecordSubscription: Omit<{
|
|
|
6396
6427
|
apiMethods?: ("search" | "create" | "import" | "delete" | "list" | "get" | "update" | "upsert" | "history" | "bulk" | "aggregate" | "restore" | "purge" | "export")[] | undefined;
|
|
6397
6428
|
} | undefined;
|
|
6398
6429
|
recordTypes?: string[] | undefined;
|
|
6399
|
-
sharingModel?: "private" | "
|
|
6430
|
+
sharingModel?: "private" | "full" | "read" | "read_write" | undefined;
|
|
6400
6431
|
publicSharing?: {
|
|
6401
6432
|
enabled: boolean;
|
|
6402
6433
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -6499,6 +6530,11 @@ declare const RecordSubscription: Omit<{
|
|
|
6499
6530
|
role?: string | undefined;
|
|
6500
6531
|
} | undefined;
|
|
6501
6532
|
}[] | undefined;
|
|
6533
|
+
protection?: {
|
|
6534
|
+
lock: "full" | "none" | "no-overlay" | "no-delete";
|
|
6535
|
+
reason: string;
|
|
6536
|
+
docsUrl?: string | undefined;
|
|
6537
|
+
} | undefined;
|
|
6502
6538
|
}, "fields"> & Pick<{
|
|
6503
6539
|
readonly name: "record_subscription";
|
|
6504
6540
|
readonly label: "Record Subscription";
|
package/dist/index.d.ts
CHANGED
|
@@ -350,6 +350,13 @@ declare const FeedItem: Omit<{
|
|
|
350
350
|
caseSensitive?: boolean | undefined;
|
|
351
351
|
autonumberFormat?: string | undefined;
|
|
352
352
|
}>;
|
|
353
|
+
_lock?: "full" | "none" | "no-overlay" | "no-delete" | undefined;
|
|
354
|
+
_lockReason?: string | undefined;
|
|
355
|
+
_lockSource?: "artifact" | "package" | "env-forced" | undefined;
|
|
356
|
+
_provenance?: "package" | "env-forced" | "org" | undefined;
|
|
357
|
+
_packageId?: string | undefined;
|
|
358
|
+
_packageVersion?: string | undefined;
|
|
359
|
+
_lockDocsUrl?: string | undefined;
|
|
353
360
|
label?: string | undefined;
|
|
354
361
|
pluralLabel?: string | undefined;
|
|
355
362
|
description?: string | undefined;
|
|
@@ -495,7 +502,7 @@ declare const FeedItem: Omit<{
|
|
|
495
502
|
wrap?: boolean | undefined;
|
|
496
503
|
type?: string | undefined;
|
|
497
504
|
pinned?: "left" | "right" | undefined;
|
|
498
|
-
summary?: "count" | "
|
|
505
|
+
summary?: "count" | "none" | "min" | "max" | "sum" | "avg" | "count_empty" | "count_filled" | "count_unique" | "percent_empty" | "percent_filled" | undefined;
|
|
499
506
|
link?: boolean | undefined;
|
|
500
507
|
action?: string | undefined;
|
|
501
508
|
}[];
|
|
@@ -544,7 +551,7 @@ declare const FeedItem: Omit<{
|
|
|
544
551
|
bordered?: boolean | undefined;
|
|
545
552
|
compactToolbar?: boolean | undefined;
|
|
546
553
|
selection?: {
|
|
547
|
-
type: "
|
|
554
|
+
type: "none" | "multiple" | "single";
|
|
548
555
|
} | undefined;
|
|
549
556
|
navigation?: {
|
|
550
557
|
mode: "none" | "split" | "page" | "modal" | "drawer" | "popover" | "new_window";
|
|
@@ -739,7 +746,7 @@ declare const FeedItem: Omit<{
|
|
|
739
746
|
apiMethods?: ("search" | "create" | "import" | "delete" | "list" | "get" | "update" | "upsert" | "history" | "bulk" | "aggregate" | "restore" | "purge" | "export")[] | undefined;
|
|
740
747
|
} | undefined;
|
|
741
748
|
recordTypes?: string[] | undefined;
|
|
742
|
-
sharingModel?: "private" | "
|
|
749
|
+
sharingModel?: "private" | "full" | "read" | "read_write" | undefined;
|
|
743
750
|
publicSharing?: {
|
|
744
751
|
enabled: boolean;
|
|
745
752
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -842,6 +849,11 @@ declare const FeedItem: Omit<{
|
|
|
842
849
|
role?: string | undefined;
|
|
843
850
|
} | undefined;
|
|
844
851
|
}[] | undefined;
|
|
852
|
+
protection?: {
|
|
853
|
+
lock: "full" | "none" | "no-overlay" | "no-delete";
|
|
854
|
+
reason: string;
|
|
855
|
+
docsUrl?: string | undefined;
|
|
856
|
+
} | undefined;
|
|
845
857
|
}, "fields"> & Pick<{
|
|
846
858
|
readonly name: "feed_item";
|
|
847
859
|
readonly label: "Feed Item";
|
|
@@ -4405,6 +4417,13 @@ declare const FeedReaction: Omit<{
|
|
|
4405
4417
|
caseSensitive?: boolean | undefined;
|
|
4406
4418
|
autonumberFormat?: string | undefined;
|
|
4407
4419
|
}>;
|
|
4420
|
+
_lock?: "full" | "none" | "no-overlay" | "no-delete" | undefined;
|
|
4421
|
+
_lockReason?: string | undefined;
|
|
4422
|
+
_lockSource?: "artifact" | "package" | "env-forced" | undefined;
|
|
4423
|
+
_provenance?: "package" | "env-forced" | "org" | undefined;
|
|
4424
|
+
_packageId?: string | undefined;
|
|
4425
|
+
_packageVersion?: string | undefined;
|
|
4426
|
+
_lockDocsUrl?: string | undefined;
|
|
4408
4427
|
label?: string | undefined;
|
|
4409
4428
|
pluralLabel?: string | undefined;
|
|
4410
4429
|
description?: string | undefined;
|
|
@@ -4550,7 +4569,7 @@ declare const FeedReaction: Omit<{
|
|
|
4550
4569
|
wrap?: boolean | undefined;
|
|
4551
4570
|
type?: string | undefined;
|
|
4552
4571
|
pinned?: "left" | "right" | undefined;
|
|
4553
|
-
summary?: "count" | "
|
|
4572
|
+
summary?: "count" | "none" | "min" | "max" | "sum" | "avg" | "count_empty" | "count_filled" | "count_unique" | "percent_empty" | "percent_filled" | undefined;
|
|
4554
4573
|
link?: boolean | undefined;
|
|
4555
4574
|
action?: string | undefined;
|
|
4556
4575
|
}[];
|
|
@@ -4599,7 +4618,7 @@ declare const FeedReaction: Omit<{
|
|
|
4599
4618
|
bordered?: boolean | undefined;
|
|
4600
4619
|
compactToolbar?: boolean | undefined;
|
|
4601
4620
|
selection?: {
|
|
4602
|
-
type: "
|
|
4621
|
+
type: "none" | "multiple" | "single";
|
|
4603
4622
|
} | undefined;
|
|
4604
4623
|
navigation?: {
|
|
4605
4624
|
mode: "none" | "split" | "page" | "modal" | "drawer" | "popover" | "new_window";
|
|
@@ -4794,7 +4813,7 @@ declare const FeedReaction: Omit<{
|
|
|
4794
4813
|
apiMethods?: ("search" | "create" | "import" | "delete" | "list" | "get" | "update" | "upsert" | "history" | "bulk" | "aggregate" | "restore" | "purge" | "export")[] | undefined;
|
|
4795
4814
|
} | undefined;
|
|
4796
4815
|
recordTypes?: string[] | undefined;
|
|
4797
|
-
sharingModel?: "private" | "
|
|
4816
|
+
sharingModel?: "private" | "full" | "read" | "read_write" | undefined;
|
|
4798
4817
|
publicSharing?: {
|
|
4799
4818
|
enabled: boolean;
|
|
4800
4819
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -4897,6 +4916,11 @@ declare const FeedReaction: Omit<{
|
|
|
4897
4916
|
role?: string | undefined;
|
|
4898
4917
|
} | undefined;
|
|
4899
4918
|
}[] | undefined;
|
|
4919
|
+
protection?: {
|
|
4920
|
+
lock: "full" | "none" | "no-overlay" | "no-delete";
|
|
4921
|
+
reason: string;
|
|
4922
|
+
docsUrl?: string | undefined;
|
|
4923
|
+
} | undefined;
|
|
4900
4924
|
}, "fields"> & Pick<{
|
|
4901
4925
|
readonly name: "feed_reaction";
|
|
4902
4926
|
readonly label: "Feed Reaction";
|
|
@@ -6007,6 +6031,13 @@ declare const RecordSubscription: Omit<{
|
|
|
6007
6031
|
caseSensitive?: boolean | undefined;
|
|
6008
6032
|
autonumberFormat?: string | undefined;
|
|
6009
6033
|
}>;
|
|
6034
|
+
_lock?: "full" | "none" | "no-overlay" | "no-delete" | undefined;
|
|
6035
|
+
_lockReason?: string | undefined;
|
|
6036
|
+
_lockSource?: "artifact" | "package" | "env-forced" | undefined;
|
|
6037
|
+
_provenance?: "package" | "env-forced" | "org" | undefined;
|
|
6038
|
+
_packageId?: string | undefined;
|
|
6039
|
+
_packageVersion?: string | undefined;
|
|
6040
|
+
_lockDocsUrl?: string | undefined;
|
|
6010
6041
|
label?: string | undefined;
|
|
6011
6042
|
pluralLabel?: string | undefined;
|
|
6012
6043
|
description?: string | undefined;
|
|
@@ -6152,7 +6183,7 @@ declare const RecordSubscription: Omit<{
|
|
|
6152
6183
|
wrap?: boolean | undefined;
|
|
6153
6184
|
type?: string | undefined;
|
|
6154
6185
|
pinned?: "left" | "right" | undefined;
|
|
6155
|
-
summary?: "count" | "
|
|
6186
|
+
summary?: "count" | "none" | "min" | "max" | "sum" | "avg" | "count_empty" | "count_filled" | "count_unique" | "percent_empty" | "percent_filled" | undefined;
|
|
6156
6187
|
link?: boolean | undefined;
|
|
6157
6188
|
action?: string | undefined;
|
|
6158
6189
|
}[];
|
|
@@ -6201,7 +6232,7 @@ declare const RecordSubscription: Omit<{
|
|
|
6201
6232
|
bordered?: boolean | undefined;
|
|
6202
6233
|
compactToolbar?: boolean | undefined;
|
|
6203
6234
|
selection?: {
|
|
6204
|
-
type: "
|
|
6235
|
+
type: "none" | "multiple" | "single";
|
|
6205
6236
|
} | undefined;
|
|
6206
6237
|
navigation?: {
|
|
6207
6238
|
mode: "none" | "split" | "page" | "modal" | "drawer" | "popover" | "new_window";
|
|
@@ -6396,7 +6427,7 @@ declare const RecordSubscription: Omit<{
|
|
|
6396
6427
|
apiMethods?: ("search" | "create" | "import" | "delete" | "list" | "get" | "update" | "upsert" | "history" | "bulk" | "aggregate" | "restore" | "purge" | "export")[] | undefined;
|
|
6397
6428
|
} | undefined;
|
|
6398
6429
|
recordTypes?: string[] | undefined;
|
|
6399
|
-
sharingModel?: "private" | "
|
|
6430
|
+
sharingModel?: "private" | "full" | "read" | "read_write" | undefined;
|
|
6400
6431
|
publicSharing?: {
|
|
6401
6432
|
enabled: boolean;
|
|
6402
6433
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -6499,6 +6530,11 @@ declare const RecordSubscription: Omit<{
|
|
|
6499
6530
|
role?: string | undefined;
|
|
6500
6531
|
} | undefined;
|
|
6501
6532
|
}[] | undefined;
|
|
6533
|
+
protection?: {
|
|
6534
|
+
lock: "full" | "none" | "no-overlay" | "no-delete";
|
|
6535
|
+
reason: string;
|
|
6536
|
+
docsUrl?: string | undefined;
|
|
6537
|
+
} | undefined;
|
|
6502
6538
|
}, "fields"> & Pick<{
|
|
6503
6539
|
readonly name: "record_subscription";
|
|
6504
6540
|
readonly label: "Record Subscription";
|
package/dist/index.js
CHANGED
|
@@ -481,7 +481,7 @@ var FeedServicePlugin = class {
|
|
|
481
481
|
name: "Feed Service",
|
|
482
482
|
version: "1.0.0",
|
|
483
483
|
type: "plugin",
|
|
484
|
-
scope: "
|
|
484
|
+
scope: "system",
|
|
485
485
|
objects: [FeedItem, FeedReaction, RecordSubscription]
|
|
486
486
|
});
|
|
487
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: '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"]}
|
|
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: 'system',\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": "7.1
|
|
3
|
+
"version": "7.2.1",
|
|
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,8 +14,8 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@objectstack/core": "7.1
|
|
18
|
-
"@objectstack/spec": "7.1
|
|
17
|
+
"@objectstack/core": "7.2.1",
|
|
18
|
+
"@objectstack/spec": "7.2.1"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/node": "^25.9.1",
|