@objectstack/service-realtime 9.4.0 → 9.5.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 +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -397,12 +397,13 @@ var SysPresence = import_data.ObjectSchema.create({
|
|
|
397
397
|
});
|
|
398
398
|
|
|
399
399
|
// src/in-memory-realtime-adapter.ts
|
|
400
|
+
var DEFAULT_MAX_SUBSCRIPTIONS = 5e4;
|
|
400
401
|
var InMemoryRealtimeAdapter = class {
|
|
401
402
|
constructor(options = {}) {
|
|
402
403
|
this.subscriptions = /* @__PURE__ */ new Map();
|
|
403
404
|
this.channelIndex = /* @__PURE__ */ new Map();
|
|
404
405
|
this.counter = 0;
|
|
405
|
-
this.maxSubscriptions = options.maxSubscriptions ??
|
|
406
|
+
this.maxSubscriptions = options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS;
|
|
406
407
|
}
|
|
407
408
|
async publish(event) {
|
|
408
409
|
for (const sub of this.subscriptions.values()) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/translations/en.objects.generated.ts","../src/translations/zh-CN.objects.generated.ts","../src/translations/ja-JP.objects.generated.ts","../src/translations/es-ES.objects.generated.ts","../src/translations/index.ts","../src/index.ts","../src/objects/sys-presence.object.ts","../src/in-memory-realtime-adapter.ts","../src/realtime-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'en'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const enObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presence\",\n pluralLabel: \"Presences\",\n description: \"Real-time user presence and activity tracking\",\n fields: {\n id: {\n label: \"Presence ID\"\n },\n created_at: {\n label: \"Created At\"\n },\n updated_at: {\n label: \"Updated At\"\n },\n user_id: {\n label: \"User\"\n },\n session_id: {\n label: \"Session\"\n },\n status: {\n label: \"Status\",\n options: {\n online: \"Online\",\n away: \"Away\",\n busy: \"Busy\",\n offline: \"Offline\"\n }\n },\n last_seen: {\n label: \"Last Seen\"\n },\n current_location: {\n label: \"Current Location\"\n },\n device: {\n label: \"Device\",\n options: {\n desktop: \"Desktop\",\n mobile: \"Mobile\",\n tablet: \"Tablet\",\n other: \"Other\"\n }\n },\n custom_status: {\n label: \"Custom Status\"\n },\n metadata: {\n label: \"Metadata\",\n help: \"Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'zh-CN'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const zhCNObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在线状态\",\n pluralLabel: \"在线状态\",\n description: \"实时用户在线与活动跟踪\",\n fields: {\n id: {\n label: \"在线状态 ID\"\n },\n created_at: {\n label: \"创建时间\"\n },\n updated_at: {\n label: \"更新时间\"\n },\n user_id: {\n label: \"用户\"\n },\n session_id: {\n label: \"会话\"\n },\n status: {\n label: \"状态\",\n options: {\n online: \"在线\",\n away: \"离开\",\n busy: \"忙碌\",\n offline: \"离线\"\n }\n },\n last_seen: {\n label: \"最近在线时间\"\n },\n current_location: {\n label: \"当前位置\"\n },\n device: {\n label: \"设备\",\n options: {\n desktop: \"桌面端\",\n mobile: \"移动端\",\n tablet: \"平板端\",\n other: \"其他\"\n }\n },\n custom_status: {\n label: \"自定义状态\"\n },\n metadata: {\n label: \"元数据\",\n help: \"与在线状态关联的任意 JSON 元数据(对应 PresenceStateSchema.metadata)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'ja-JP'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const jaJPObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在席状況\",\n pluralLabel: \"在席状況\",\n description: \"リアルタイムのユーザー在席状況とアクティビティ追跡\",\n fields: {\n id: {\n label: \"在席 ID\"\n },\n created_at: {\n label: \"作成日時\"\n },\n updated_at: {\n label: \"更新日時\"\n },\n user_id: {\n label: \"ユーザー\"\n },\n session_id: {\n label: \"セッション\"\n },\n status: {\n label: \"ステータス\",\n options: {\n online: \"オンライン\",\n away: \"離席中\",\n busy: \"取り込み中\",\n offline: \"オフライン\"\n }\n },\n last_seen: {\n label: \"最終確認日時\"\n },\n current_location: {\n label: \"現在地\"\n },\n device: {\n label: \"デバイス\",\n options: {\n desktop: \"デスクトップ\",\n mobile: \"モバイル\",\n tablet: \"タブレット\",\n other: \"その他\"\n }\n },\n custom_status: {\n label: \"カスタムステータス\"\n },\n metadata: {\n label: \"メタデータ\",\n help: \"在席状態に関連付けられた任意の JSON メタデータ(PresenceStateSchema.metadata に対応)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'es-ES'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const esESObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presencia\",\n pluralLabel: \"Presencias\",\n description: \"Seguimiento en tiempo real de presencia y actividad de usuarios\",\n fields: {\n id: {\n label: \"ID de presencia\"\n },\n created_at: {\n label: \"Creado el\"\n },\n updated_at: {\n label: \"Actualizado el\"\n },\n user_id: {\n label: \"Usuario\"\n },\n session_id: {\n label: \"Sesión\"\n },\n status: {\n label: \"Estado\",\n options: {\n online: \"En línea\",\n away: \"Ausente\",\n busy: \"Ocupado\",\n offline: \"Desconectado\"\n }\n },\n last_seen: {\n label: \"Visto por última vez\"\n },\n current_location: {\n label: \"Ubicación actual\"\n },\n device: {\n label: \"Dispositivo\",\n options: {\n desktop: \"Escritorio\",\n mobile: \"Móvil\",\n tablet: \"Tableta\",\n other: \"Otro\"\n }\n },\n custom_status: {\n label: \"Estado personalizado\"\n },\n metadata: {\n label: \"Metadatos\",\n help: \"Metadatos JSON arbitrarios asociados al estado de presencia (coincide con PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * RealtimeTranslations — i18n bundle owned by this service plugin\n * (ADR-0029 D8).\n *\n * Object label/field/view/action translations for sys_presence, the object\n * this plugin owns. Loaded at runtime via the plugin's `kernel:ready` hook\n * (`i18n.loadTranslations`). Regenerate with `os i18n extract` against\n * `scripts/i18n-extract.config.ts`.\n */\n\nimport type { TranslationBundle } from '@objectstack/spec/system';\nimport { enObjects } from './en.objects.generated.js';\nimport { zhCNObjects } from './zh-CN.objects.generated.js';\nimport { jaJPObjects } from './ja-JP.objects.generated.js';\nimport { esESObjects } from './es-ES.objects.generated.js';\n\nexport const RealtimeTranslations: TranslationBundle = {\n en: { objects: enObjects },\n 'zh-CN': { objects: zhCNObjects },\n 'ja-JP': { objects: jaJPObjects },\n 'es-ES': { objects: esESObjects },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport { RealtimeServicePlugin } from './realtime-service-plugin.js';\nexport type { RealtimeServicePluginOptions } from './realtime-service-plugin.js';\nexport { InMemoryRealtimeAdapter } from './in-memory-realtime-adapter.js';\nexport type { InMemoryRealtimeAdapterOptions } from './in-memory-realtime-adapter.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_presence — System Presence Object\n *\n * Tracks real-time user presence and activity across the platform.\n * Fields align with the PresenceStateSchema protocol definition\n * from `@objectstack/spec/api` (websocket.zod.ts).\n *\n * Owned by `service-realtime` as the canonical Presence domain object.\n *\n * @namespace sys\n * @see PresenceStateSchema in packages/spec/src/api/websocket.zod.ts\n */\nexport const SysPresence = ObjectSchema.create({\n name: 'sys_presence',\n label: 'Presence',\n pluralLabel: 'Presences',\n icon: 'wifi',\n isSystem: true,\n managedBy: 'append-only',\n description: 'Real-time user presence and activity tracking',\n titleFormat: '{user_id} ({status})',\n compactLayout: ['user_id', 'status', 'last_seen'],\n\n fields: {\n id: Field.text({\n label: 'Presence ID',\n required: true,\n readonly: true,\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 user_id: Field.lookup('sys_user', {\n label: 'User',\n required: true,\n searchable: true,\n }),\n\n session_id: Field.lookup('sys_session', {\n label: 'Session',\n required: true,\n }),\n\n status: Field.select({\n label: 'Status',\n required: true,\n defaultValue: 'online',\n options: [\n { value: 'online', label: 'Online' },\n { value: 'away', label: 'Away' },\n { value: 'busy', label: 'Busy' },\n { value: 'offline', label: 'Offline' },\n ],\n }),\n\n last_seen: Field.datetime({\n label: 'Last Seen',\n required: true,\n defaultValue: 'NOW()',\n }),\n\n current_location: Field.text({\n label: 'Current Location',\n required: false,\n maxLength: 500,\n }),\n\n device: Field.select({\n label: 'Device',\n required: false,\n options: [\n { value: 'desktop', label: 'Desktop' },\n { value: 'mobile', label: 'Mobile' },\n { value: 'tablet', label: 'Tablet' },\n { value: 'other', label: 'Other' },\n ],\n }),\n\n custom_status: Field.text({\n label: 'Custom Status',\n required: false,\n maxLength: 255,\n }),\n\n metadata: Field.json({\n label: 'Metadata',\n required: false,\n description: 'Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).',\n }),\n },\n\n indexes: [\n { fields: ['user_id'], unique: false },\n { fields: ['session_id'], unique: true },\n { fields: ['status'], 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 {\n IRealtimeService,\n RealtimeEventPayload,\n RealtimeEventHandler,\n RealtimeSubscriptionOptions,\n} from '@objectstack/spec/contracts';\n\n/**\n * Internal subscription entry.\n */\ninterface Subscription {\n id: string;\n channel: string;\n handler: RealtimeEventHandler;\n options?: RealtimeSubscriptionOptions;\n}\n\n/**\n * Configuration options for InMemoryRealtimeAdapter.\n */\nexport interface InMemoryRealtimeAdapterOptions {\n /** Maximum number of subscriptions allowed (0 = unlimited) */\n maxSubscriptions?: number;\n}\n\n/**\n * In-memory pub/sub adapter implementing IRealtimeService.\n *\n * Uses a Map-backed subscription store with channel-based routing.\n * Supports event type and object filtering via subscription options.\n *\n * Suitable for single-process environments, development, and testing.\n * For production multi-instance deployments, use a Redis-backed adapter.\n *\n * @example\n * ```ts\n * const realtime = new InMemoryRealtimeAdapter();\n *\n * const subId = await realtime.subscribe('records', (event) => {\n * console.log('Received:', event.type, event.payload);\n * }, { object: 'account', eventTypes: ['record.created'] });\n *\n * await realtime.publish({\n * type: 'record.created',\n * object: 'account',\n * payload: { id: 'acc-1', name: 'Acme' },\n * timestamp: new Date().toISOString(),\n * });\n *\n * await realtime.unsubscribe(subId);\n * ```\n */\nexport class InMemoryRealtimeAdapter implements IRealtimeService {\n private readonly subscriptions = new Map<string, Subscription>();\n private readonly channelIndex = new Map<string, Set<string>>();\n private counter = 0;\n private readonly maxSubscriptions: number;\n\n constructor(options: InMemoryRealtimeAdapterOptions = {}) {\n this.maxSubscriptions = options.maxSubscriptions ?? 0;\n }\n\n async publish(event: RealtimeEventPayload): Promise<void> {\n // Deliver to all channel subscriptions that match filters\n for (const sub of this.subscriptions.values()) {\n if (this.matchesSubscription(event, sub)) {\n try {\n await sub.handler(event);\n } catch {\n // Swallow handler errors to avoid breaking the publish loop\n }\n }\n }\n }\n\n async subscribe(\n channel: string,\n handler: RealtimeEventHandler,\n options?: RealtimeSubscriptionOptions,\n ): Promise<string> {\n if (this.maxSubscriptions > 0 && this.subscriptions.size >= this.maxSubscriptions) {\n throw new Error(\n `Maximum subscription limit reached (${this.maxSubscriptions}). ` +\n 'Unsubscribe from existing channels before adding new subscriptions.',\n );\n }\n\n const id = `sub-${++this.counter}`;\n const sub: Subscription = { id, channel, handler, options };\n this.subscriptions.set(id, sub);\n\n // Maintain channel index for efficient lookups\n if (!this.channelIndex.has(channel)) {\n this.channelIndex.set(channel, new Set());\n }\n this.channelIndex.get(channel)!.add(id);\n\n return id;\n }\n\n async unsubscribe(subscriptionId: string): Promise<void> {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n\n this.subscriptions.delete(subscriptionId);\n\n // Clean up channel index\n const channelSubs = this.channelIndex.get(sub.channel);\n if (channelSubs) {\n channelSubs.delete(subscriptionId);\n if (channelSubs.size === 0) {\n this.channelIndex.delete(sub.channel);\n }\n }\n }\n\n /**\n * Get the number of active subscriptions.\n */\n getSubscriptionCount(): number {\n return this.subscriptions.size;\n }\n\n /**\n * Get all active channel names.\n */\n getChannels(): string[] {\n return Array.from(this.channelIndex.keys());\n }\n\n /**\n * Check if an event matches a subscription's filters.\n */\n private matchesSubscription(event: RealtimeEventPayload, sub: Subscription): boolean {\n const opts = sub.options;\n if (!opts) return true;\n\n // Filter by object name\n if (opts.object && event.object !== opts.object) {\n return false;\n }\n\n // Filter by event types\n if (opts.eventTypes && opts.eventTypes.length > 0) {\n if (!opts.eventTypes.includes(event.type)) {\n return false;\n }\n }\n\n return true;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysPresence } from './objects/index.js';\nimport { InMemoryRealtimeAdapter } from './in-memory-realtime-adapter.js';\nimport type { InMemoryRealtimeAdapterOptions } from './in-memory-realtime-adapter.js';\n\n/**\n * Configuration options for the RealtimeServicePlugin.\n */\nexport interface RealtimeServicePluginOptions {\n /** Realtime adapter type (default: 'memory') */\n adapter?: 'memory';\n /** Options for the in-memory adapter */\n memory?: InMemoryRealtimeAdapterOptions;\n}\n\n/**\n * RealtimeServicePlugin — Production IRealtimeService implementation.\n *\n * Registers a realtime pub/sub service with the kernel during the init phase.\n * Currently supports in-memory pub/sub for single-process environments.\n *\n * @example\n * ```ts\n * import { ObjectKernel } from '@objectstack/core';\n * import { RealtimeServicePlugin } from '@objectstack/service-realtime';\n *\n * const kernel = new ObjectKernel();\n * kernel.use(new RealtimeServicePlugin());\n * await kernel.bootstrap();\n *\n * const realtime = kernel.getService('realtime');\n * await realtime.subscribe('records', (event) => {\n * console.log(event.type, event.payload);\n * });\n * ```\n */\nexport class RealtimeServicePlugin implements Plugin {\n name = 'com.objectstack.service.realtime';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: RealtimeServicePluginOptions;\n\n constructor(options: RealtimeServicePluginOptions = {}) {\n this.options = { adapter: 'memory', ...options };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const realtime = new InMemoryRealtimeAdapter(this.options.memory);\n ctx.registerService('realtime', realtime);\n\n // Register realtime system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.service.realtime',\n name: 'Realtime Service',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n namespace: 'sys',\n objects: [SysPresence],\n });\n\n // ADR-0029 D8 — contribute sys_presence translations on kernel:ready.\n if (typeof (ctx as any).hook === 'function') {\n (ctx as any).hook('kernel:ready', async () => {\n try {\n const i18n = ctx.getService<any>('i18n');\n if (i18n && typeof i18n.loadTranslations === 'function') {\n const { RealtimeTranslations } = await import('./translations/index.js');\n for (const [locale, data] of Object.entries(RealtimeTranslations)) {\n i18n.loadTranslations(locale, data as Record<string, unknown>);\n }\n }\n } catch { /* i18n optional */ }\n });\n }\n\n ctx.logger.info('RealtimeServicePlugin: registered in-memory realtime adapter');\n }\n}\n"],"mappings":"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","names":["RealtimeTranslations"]}
|
|
1
|
+
{"version":3,"sources":["../src/translations/en.objects.generated.ts","../src/translations/zh-CN.objects.generated.ts","../src/translations/ja-JP.objects.generated.ts","../src/translations/es-ES.objects.generated.ts","../src/translations/index.ts","../src/index.ts","../src/objects/sys-presence.object.ts","../src/in-memory-realtime-adapter.ts","../src/realtime-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'en'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const enObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presence\",\n pluralLabel: \"Presences\",\n description: \"Real-time user presence and activity tracking\",\n fields: {\n id: {\n label: \"Presence ID\"\n },\n created_at: {\n label: \"Created At\"\n },\n updated_at: {\n label: \"Updated At\"\n },\n user_id: {\n label: \"User\"\n },\n session_id: {\n label: \"Session\"\n },\n status: {\n label: \"Status\",\n options: {\n online: \"Online\",\n away: \"Away\",\n busy: \"Busy\",\n offline: \"Offline\"\n }\n },\n last_seen: {\n label: \"Last Seen\"\n },\n current_location: {\n label: \"Current Location\"\n },\n device: {\n label: \"Device\",\n options: {\n desktop: \"Desktop\",\n mobile: \"Mobile\",\n tablet: \"Tablet\",\n other: \"Other\"\n }\n },\n custom_status: {\n label: \"Custom Status\"\n },\n metadata: {\n label: \"Metadata\",\n help: \"Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'zh-CN'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const zhCNObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在线状态\",\n pluralLabel: \"在线状态\",\n description: \"实时用户在线与活动跟踪\",\n fields: {\n id: {\n label: \"在线状态 ID\"\n },\n created_at: {\n label: \"创建时间\"\n },\n updated_at: {\n label: \"更新时间\"\n },\n user_id: {\n label: \"用户\"\n },\n session_id: {\n label: \"会话\"\n },\n status: {\n label: \"状态\",\n options: {\n online: \"在线\",\n away: \"离开\",\n busy: \"忙碌\",\n offline: \"离线\"\n }\n },\n last_seen: {\n label: \"最近在线时间\"\n },\n current_location: {\n label: \"当前位置\"\n },\n device: {\n label: \"设备\",\n options: {\n desktop: \"桌面端\",\n mobile: \"移动端\",\n tablet: \"平板端\",\n other: \"其他\"\n }\n },\n custom_status: {\n label: \"自定义状态\"\n },\n metadata: {\n label: \"元数据\",\n help: \"与在线状态关联的任意 JSON 元数据(对应 PresenceStateSchema.metadata)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'ja-JP'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const jaJPObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在席状況\",\n pluralLabel: \"在席状況\",\n description: \"リアルタイムのユーザー在席状況とアクティビティ追跡\",\n fields: {\n id: {\n label: \"在席 ID\"\n },\n created_at: {\n label: \"作成日時\"\n },\n updated_at: {\n label: \"更新日時\"\n },\n user_id: {\n label: \"ユーザー\"\n },\n session_id: {\n label: \"セッション\"\n },\n status: {\n label: \"ステータス\",\n options: {\n online: \"オンライン\",\n away: \"離席中\",\n busy: \"取り込み中\",\n offline: \"オフライン\"\n }\n },\n last_seen: {\n label: \"最終確認日時\"\n },\n current_location: {\n label: \"現在地\"\n },\n device: {\n label: \"デバイス\",\n options: {\n desktop: \"デスクトップ\",\n mobile: \"モバイル\",\n tablet: \"タブレット\",\n other: \"その他\"\n }\n },\n custom_status: {\n label: \"カスタムステータス\"\n },\n metadata: {\n label: \"メタデータ\",\n help: \"在席状態に関連付けられた任意の JSON メタデータ(PresenceStateSchema.metadata に対応)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'es-ES'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const esESObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presencia\",\n pluralLabel: \"Presencias\",\n description: \"Seguimiento en tiempo real de presencia y actividad de usuarios\",\n fields: {\n id: {\n label: \"ID de presencia\"\n },\n created_at: {\n label: \"Creado el\"\n },\n updated_at: {\n label: \"Actualizado el\"\n },\n user_id: {\n label: \"Usuario\"\n },\n session_id: {\n label: \"Sesión\"\n },\n status: {\n label: \"Estado\",\n options: {\n online: \"En línea\",\n away: \"Ausente\",\n busy: \"Ocupado\",\n offline: \"Desconectado\"\n }\n },\n last_seen: {\n label: \"Visto por última vez\"\n },\n current_location: {\n label: \"Ubicación actual\"\n },\n device: {\n label: \"Dispositivo\",\n options: {\n desktop: \"Escritorio\",\n mobile: \"Móvil\",\n tablet: \"Tableta\",\n other: \"Otro\"\n }\n },\n custom_status: {\n label: \"Estado personalizado\"\n },\n metadata: {\n label: \"Metadatos\",\n help: \"Metadatos JSON arbitrarios asociados al estado de presencia (coincide con PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * RealtimeTranslations — i18n bundle owned by this service plugin\n * (ADR-0029 D8).\n *\n * Object label/field/view/action translations for sys_presence, the object\n * this plugin owns. Loaded at runtime via the plugin's `kernel:ready` hook\n * (`i18n.loadTranslations`). Regenerate with `os i18n extract` against\n * `scripts/i18n-extract.config.ts`.\n */\n\nimport type { TranslationBundle } from '@objectstack/spec/system';\nimport { enObjects } from './en.objects.generated.js';\nimport { zhCNObjects } from './zh-CN.objects.generated.js';\nimport { jaJPObjects } from './ja-JP.objects.generated.js';\nimport { esESObjects } from './es-ES.objects.generated.js';\n\nexport const RealtimeTranslations: TranslationBundle = {\n en: { objects: enObjects },\n 'zh-CN': { objects: zhCNObjects },\n 'ja-JP': { objects: jaJPObjects },\n 'es-ES': { objects: esESObjects },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport { RealtimeServicePlugin } from './realtime-service-plugin.js';\nexport type { RealtimeServicePluginOptions } from './realtime-service-plugin.js';\nexport { InMemoryRealtimeAdapter } from './in-memory-realtime-adapter.js';\nexport type { InMemoryRealtimeAdapterOptions } from './in-memory-realtime-adapter.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_presence — System Presence Object\n *\n * Tracks real-time user presence and activity across the platform.\n * Fields align with the PresenceStateSchema protocol definition\n * from `@objectstack/spec/api` (websocket.zod.ts).\n *\n * Owned by `service-realtime` as the canonical Presence domain object.\n *\n * @namespace sys\n * @see PresenceStateSchema in packages/spec/src/api/websocket.zod.ts\n */\nexport const SysPresence = ObjectSchema.create({\n name: 'sys_presence',\n label: 'Presence',\n pluralLabel: 'Presences',\n icon: 'wifi',\n isSystem: true,\n managedBy: 'append-only',\n description: 'Real-time user presence and activity tracking',\n titleFormat: '{user_id} ({status})',\n compactLayout: ['user_id', 'status', 'last_seen'],\n\n fields: {\n id: Field.text({\n label: 'Presence ID',\n required: true,\n readonly: true,\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 user_id: Field.lookup('sys_user', {\n label: 'User',\n required: true,\n searchable: true,\n }),\n\n session_id: Field.lookup('sys_session', {\n label: 'Session',\n required: true,\n }),\n\n status: Field.select({\n label: 'Status',\n required: true,\n defaultValue: 'online',\n options: [\n { value: 'online', label: 'Online' },\n { value: 'away', label: 'Away' },\n { value: 'busy', label: 'Busy' },\n { value: 'offline', label: 'Offline' },\n ],\n }),\n\n last_seen: Field.datetime({\n label: 'Last Seen',\n required: true,\n defaultValue: 'NOW()',\n }),\n\n current_location: Field.text({\n label: 'Current Location',\n required: false,\n maxLength: 500,\n }),\n\n device: Field.select({\n label: 'Device',\n required: false,\n options: [\n { value: 'desktop', label: 'Desktop' },\n { value: 'mobile', label: 'Mobile' },\n { value: 'tablet', label: 'Tablet' },\n { value: 'other', label: 'Other' },\n ],\n }),\n\n custom_status: Field.text({\n label: 'Custom Status',\n required: false,\n maxLength: 255,\n }),\n\n metadata: Field.json({\n label: 'Metadata',\n required: false,\n description: 'Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).',\n }),\n },\n\n indexes: [\n { fields: ['user_id'], unique: false },\n { fields: ['session_id'], unique: true },\n { fields: ['status'], 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 {\n IRealtimeService,\n RealtimeEventPayload,\n RealtimeEventHandler,\n RealtimeSubscriptionOptions,\n} from '@objectstack/spec/contracts';\n\n/**\n * Internal subscription entry.\n */\ninterface Subscription {\n id: string;\n channel: string;\n handler: RealtimeEventHandler;\n options?: RealtimeSubscriptionOptions;\n}\n\n/**\n * Default safety cap on active subscriptions. This adapter is process-local\n * (the v1 single-instance contract — see launch-readiness.md P0-5); an\n * unbounded subscription map would grow until the pod OOMs under a subscription\n * leak or an abusive client. The cap is a backstop: `subscribe` throws once\n * it's reached. Operators raise `maxSubscriptions` for high-fan-out nodes;\n * `maxSubscriptions: 0` opts out entirely (unbounded — only for tests).\n */\nexport const DEFAULT_MAX_SUBSCRIPTIONS = 50_000;\n\n/**\n * Configuration options for InMemoryRealtimeAdapter.\n */\nexport interface InMemoryRealtimeAdapterOptions {\n /**\n * Maximum number of subscriptions allowed. Defaults to\n * {@link DEFAULT_MAX_SUBSCRIPTIONS}; `0` = unbounded (explicit opt-out).\n */\n maxSubscriptions?: number;\n}\n\n/**\n * In-memory pub/sub adapter implementing IRealtimeService.\n *\n * Uses a Map-backed subscription store with channel-based routing.\n * Supports event type and object filtering via subscription options.\n *\n * Suitable for single-process environments, development, and testing.\n * For production multi-instance deployments, use a Redis-backed adapter.\n *\n * @example\n * ```ts\n * const realtime = new InMemoryRealtimeAdapter();\n *\n * const subId = await realtime.subscribe('records', (event) => {\n * console.log('Received:', event.type, event.payload);\n * }, { object: 'account', eventTypes: ['record.created'] });\n *\n * await realtime.publish({\n * type: 'record.created',\n * object: 'account',\n * payload: { id: 'acc-1', name: 'Acme' },\n * timestamp: new Date().toISOString(),\n * });\n *\n * await realtime.unsubscribe(subId);\n * ```\n */\nexport class InMemoryRealtimeAdapter implements IRealtimeService {\n private readonly subscriptions = new Map<string, Subscription>();\n private readonly channelIndex = new Map<string, Set<string>>();\n private counter = 0;\n private readonly maxSubscriptions: number;\n\n constructor(options: InMemoryRealtimeAdapterOptions = {}) {\n this.maxSubscriptions = options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS;\n }\n\n async publish(event: RealtimeEventPayload): Promise<void> {\n // Deliver to all channel subscriptions that match filters\n for (const sub of this.subscriptions.values()) {\n if (this.matchesSubscription(event, sub)) {\n try {\n await sub.handler(event);\n } catch {\n // Swallow handler errors to avoid breaking the publish loop\n }\n }\n }\n }\n\n async subscribe(\n channel: string,\n handler: RealtimeEventHandler,\n options?: RealtimeSubscriptionOptions,\n ): Promise<string> {\n if (this.maxSubscriptions > 0 && this.subscriptions.size >= this.maxSubscriptions) {\n throw new Error(\n `Maximum subscription limit reached (${this.maxSubscriptions}). ` +\n 'Unsubscribe from existing channels before adding new subscriptions.',\n );\n }\n\n const id = `sub-${++this.counter}`;\n const sub: Subscription = { id, channel, handler, options };\n this.subscriptions.set(id, sub);\n\n // Maintain channel index for efficient lookups\n if (!this.channelIndex.has(channel)) {\n this.channelIndex.set(channel, new Set());\n }\n this.channelIndex.get(channel)!.add(id);\n\n return id;\n }\n\n async unsubscribe(subscriptionId: string): Promise<void> {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n\n this.subscriptions.delete(subscriptionId);\n\n // Clean up channel index\n const channelSubs = this.channelIndex.get(sub.channel);\n if (channelSubs) {\n channelSubs.delete(subscriptionId);\n if (channelSubs.size === 0) {\n this.channelIndex.delete(sub.channel);\n }\n }\n }\n\n /**\n * Get the number of active subscriptions.\n */\n getSubscriptionCount(): number {\n return this.subscriptions.size;\n }\n\n /**\n * Get all active channel names.\n */\n getChannels(): string[] {\n return Array.from(this.channelIndex.keys());\n }\n\n /**\n * Check if an event matches a subscription's filters.\n */\n private matchesSubscription(event: RealtimeEventPayload, sub: Subscription): boolean {\n const opts = sub.options;\n if (!opts) return true;\n\n // Filter by object name\n if (opts.object && event.object !== opts.object) {\n return false;\n }\n\n // Filter by event types\n if (opts.eventTypes && opts.eventTypes.length > 0) {\n if (!opts.eventTypes.includes(event.type)) {\n return false;\n }\n }\n\n return true;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysPresence } from './objects/index.js';\nimport { InMemoryRealtimeAdapter } from './in-memory-realtime-adapter.js';\nimport type { InMemoryRealtimeAdapterOptions } from './in-memory-realtime-adapter.js';\n\n/**\n * Configuration options for the RealtimeServicePlugin.\n */\nexport interface RealtimeServicePluginOptions {\n /** Realtime adapter type (default: 'memory') */\n adapter?: 'memory';\n /** Options for the in-memory adapter */\n memory?: InMemoryRealtimeAdapterOptions;\n}\n\n/**\n * RealtimeServicePlugin — Production IRealtimeService implementation.\n *\n * Registers a realtime pub/sub service with the kernel during the init phase.\n * Currently supports in-memory pub/sub for single-process environments.\n *\n * **v1 deployment contract (launch-readiness.md P0-5): single-instance only.**\n * The in-memory adapter is process-local — events published on node A are not\n * delivered to subscribers on node B. A default `maxSubscriptions` safety cap is\n * enforced (see {@link InMemoryRealtimeAdapter}) so the subscription map can't\n * grow until OOM. HA (a Redis-backed adapter over the existing `RedisPubSub` in\n * `service-cluster-redis`) is a post-GA fast-follow.\n *\n * @example\n * ```ts\n * import { ObjectKernel } from '@objectstack/core';\n * import { RealtimeServicePlugin } from '@objectstack/service-realtime';\n *\n * const kernel = new ObjectKernel();\n * kernel.use(new RealtimeServicePlugin());\n * await kernel.bootstrap();\n *\n * const realtime = kernel.getService('realtime');\n * await realtime.subscribe('records', (event) => {\n * console.log(event.type, event.payload);\n * });\n * ```\n */\nexport class RealtimeServicePlugin implements Plugin {\n name = 'com.objectstack.service.realtime';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: RealtimeServicePluginOptions;\n\n constructor(options: RealtimeServicePluginOptions = {}) {\n this.options = { adapter: 'memory', ...options };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const realtime = new InMemoryRealtimeAdapter(this.options.memory);\n ctx.registerService('realtime', realtime);\n\n // Register realtime system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.service.realtime',\n name: 'Realtime Service',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n namespace: 'sys',\n objects: [SysPresence],\n });\n\n // ADR-0029 D8 — contribute sys_presence translations on kernel:ready.\n if (typeof (ctx as any).hook === 'function') {\n (ctx as any).hook('kernel:ready', async () => {\n try {\n const i18n = ctx.getService<any>('i18n');\n if (i18n && typeof i18n.loadTranslations === 'function') {\n const { RealtimeTranslations } = await import('./translations/index.js');\n for (const [locale, data] of Object.entries(RealtimeTranslations)) {\n i18n.loadTranslations(locale, data as Record<string, unknown>);\n }\n }\n } catch { /* i18n optional */ }\n });\n }\n\n ctx.logger.info('RealtimeServicePlugin: registered in-memory realtime adapter');\n }\n}\n"],"mappings":"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","names":["RealtimeTranslations"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -5,7 +5,10 @@ import { IRealtimeService, RealtimeEventPayload, RealtimeEventHandler, RealtimeS
|
|
|
5
5
|
* Configuration options for InMemoryRealtimeAdapter.
|
|
6
6
|
*/
|
|
7
7
|
interface InMemoryRealtimeAdapterOptions {
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of subscriptions allowed. Defaults to
|
|
10
|
+
* {@link DEFAULT_MAX_SUBSCRIPTIONS}; `0` = unbounded (explicit opt-out).
|
|
11
|
+
*/
|
|
9
12
|
maxSubscriptions?: number;
|
|
10
13
|
}
|
|
11
14
|
/**
|
|
@@ -73,6 +76,13 @@ interface RealtimeServicePluginOptions {
|
|
|
73
76
|
* Registers a realtime pub/sub service with the kernel during the init phase.
|
|
74
77
|
* Currently supports in-memory pub/sub for single-process environments.
|
|
75
78
|
*
|
|
79
|
+
* **v1 deployment contract (launch-readiness.md P0-5): single-instance only.**
|
|
80
|
+
* The in-memory adapter is process-local — events published on node A are not
|
|
81
|
+
* delivered to subscribers on node B. A default `maxSubscriptions` safety cap is
|
|
82
|
+
* enforced (see {@link InMemoryRealtimeAdapter}) so the subscription map can't
|
|
83
|
+
* grow until OOM. HA (a Redis-backed adapter over the existing `RedisPubSub` in
|
|
84
|
+
* `service-cluster-redis`) is a post-GA fast-follow.
|
|
85
|
+
*
|
|
76
86
|
* @example
|
|
77
87
|
* ```ts
|
|
78
88
|
* import { ObjectKernel } from '@objectstack/core';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,10 @@ import { IRealtimeService, RealtimeEventPayload, RealtimeEventHandler, RealtimeS
|
|
|
5
5
|
* Configuration options for InMemoryRealtimeAdapter.
|
|
6
6
|
*/
|
|
7
7
|
interface InMemoryRealtimeAdapterOptions {
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of subscriptions allowed. Defaults to
|
|
10
|
+
* {@link DEFAULT_MAX_SUBSCRIPTIONS}; `0` = unbounded (explicit opt-out).
|
|
11
|
+
*/
|
|
9
12
|
maxSubscriptions?: number;
|
|
10
13
|
}
|
|
11
14
|
/**
|
|
@@ -73,6 +76,13 @@ interface RealtimeServicePluginOptions {
|
|
|
73
76
|
* Registers a realtime pub/sub service with the kernel during the init phase.
|
|
74
77
|
* Currently supports in-memory pub/sub for single-process environments.
|
|
75
78
|
*
|
|
79
|
+
* **v1 deployment contract (launch-readiness.md P0-5): single-instance only.**
|
|
80
|
+
* The in-memory adapter is process-local — events published on node A are not
|
|
81
|
+
* delivered to subscribers on node B. A default `maxSubscriptions` safety cap is
|
|
82
|
+
* enforced (see {@link InMemoryRealtimeAdapter}) so the subscription map can't
|
|
83
|
+
* grow until OOM. HA (a Redis-backed adapter over the existing `RedisPubSub` in
|
|
84
|
+
* `service-cluster-redis`) is a post-GA fast-follow.
|
|
85
|
+
*
|
|
76
86
|
* @example
|
|
77
87
|
* ```ts
|
|
78
88
|
* import { ObjectKernel } from '@objectstack/core';
|
package/dist/index.js
CHANGED
|
@@ -377,12 +377,13 @@ var SysPresence = ObjectSchema.create({
|
|
|
377
377
|
});
|
|
378
378
|
|
|
379
379
|
// src/in-memory-realtime-adapter.ts
|
|
380
|
+
var DEFAULT_MAX_SUBSCRIPTIONS = 5e4;
|
|
380
381
|
var InMemoryRealtimeAdapter = class {
|
|
381
382
|
constructor(options = {}) {
|
|
382
383
|
this.subscriptions = /* @__PURE__ */ new Map();
|
|
383
384
|
this.channelIndex = /* @__PURE__ */ new Map();
|
|
384
385
|
this.counter = 0;
|
|
385
|
-
this.maxSubscriptions = options.maxSubscriptions ??
|
|
386
|
+
this.maxSubscriptions = options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS;
|
|
386
387
|
}
|
|
387
388
|
async publish(event) {
|
|
388
389
|
for (const sub of this.subscriptions.values()) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/translations/en.objects.generated.ts","../src/translations/zh-CN.objects.generated.ts","../src/translations/ja-JP.objects.generated.ts","../src/translations/es-ES.objects.generated.ts","../src/translations/index.ts","../src/objects/sys-presence.object.ts","../src/in-memory-realtime-adapter.ts","../src/realtime-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'en'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const enObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presence\",\n pluralLabel: \"Presences\",\n description: \"Real-time user presence and activity tracking\",\n fields: {\n id: {\n label: \"Presence ID\"\n },\n created_at: {\n label: \"Created At\"\n },\n updated_at: {\n label: \"Updated At\"\n },\n user_id: {\n label: \"User\"\n },\n session_id: {\n label: \"Session\"\n },\n status: {\n label: \"Status\",\n options: {\n online: \"Online\",\n away: \"Away\",\n busy: \"Busy\",\n offline: \"Offline\"\n }\n },\n last_seen: {\n label: \"Last Seen\"\n },\n current_location: {\n label: \"Current Location\"\n },\n device: {\n label: \"Device\",\n options: {\n desktop: \"Desktop\",\n mobile: \"Mobile\",\n tablet: \"Tablet\",\n other: \"Other\"\n }\n },\n custom_status: {\n label: \"Custom Status\"\n },\n metadata: {\n label: \"Metadata\",\n help: \"Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'zh-CN'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const zhCNObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在线状态\",\n pluralLabel: \"在线状态\",\n description: \"实时用户在线与活动跟踪\",\n fields: {\n id: {\n label: \"在线状态 ID\"\n },\n created_at: {\n label: \"创建时间\"\n },\n updated_at: {\n label: \"更新时间\"\n },\n user_id: {\n label: \"用户\"\n },\n session_id: {\n label: \"会话\"\n },\n status: {\n label: \"状态\",\n options: {\n online: \"在线\",\n away: \"离开\",\n busy: \"忙碌\",\n offline: \"离线\"\n }\n },\n last_seen: {\n label: \"最近在线时间\"\n },\n current_location: {\n label: \"当前位置\"\n },\n device: {\n label: \"设备\",\n options: {\n desktop: \"桌面端\",\n mobile: \"移动端\",\n tablet: \"平板端\",\n other: \"其他\"\n }\n },\n custom_status: {\n label: \"自定义状态\"\n },\n metadata: {\n label: \"元数据\",\n help: \"与在线状态关联的任意 JSON 元数据(对应 PresenceStateSchema.metadata)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'ja-JP'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const jaJPObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在席状況\",\n pluralLabel: \"在席状況\",\n description: \"リアルタイムのユーザー在席状況とアクティビティ追跡\",\n fields: {\n id: {\n label: \"在席 ID\"\n },\n created_at: {\n label: \"作成日時\"\n },\n updated_at: {\n label: \"更新日時\"\n },\n user_id: {\n label: \"ユーザー\"\n },\n session_id: {\n label: \"セッション\"\n },\n status: {\n label: \"ステータス\",\n options: {\n online: \"オンライン\",\n away: \"離席中\",\n busy: \"取り込み中\",\n offline: \"オフライン\"\n }\n },\n last_seen: {\n label: \"最終確認日時\"\n },\n current_location: {\n label: \"現在地\"\n },\n device: {\n label: \"デバイス\",\n options: {\n desktop: \"デスクトップ\",\n mobile: \"モバイル\",\n tablet: \"タブレット\",\n other: \"その他\"\n }\n },\n custom_status: {\n label: \"カスタムステータス\"\n },\n metadata: {\n label: \"メタデータ\",\n help: \"在席状態に関連付けられた任意の JSON メタデータ(PresenceStateSchema.metadata に対応)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'es-ES'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const esESObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presencia\",\n pluralLabel: \"Presencias\",\n description: \"Seguimiento en tiempo real de presencia y actividad de usuarios\",\n fields: {\n id: {\n label: \"ID de presencia\"\n },\n created_at: {\n label: \"Creado el\"\n },\n updated_at: {\n label: \"Actualizado el\"\n },\n user_id: {\n label: \"Usuario\"\n },\n session_id: {\n label: \"Sesión\"\n },\n status: {\n label: \"Estado\",\n options: {\n online: \"En línea\",\n away: \"Ausente\",\n busy: \"Ocupado\",\n offline: \"Desconectado\"\n }\n },\n last_seen: {\n label: \"Visto por última vez\"\n },\n current_location: {\n label: \"Ubicación actual\"\n },\n device: {\n label: \"Dispositivo\",\n options: {\n desktop: \"Escritorio\",\n mobile: \"Móvil\",\n tablet: \"Tableta\",\n other: \"Otro\"\n }\n },\n custom_status: {\n label: \"Estado personalizado\"\n },\n metadata: {\n label: \"Metadatos\",\n help: \"Metadatos JSON arbitrarios asociados al estado de presencia (coincide con PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * RealtimeTranslations — i18n bundle owned by this service plugin\n * (ADR-0029 D8).\n *\n * Object label/field/view/action translations for sys_presence, the object\n * this plugin owns. Loaded at runtime via the plugin's `kernel:ready` hook\n * (`i18n.loadTranslations`). Regenerate with `os i18n extract` against\n * `scripts/i18n-extract.config.ts`.\n */\n\nimport type { TranslationBundle } from '@objectstack/spec/system';\nimport { enObjects } from './en.objects.generated.js';\nimport { zhCNObjects } from './zh-CN.objects.generated.js';\nimport { jaJPObjects } from './ja-JP.objects.generated.js';\nimport { esESObjects } from './es-ES.objects.generated.js';\n\nexport const RealtimeTranslations: TranslationBundle = {\n en: { objects: enObjects },\n 'zh-CN': { objects: zhCNObjects },\n 'ja-JP': { objects: jaJPObjects },\n 'es-ES': { objects: esESObjects },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_presence — System Presence Object\n *\n * Tracks real-time user presence and activity across the platform.\n * Fields align with the PresenceStateSchema protocol definition\n * from `@objectstack/spec/api` (websocket.zod.ts).\n *\n * Owned by `service-realtime` as the canonical Presence domain object.\n *\n * @namespace sys\n * @see PresenceStateSchema in packages/spec/src/api/websocket.zod.ts\n */\nexport const SysPresence = ObjectSchema.create({\n name: 'sys_presence',\n label: 'Presence',\n pluralLabel: 'Presences',\n icon: 'wifi',\n isSystem: true,\n managedBy: 'append-only',\n description: 'Real-time user presence and activity tracking',\n titleFormat: '{user_id} ({status})',\n compactLayout: ['user_id', 'status', 'last_seen'],\n\n fields: {\n id: Field.text({\n label: 'Presence ID',\n required: true,\n readonly: true,\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 user_id: Field.lookup('sys_user', {\n label: 'User',\n required: true,\n searchable: true,\n }),\n\n session_id: Field.lookup('sys_session', {\n label: 'Session',\n required: true,\n }),\n\n status: Field.select({\n label: 'Status',\n required: true,\n defaultValue: 'online',\n options: [\n { value: 'online', label: 'Online' },\n { value: 'away', label: 'Away' },\n { value: 'busy', label: 'Busy' },\n { value: 'offline', label: 'Offline' },\n ],\n }),\n\n last_seen: Field.datetime({\n label: 'Last Seen',\n required: true,\n defaultValue: 'NOW()',\n }),\n\n current_location: Field.text({\n label: 'Current Location',\n required: false,\n maxLength: 500,\n }),\n\n device: Field.select({\n label: 'Device',\n required: false,\n options: [\n { value: 'desktop', label: 'Desktop' },\n { value: 'mobile', label: 'Mobile' },\n { value: 'tablet', label: 'Tablet' },\n { value: 'other', label: 'Other' },\n ],\n }),\n\n custom_status: Field.text({\n label: 'Custom Status',\n required: false,\n maxLength: 255,\n }),\n\n metadata: Field.json({\n label: 'Metadata',\n required: false,\n description: 'Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).',\n }),\n },\n\n indexes: [\n { fields: ['user_id'], unique: false },\n { fields: ['session_id'], unique: true },\n { fields: ['status'], 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 {\n IRealtimeService,\n RealtimeEventPayload,\n RealtimeEventHandler,\n RealtimeSubscriptionOptions,\n} from '@objectstack/spec/contracts';\n\n/**\n * Internal subscription entry.\n */\ninterface Subscription {\n id: string;\n channel: string;\n handler: RealtimeEventHandler;\n options?: RealtimeSubscriptionOptions;\n}\n\n/**\n * Configuration options for InMemoryRealtimeAdapter.\n */\nexport interface InMemoryRealtimeAdapterOptions {\n /** Maximum number of subscriptions allowed (0 = unlimited) */\n maxSubscriptions?: number;\n}\n\n/**\n * In-memory pub/sub adapter implementing IRealtimeService.\n *\n * Uses a Map-backed subscription store with channel-based routing.\n * Supports event type and object filtering via subscription options.\n *\n * Suitable for single-process environments, development, and testing.\n * For production multi-instance deployments, use a Redis-backed adapter.\n *\n * @example\n * ```ts\n * const realtime = new InMemoryRealtimeAdapter();\n *\n * const subId = await realtime.subscribe('records', (event) => {\n * console.log('Received:', event.type, event.payload);\n * }, { object: 'account', eventTypes: ['record.created'] });\n *\n * await realtime.publish({\n * type: 'record.created',\n * object: 'account',\n * payload: { id: 'acc-1', name: 'Acme' },\n * timestamp: new Date().toISOString(),\n * });\n *\n * await realtime.unsubscribe(subId);\n * ```\n */\nexport class InMemoryRealtimeAdapter implements IRealtimeService {\n private readonly subscriptions = new Map<string, Subscription>();\n private readonly channelIndex = new Map<string, Set<string>>();\n private counter = 0;\n private readonly maxSubscriptions: number;\n\n constructor(options: InMemoryRealtimeAdapterOptions = {}) {\n this.maxSubscriptions = options.maxSubscriptions ?? 0;\n }\n\n async publish(event: RealtimeEventPayload): Promise<void> {\n // Deliver to all channel subscriptions that match filters\n for (const sub of this.subscriptions.values()) {\n if (this.matchesSubscription(event, sub)) {\n try {\n await sub.handler(event);\n } catch {\n // Swallow handler errors to avoid breaking the publish loop\n }\n }\n }\n }\n\n async subscribe(\n channel: string,\n handler: RealtimeEventHandler,\n options?: RealtimeSubscriptionOptions,\n ): Promise<string> {\n if (this.maxSubscriptions > 0 && this.subscriptions.size >= this.maxSubscriptions) {\n throw new Error(\n `Maximum subscription limit reached (${this.maxSubscriptions}). ` +\n 'Unsubscribe from existing channels before adding new subscriptions.',\n );\n }\n\n const id = `sub-${++this.counter}`;\n const sub: Subscription = { id, channel, handler, options };\n this.subscriptions.set(id, sub);\n\n // Maintain channel index for efficient lookups\n if (!this.channelIndex.has(channel)) {\n this.channelIndex.set(channel, new Set());\n }\n this.channelIndex.get(channel)!.add(id);\n\n return id;\n }\n\n async unsubscribe(subscriptionId: string): Promise<void> {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n\n this.subscriptions.delete(subscriptionId);\n\n // Clean up channel index\n const channelSubs = this.channelIndex.get(sub.channel);\n if (channelSubs) {\n channelSubs.delete(subscriptionId);\n if (channelSubs.size === 0) {\n this.channelIndex.delete(sub.channel);\n }\n }\n }\n\n /**\n * Get the number of active subscriptions.\n */\n getSubscriptionCount(): number {\n return this.subscriptions.size;\n }\n\n /**\n * Get all active channel names.\n */\n getChannels(): string[] {\n return Array.from(this.channelIndex.keys());\n }\n\n /**\n * Check if an event matches a subscription's filters.\n */\n private matchesSubscription(event: RealtimeEventPayload, sub: Subscription): boolean {\n const opts = sub.options;\n if (!opts) return true;\n\n // Filter by object name\n if (opts.object && event.object !== opts.object) {\n return false;\n }\n\n // Filter by event types\n if (opts.eventTypes && opts.eventTypes.length > 0) {\n if (!opts.eventTypes.includes(event.type)) {\n return false;\n }\n }\n\n return true;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysPresence } from './objects/index.js';\nimport { InMemoryRealtimeAdapter } from './in-memory-realtime-adapter.js';\nimport type { InMemoryRealtimeAdapterOptions } from './in-memory-realtime-adapter.js';\n\n/**\n * Configuration options for the RealtimeServicePlugin.\n */\nexport interface RealtimeServicePluginOptions {\n /** Realtime adapter type (default: 'memory') */\n adapter?: 'memory';\n /** Options for the in-memory adapter */\n memory?: InMemoryRealtimeAdapterOptions;\n}\n\n/**\n * RealtimeServicePlugin — Production IRealtimeService implementation.\n *\n * Registers a realtime pub/sub service with the kernel during the init phase.\n * Currently supports in-memory pub/sub for single-process environments.\n *\n * @example\n * ```ts\n * import { ObjectKernel } from '@objectstack/core';\n * import { RealtimeServicePlugin } from '@objectstack/service-realtime';\n *\n * const kernel = new ObjectKernel();\n * kernel.use(new RealtimeServicePlugin());\n * await kernel.bootstrap();\n *\n * const realtime = kernel.getService('realtime');\n * await realtime.subscribe('records', (event) => {\n * console.log(event.type, event.payload);\n * });\n * ```\n */\nexport class RealtimeServicePlugin implements Plugin {\n name = 'com.objectstack.service.realtime';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: RealtimeServicePluginOptions;\n\n constructor(options: RealtimeServicePluginOptions = {}) {\n this.options = { adapter: 'memory', ...options };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const realtime = new InMemoryRealtimeAdapter(this.options.memory);\n ctx.registerService('realtime', realtime);\n\n // Register realtime system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.service.realtime',\n name: 'Realtime Service',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n namespace: 'sys',\n objects: [SysPresence],\n });\n\n // ADR-0029 D8 — contribute sys_presence translations on kernel:ready.\n if (typeof (ctx as any).hook === 'function') {\n (ctx as any).hook('kernel:ready', async () => {\n try {\n const i18n = ctx.getService<any>('i18n');\n if (i18n && typeof i18n.loadTranslations === 'function') {\n const { RealtimeTranslations } = await import('./translations/index.js');\n for (const [locale, data] of Object.entries(RealtimeTranslations)) {\n i18n.loadTranslations(locale, data as Record<string, unknown>);\n }\n }\n } catch { /* i18n optional */ }\n });\n }\n\n ctx.logger.info('RealtimeServicePlugin: registered in-memory realtime adapter');\n }\n}\n"],"mappings":"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","names":["RealtimeTranslations"]}
|
|
1
|
+
{"version":3,"sources":["../src/translations/en.objects.generated.ts","../src/translations/zh-CN.objects.generated.ts","../src/translations/ja-JP.objects.generated.ts","../src/translations/es-ES.objects.generated.ts","../src/translations/index.ts","../src/objects/sys-presence.object.ts","../src/in-memory-realtime-adapter.ts","../src/realtime-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'en'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const enObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presence\",\n pluralLabel: \"Presences\",\n description: \"Real-time user presence and activity tracking\",\n fields: {\n id: {\n label: \"Presence ID\"\n },\n created_at: {\n label: \"Created At\"\n },\n updated_at: {\n label: \"Updated At\"\n },\n user_id: {\n label: \"User\"\n },\n session_id: {\n label: \"Session\"\n },\n status: {\n label: \"Status\",\n options: {\n online: \"Online\",\n away: \"Away\",\n busy: \"Busy\",\n offline: \"Offline\"\n }\n },\n last_seen: {\n label: \"Last Seen\"\n },\n current_location: {\n label: \"Current Location\"\n },\n device: {\n label: \"Device\",\n options: {\n desktop: \"Desktop\",\n mobile: \"Mobile\",\n tablet: \"Tablet\",\n other: \"Other\"\n }\n },\n custom_status: {\n label: \"Custom Status\"\n },\n metadata: {\n label: \"Metadata\",\n help: \"Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'zh-CN'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const zhCNObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在线状态\",\n pluralLabel: \"在线状态\",\n description: \"实时用户在线与活动跟踪\",\n fields: {\n id: {\n label: \"在线状态 ID\"\n },\n created_at: {\n label: \"创建时间\"\n },\n updated_at: {\n label: \"更新时间\"\n },\n user_id: {\n label: \"用户\"\n },\n session_id: {\n label: \"会话\"\n },\n status: {\n label: \"状态\",\n options: {\n online: \"在线\",\n away: \"离开\",\n busy: \"忙碌\",\n offline: \"离线\"\n }\n },\n last_seen: {\n label: \"最近在线时间\"\n },\n current_location: {\n label: \"当前位置\"\n },\n device: {\n label: \"设备\",\n options: {\n desktop: \"桌面端\",\n mobile: \"移动端\",\n tablet: \"平板端\",\n other: \"其他\"\n }\n },\n custom_status: {\n label: \"自定义状态\"\n },\n metadata: {\n label: \"元数据\",\n help: \"与在线状态关联的任意 JSON 元数据(对应 PresenceStateSchema.metadata)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'ja-JP'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const jaJPObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"在席状況\",\n pluralLabel: \"在席状況\",\n description: \"リアルタイムのユーザー在席状況とアクティビティ追跡\",\n fields: {\n id: {\n label: \"在席 ID\"\n },\n created_at: {\n label: \"作成日時\"\n },\n updated_at: {\n label: \"更新日時\"\n },\n user_id: {\n label: \"ユーザー\"\n },\n session_id: {\n label: \"セッション\"\n },\n status: {\n label: \"ステータス\",\n options: {\n online: \"オンライン\",\n away: \"離席中\",\n busy: \"取り込み中\",\n offline: \"オフライン\"\n }\n },\n last_seen: {\n label: \"最終確認日時\"\n },\n current_location: {\n label: \"現在地\"\n },\n device: {\n label: \"デバイス\",\n options: {\n desktop: \"デスクトップ\",\n mobile: \"モバイル\",\n tablet: \"タブレット\",\n other: \"その他\"\n }\n },\n custom_status: {\n label: \"カスタムステータス\"\n },\n metadata: {\n label: \"メタデータ\",\n help: \"在席状態に関連付けられた任意の JSON メタデータ(PresenceStateSchema.metadata に対応)。\"\n }\n }\n }\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Auto-generated by 'os i18n extract' for locale 'es-ES'.\n * Edit translations in place; re-run extract (with --merge) to fill new gaps.\n * Do not hand-edit the structure — only the leaf string values.\n */\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\nexport const esESObjects: NonNullable<TranslationData['objects']> = {\n sys_presence: {\n label: \"Presencia\",\n pluralLabel: \"Presencias\",\n description: \"Seguimiento en tiempo real de presencia y actividad de usuarios\",\n fields: {\n id: {\n label: \"ID de presencia\"\n },\n created_at: {\n label: \"Creado el\"\n },\n updated_at: {\n label: \"Actualizado el\"\n },\n user_id: {\n label: \"Usuario\"\n },\n session_id: {\n label: \"Sesión\"\n },\n status: {\n label: \"Estado\",\n options: {\n online: \"En línea\",\n away: \"Ausente\",\n busy: \"Ocupado\",\n offline: \"Desconectado\"\n }\n },\n last_seen: {\n label: \"Visto por última vez\"\n },\n current_location: {\n label: \"Ubicación actual\"\n },\n device: {\n label: \"Dispositivo\",\n options: {\n desktop: \"Escritorio\",\n mobile: \"Móvil\",\n tablet: \"Tableta\",\n other: \"Otro\"\n }\n },\n custom_status: {\n label: \"Estado personalizado\"\n },\n metadata: {\n label: \"Metadatos\",\n help: \"Metadatos JSON arbitrarios asociados al estado de presencia (coincide con PresenceStateSchema.metadata).\"\n }\n }\n }\n};\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * RealtimeTranslations — i18n bundle owned by this service plugin\n * (ADR-0029 D8).\n *\n * Object label/field/view/action translations for sys_presence, the object\n * this plugin owns. Loaded at runtime via the plugin's `kernel:ready` hook\n * (`i18n.loadTranslations`). Regenerate with `os i18n extract` against\n * `scripts/i18n-extract.config.ts`.\n */\n\nimport type { TranslationBundle } from '@objectstack/spec/system';\nimport { enObjects } from './en.objects.generated.js';\nimport { zhCNObjects } from './zh-CN.objects.generated.js';\nimport { jaJPObjects } from './ja-JP.objects.generated.js';\nimport { esESObjects } from './es-ES.objects.generated.js';\n\nexport const RealtimeTranslations: TranslationBundle = {\n en: { objects: enObjects },\n 'zh-CN': { objects: zhCNObjects },\n 'ja-JP': { objects: jaJPObjects },\n 'es-ES': { objects: esESObjects },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_presence — System Presence Object\n *\n * Tracks real-time user presence and activity across the platform.\n * Fields align with the PresenceStateSchema protocol definition\n * from `@objectstack/spec/api` (websocket.zod.ts).\n *\n * Owned by `service-realtime` as the canonical Presence domain object.\n *\n * @namespace sys\n * @see PresenceStateSchema in packages/spec/src/api/websocket.zod.ts\n */\nexport const SysPresence = ObjectSchema.create({\n name: 'sys_presence',\n label: 'Presence',\n pluralLabel: 'Presences',\n icon: 'wifi',\n isSystem: true,\n managedBy: 'append-only',\n description: 'Real-time user presence and activity tracking',\n titleFormat: '{user_id} ({status})',\n compactLayout: ['user_id', 'status', 'last_seen'],\n\n fields: {\n id: Field.text({\n label: 'Presence ID',\n required: true,\n readonly: true,\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 user_id: Field.lookup('sys_user', {\n label: 'User',\n required: true,\n searchable: true,\n }),\n\n session_id: Field.lookup('sys_session', {\n label: 'Session',\n required: true,\n }),\n\n status: Field.select({\n label: 'Status',\n required: true,\n defaultValue: 'online',\n options: [\n { value: 'online', label: 'Online' },\n { value: 'away', label: 'Away' },\n { value: 'busy', label: 'Busy' },\n { value: 'offline', label: 'Offline' },\n ],\n }),\n\n last_seen: Field.datetime({\n label: 'Last Seen',\n required: true,\n defaultValue: 'NOW()',\n }),\n\n current_location: Field.text({\n label: 'Current Location',\n required: false,\n maxLength: 500,\n }),\n\n device: Field.select({\n label: 'Device',\n required: false,\n options: [\n { value: 'desktop', label: 'Desktop' },\n { value: 'mobile', label: 'Mobile' },\n { value: 'tablet', label: 'Tablet' },\n { value: 'other', label: 'Other' },\n ],\n }),\n\n custom_status: Field.text({\n label: 'Custom Status',\n required: false,\n maxLength: 255,\n }),\n\n metadata: Field.json({\n label: 'Metadata',\n required: false,\n description: 'Arbitrary JSON metadata associated with the presence state (matches PresenceStateSchema.metadata).',\n }),\n },\n\n indexes: [\n { fields: ['user_id'], unique: false },\n { fields: ['session_id'], unique: true },\n { fields: ['status'], 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 {\n IRealtimeService,\n RealtimeEventPayload,\n RealtimeEventHandler,\n RealtimeSubscriptionOptions,\n} from '@objectstack/spec/contracts';\n\n/**\n * Internal subscription entry.\n */\ninterface Subscription {\n id: string;\n channel: string;\n handler: RealtimeEventHandler;\n options?: RealtimeSubscriptionOptions;\n}\n\n/**\n * Default safety cap on active subscriptions. This adapter is process-local\n * (the v1 single-instance contract — see launch-readiness.md P0-5); an\n * unbounded subscription map would grow until the pod OOMs under a subscription\n * leak or an abusive client. The cap is a backstop: `subscribe` throws once\n * it's reached. Operators raise `maxSubscriptions` for high-fan-out nodes;\n * `maxSubscriptions: 0` opts out entirely (unbounded — only for tests).\n */\nexport const DEFAULT_MAX_SUBSCRIPTIONS = 50_000;\n\n/**\n * Configuration options for InMemoryRealtimeAdapter.\n */\nexport interface InMemoryRealtimeAdapterOptions {\n /**\n * Maximum number of subscriptions allowed. Defaults to\n * {@link DEFAULT_MAX_SUBSCRIPTIONS}; `0` = unbounded (explicit opt-out).\n */\n maxSubscriptions?: number;\n}\n\n/**\n * In-memory pub/sub adapter implementing IRealtimeService.\n *\n * Uses a Map-backed subscription store with channel-based routing.\n * Supports event type and object filtering via subscription options.\n *\n * Suitable for single-process environments, development, and testing.\n * For production multi-instance deployments, use a Redis-backed adapter.\n *\n * @example\n * ```ts\n * const realtime = new InMemoryRealtimeAdapter();\n *\n * const subId = await realtime.subscribe('records', (event) => {\n * console.log('Received:', event.type, event.payload);\n * }, { object: 'account', eventTypes: ['record.created'] });\n *\n * await realtime.publish({\n * type: 'record.created',\n * object: 'account',\n * payload: { id: 'acc-1', name: 'Acme' },\n * timestamp: new Date().toISOString(),\n * });\n *\n * await realtime.unsubscribe(subId);\n * ```\n */\nexport class InMemoryRealtimeAdapter implements IRealtimeService {\n private readonly subscriptions = new Map<string, Subscription>();\n private readonly channelIndex = new Map<string, Set<string>>();\n private counter = 0;\n private readonly maxSubscriptions: number;\n\n constructor(options: InMemoryRealtimeAdapterOptions = {}) {\n this.maxSubscriptions = options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS;\n }\n\n async publish(event: RealtimeEventPayload): Promise<void> {\n // Deliver to all channel subscriptions that match filters\n for (const sub of this.subscriptions.values()) {\n if (this.matchesSubscription(event, sub)) {\n try {\n await sub.handler(event);\n } catch {\n // Swallow handler errors to avoid breaking the publish loop\n }\n }\n }\n }\n\n async subscribe(\n channel: string,\n handler: RealtimeEventHandler,\n options?: RealtimeSubscriptionOptions,\n ): Promise<string> {\n if (this.maxSubscriptions > 0 && this.subscriptions.size >= this.maxSubscriptions) {\n throw new Error(\n `Maximum subscription limit reached (${this.maxSubscriptions}). ` +\n 'Unsubscribe from existing channels before adding new subscriptions.',\n );\n }\n\n const id = `sub-${++this.counter}`;\n const sub: Subscription = { id, channel, handler, options };\n this.subscriptions.set(id, sub);\n\n // Maintain channel index for efficient lookups\n if (!this.channelIndex.has(channel)) {\n this.channelIndex.set(channel, new Set());\n }\n this.channelIndex.get(channel)!.add(id);\n\n return id;\n }\n\n async unsubscribe(subscriptionId: string): Promise<void> {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n\n this.subscriptions.delete(subscriptionId);\n\n // Clean up channel index\n const channelSubs = this.channelIndex.get(sub.channel);\n if (channelSubs) {\n channelSubs.delete(subscriptionId);\n if (channelSubs.size === 0) {\n this.channelIndex.delete(sub.channel);\n }\n }\n }\n\n /**\n * Get the number of active subscriptions.\n */\n getSubscriptionCount(): number {\n return this.subscriptions.size;\n }\n\n /**\n * Get all active channel names.\n */\n getChannels(): string[] {\n return Array.from(this.channelIndex.keys());\n }\n\n /**\n * Check if an event matches a subscription's filters.\n */\n private matchesSubscription(event: RealtimeEventPayload, sub: Subscription): boolean {\n const opts = sub.options;\n if (!opts) return true;\n\n // Filter by object name\n if (opts.object && event.object !== opts.object) {\n return false;\n }\n\n // Filter by event types\n if (opts.eventTypes && opts.eventTypes.length > 0) {\n if (!opts.eventTypes.includes(event.type)) {\n return false;\n }\n }\n\n return true;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysPresence } from './objects/index.js';\nimport { InMemoryRealtimeAdapter } from './in-memory-realtime-adapter.js';\nimport type { InMemoryRealtimeAdapterOptions } from './in-memory-realtime-adapter.js';\n\n/**\n * Configuration options for the RealtimeServicePlugin.\n */\nexport interface RealtimeServicePluginOptions {\n /** Realtime adapter type (default: 'memory') */\n adapter?: 'memory';\n /** Options for the in-memory adapter */\n memory?: InMemoryRealtimeAdapterOptions;\n}\n\n/**\n * RealtimeServicePlugin — Production IRealtimeService implementation.\n *\n * Registers a realtime pub/sub service with the kernel during the init phase.\n * Currently supports in-memory pub/sub for single-process environments.\n *\n * **v1 deployment contract (launch-readiness.md P0-5): single-instance only.**\n * The in-memory adapter is process-local — events published on node A are not\n * delivered to subscribers on node B. A default `maxSubscriptions` safety cap is\n * enforced (see {@link InMemoryRealtimeAdapter}) so the subscription map can't\n * grow until OOM. HA (a Redis-backed adapter over the existing `RedisPubSub` in\n * `service-cluster-redis`) is a post-GA fast-follow.\n *\n * @example\n * ```ts\n * import { ObjectKernel } from '@objectstack/core';\n * import { RealtimeServicePlugin } from '@objectstack/service-realtime';\n *\n * const kernel = new ObjectKernel();\n * kernel.use(new RealtimeServicePlugin());\n * await kernel.bootstrap();\n *\n * const realtime = kernel.getService('realtime');\n * await realtime.subscribe('records', (event) => {\n * console.log(event.type, event.payload);\n * });\n * ```\n */\nexport class RealtimeServicePlugin implements Plugin {\n name = 'com.objectstack.service.realtime';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: RealtimeServicePluginOptions;\n\n constructor(options: RealtimeServicePluginOptions = {}) {\n this.options = { adapter: 'memory', ...options };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const realtime = new InMemoryRealtimeAdapter(this.options.memory);\n ctx.registerService('realtime', realtime);\n\n // Register realtime system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.service.realtime',\n name: 'Realtime Service',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n namespace: 'sys',\n objects: [SysPresence],\n });\n\n // ADR-0029 D8 — contribute sys_presence translations on kernel:ready.\n if (typeof (ctx as any).hook === 'function') {\n (ctx as any).hook('kernel:ready', async () => {\n try {\n const i18n = ctx.getService<any>('i18n');\n if (i18n && typeof i18n.loadTranslations === 'function') {\n const { RealtimeTranslations } = await import('./translations/index.js');\n for (const [locale, data] of Object.entries(RealtimeTranslations)) {\n i18n.loadTranslations(locale, data as Record<string, unknown>);\n }\n }\n } catch { /* i18n optional */ }\n });\n }\n\n ctx.logger.info('RealtimeServicePlugin: registered in-memory realtime adapter');\n }\n}\n"],"mappings":";;;;;;;;;;;AAAA,IAUa;AAVb;AAAA;AAAA;AAUO,IAAM,YAAqD;AAAA,MAChE,cAAc;AAAA,QACZ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,IAAI;AAAA,YACF,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT,OAAO;AAAA,UACT;AAAA,UACA,kBAAkB;AAAA,YAChB,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,eAAe;AAAA,YACb,OAAO;AAAA,UACT;AAAA,UACA,UAAU;AAAA,YACR,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AChEA,IAUa;AAVb;AAAA;AAAA;AAUO,IAAM,cAAuD;AAAA,MAClE,cAAc;AAAA,QACZ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,IAAI;AAAA,YACF,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT,OAAO;AAAA,UACT;AAAA,UACA,kBAAkB;AAAA,YAChB,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,eAAe;AAAA,YACb,OAAO;AAAA,UACT;AAAA,UACA,UAAU;AAAA,YACR,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AChEA,IAUa;AAVb;AAAA;AAAA;AAUO,IAAM,cAAuD;AAAA,MAClE,cAAc;AAAA,QACZ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,IAAI;AAAA,YACF,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT,OAAO;AAAA,UACT;AAAA,UACA,kBAAkB;AAAA,YAChB,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,eAAe;AAAA,YACb,OAAO;AAAA,UACT;AAAA,UACA,UAAU;AAAA,YACR,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AChEA,IAUa;AAVb;AAAA;AAAA;AAUO,IAAM,cAAuD;AAAA,MAClE,cAAc;AAAA,QACZ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,IAAI;AAAA,YACF,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA,YAAY;AAAA,YACV,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT,OAAO;AAAA,UACT;AAAA,UACA,kBAAkB;AAAA,YAChB,OAAO;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,YACN,OAAO;AAAA,YACP,SAAS;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,eAAe;AAAA,YACb,OAAO;AAAA,UACT;AAAA,UACA,UAAU;AAAA,YACR,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AChEA;AAAA;AAAA;AAAA;AAAA,IAkBa;AAlBb;AAAA;AAAA;AAaA;AACA;AACA;AACA;AAEO,IAAM,uBAA0C;AAAA,MACrD,IAAI,EAAE,SAAS,UAAU;AAAA,MACzB,SAAS,EAAE,SAAS,YAAY;AAAA,MAChC,SAAS,EAAE,SAAS,YAAY;AAAA,MAChC,SAAS,EAAE,SAAS,YAAY;AAAA,IAClC;AAAA;AAAA;;;ACrBA,SAAS,cAAc,aAAa;AAc7B,IAAM,cAAc,aAAa,OAAO;AAAA,EAC7C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,CAAC,WAAW,UAAU,WAAW;AAAA,EAEhD,QAAQ;AAAA,IACN,IAAI,MAAM,KAAK;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,MAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,MAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,SAAS,MAAM,OAAO,YAAY;AAAA,MAChC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,IAED,YAAY,MAAM,OAAO,eAAe;AAAA,MACtC,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,QAAQ,MAAM,OAAO;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,SAAS;AAAA,QACP,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,QACnC,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QAC/B,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,IAED,WAAW,MAAM,SAAS;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,IAChB,CAAC;AAAA,IAED,kBAAkB,MAAM,KAAK;AAAA,MAC3B,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AAAA,IAED,QAAQ,MAAM,OAAO;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,SAAS;AAAA,QACP,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,QACrC,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,QACnC,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,QACnC,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,IAED,eAAe,MAAM,KAAK;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AAAA,IAED,UAAU,MAAM,KAAK;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AAAA,IACP,EAAE,QAAQ,CAAC,SAAS,GAAG,QAAQ,MAAM;AAAA,IACrC,EAAE,QAAQ,CAAC,YAAY,GAAG,QAAQ,KAAK;AAAA,IACvC,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,MAAM;AAAA,EACtC;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;;;AC5FM,IAAM,4BAA4B;AAwClC,IAAM,0BAAN,MAA0D;AAAA,EAM/D,YAAY,UAA0C,CAAC,GAAG;AAL1D,SAAiB,gBAAgB,oBAAI,IAA0B;AAC/D,SAAiB,eAAe,oBAAI,IAAyB;AAC7D,SAAQ,UAAU;AAIhB,SAAK,mBAAmB,QAAQ,oBAAoB;AAAA,EACtD;AAAA,EAEA,MAAM,QAAQ,OAA4C;AAExD,eAAW,OAAO,KAAK,cAAc,OAAO,GAAG;AAC7C,UAAI,KAAK,oBAAoB,OAAO,GAAG,GAAG;AACxC,YAAI;AACF,gBAAM,IAAI,QAAQ,KAAK;AAAA,QACzB,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UACJ,SACA,SACA,SACiB;AACjB,QAAI,KAAK,mBAAmB,KAAK,KAAK,cAAc,QAAQ,KAAK,kBAAkB;AACjF,YAAM,IAAI;AAAA,QACR,uCAAuC,KAAK,gBAAgB;AAAA,MAE9D;AAAA,IACF;AAEA,UAAM,KAAK,OAAO,EAAE,KAAK,OAAO;AAChC,UAAM,MAAoB,EAAE,IAAI,SAAS,SAAS,QAAQ;AAC1D,SAAK,cAAc,IAAI,IAAI,GAAG;AAG9B,QAAI,CAAC,KAAK,aAAa,IAAI,OAAO,GAAG;AACnC,WAAK,aAAa,IAAI,SAAS,oBAAI,IAAI,CAAC;AAAA,IAC1C;AACA,SAAK,aAAa,IAAI,OAAO,EAAG,IAAI,EAAE;AAEtC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,gBAAuC;AACvD,UAAM,MAAM,KAAK,cAAc,IAAI,cAAc;AACjD,QAAI,CAAC,IAAK;AAEV,SAAK,cAAc,OAAO,cAAc;AAGxC,UAAM,cAAc,KAAK,aAAa,IAAI,IAAI,OAAO;AACrD,QAAI,aAAa;AACf,kBAAY,OAAO,cAAc;AACjC,UAAI,YAAY,SAAS,GAAG;AAC1B,aAAK,aAAa,OAAO,IAAI,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA+B;AAC7B,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAwB;AACtB,WAAO,MAAM,KAAK,KAAK,aAAa,KAAK,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,OAA6B,KAA4B;AACnF,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,KAAM,QAAO;AAGlB,QAAI,KAAK,UAAU,MAAM,WAAW,KAAK,QAAQ;AAC/C,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,cAAc,KAAK,WAAW,SAAS,GAAG;AACjD,UAAI,CAAC,KAAK,WAAW,SAAS,MAAM,IAAI,GAAG;AACzC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;ACzHO,IAAM,wBAAN,MAA8C;AAAA,EAQnD,YAAY,UAAwC,CAAC,GAAG;AAPxD,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,WAAW,IAAI,wBAAwB,KAAK,QAAQ,MAAM;AAChE,QAAI,gBAAgB,YAAY,QAAQ;AAGxC,QAAI,WAAuC,UAAU,EAAE,SAAS;AAAA,MAC9D,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,MACX,SAAS,CAAC,WAAW;AAAA,IACvB,CAAC;AAGD,QAAI,OAAQ,IAAY,SAAS,YAAY;AAC3C,MAAC,IAAY,KAAK,gBAAgB,YAAY;AAC5C,YAAI;AACF,gBAAM,OAAO,IAAI,WAAgB,MAAM;AACvC,cAAI,QAAQ,OAAO,KAAK,qBAAqB,YAAY;AACvD,kBAAM,EAAE,sBAAAA,sBAAqB,IAAI,MAAM;AACvC,uBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQA,qBAAoB,GAAG;AACjE,mBAAK,iBAAiB,QAAQ,IAA+B;AAAA,YAC/D;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAAsB;AAAA,MAChC,CAAC;AAAA,IACH;AAEA,QAAI,OAAO,KAAK,8DAA8D;AAAA,EAChF;AACF;","names":["RealtimeTranslations"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/service-realtime",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.5.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Realtime Service for ObjectStack — implements IRealtimeService with WebSocket and in-memory pub/sub",
|
|
6
6
|
"type": "module",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@objectstack/core": "9.
|
|
18
|
-
"@objectstack/platform-objects": "9.
|
|
19
|
-
"@objectstack/spec": "9.
|
|
17
|
+
"@objectstack/core": "9.5.1",
|
|
18
|
+
"@objectstack/platform-objects": "9.5.1",
|
|
19
|
+
"@objectstack/spec": "9.5.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^25.9.2",
|