Skip to content

feat: implement service-i18n and service-realtime (Phase 4c)#728

Merged
hotlong merged 2 commits into
mainfrom
copilot/implement-i18n-and-realtime-services
Feb 19, 2026
Merged

feat: implement service-i18n and service-realtime (Phase 4c)#728
hotlong merged 2 commits into
mainfrom
copilot/implement-i18n-and-realtime-services

Conversation

Copilot AI commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

Implements II18nService and IRealtimeService contracts as new service-* packages, following existing adapter+plugin patterns from service-cache/queue/job/storage.

@objectstack/service-i18n

  • FileI18nAdapter — Loads {locale}.json files from disk, dot-notation key resolution, {{param}} interpolation, fallback locale chain
  • I18nServicePlugin — Registers as 'i18n' service on kernel init
  • 20 tests

@objectstack/service-realtime

  • InMemoryRealtimeAdapter — Map-backed pub/sub with channel routing, object/eventTypes subscription filtering, configurable maxSubscriptions, handler error isolation
  • RealtimeServicePlugin — Registers as 'realtime' service on kernel init
  • 14 tests

ROADMAP.md

  • Contract matrix: both marked ✅, implemented count 11→13 (52%)
  • Added to Package Status Matrix

Usage

import { I18nServicePlugin } from '@objectstack/service-i18n';
import { RealtimeServicePlugin } from '@objectstack/service-realtime';

kernel.use(new I18nServicePlugin({ localesDir: './i18n', fallbackLocale: 'en' }));
kernel.use(new RealtimeServicePlugin());
await kernel.bootstrap();

const i18n = kernel.getService('i18n');
i18n.t('objects.account.label', 'zh-CN'); // '客户'

const realtime = kernel.getService('realtime');
await realtime.subscribe('records', handler, { object: 'account', eventTypes: ['record.created'] });

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel

vercel Bot commented Feb 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectstack-play Ready Ready Preview, Comment Feb 19, 2026 2:23am
spec Ready Ready Preview, Comment Feb 19, 2026 2:23am

Request Review

- service-i18n: FileI18nAdapter with file-based JSON locale loading, dot-notation key resolution, parameter interpolation, fallback locale support (20 tests)
- service-realtime: InMemoryRealtimeAdapter with channel-based pub/sub, event type/object filtering, subscription limits (14 tests)
- Both packages follow existing service-* patterns with Plugin + Adapter architecture
- Updated ROADMAP.md contract matrix and package status

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement I18nService and IRealtimeService components feat: implement service-i18n and service-realtime (Phase 4c) Feb 19, 2026
Copilot AI requested a review from hotlong February 19, 2026 02:20
@hotlong
hotlong marked this pull request as ready for review February 19, 2026 02:42
Copilot AI review requested due to automatic review settings February 19, 2026 02:42
@hotlong
hotlong merged commit dfa3a4f into main Feb 19, 2026
3 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements two new service packages (@objectstack/service-i18n and @objectstack/service-realtime) to provide production-ready implementations of the II18nService and IRealtimeService contracts. Both packages follow the established adapter+plugin pattern used by existing services (cache, queue, job, storage).

Changes:

  • Adds @objectstack/service-i18n with file-based locale loading, dot-notation key resolution, parameter interpolation, and fallback locale support (20 tests)
  • Adds @objectstack/service-realtime with in-memory pub/sub, channel routing, event filtering, and error isolation (14 tests)
  • Updates ROADMAP.md contract implementation count from 11 to 13 (52%) and adds both packages to the Package Status Matrix

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/services/service-i18n/package.json Package configuration matching service-cache/queue/job/storage pattern with workspace dependencies
packages/services/service-i18n/tsconfig.json TypeScript config extending root tsconfig with src→dist compilation settings
packages/services/service-i18n/src/index.ts Public API exports for I18nServicePlugin and FileI18nAdapter
packages/services/service-i18n/src/i18n-service-plugin.ts Plugin implementing kernel registration pattern via ctx.registerService('i18n', adapter)
packages/services/service-i18n/src/file-i18n-adapter.ts II18nService implementation with JSON file loading, nested key resolution, and parameter interpolation
packages/services/service-i18n/src/file-i18n-adapter.test.ts Comprehensive test suite (20 tests) covering all adapter features including edge cases
packages/services/service-realtime/package.json Package configuration matching other service packages
packages/services/service-realtime/tsconfig.json TypeScript config extending root tsconfig
packages/services/service-realtime/src/index.ts Public API exports for RealtimeServicePlugin and InMemoryRealtimeAdapter
packages/services/service-realtime/src/realtime-service-plugin.ts Plugin implementing kernel registration pattern via ctx.registerService('realtime', adapter)
packages/services/service-realtime/src/in-memory-realtime-adapter.ts IRealtimeService implementation with Map-backed pub/sub, subscription filtering, and maxSubscriptions limit
packages/services/service-realtime/src/in-memory-realtime-adapter.test.ts Test suite (14 tests) covering subscription lifecycle, filtering, and error handling
ROADMAP.md Updates contract implementation count (11→13, 52%), marks both services as complete, and adds Package Status Matrix entries
pnpm-lock.yaml Lockfile updates for two new workspace packages with their dependencies
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +65 to +76
async publish(event: RealtimeEventPayload): Promise<void> {
// Deliver to all channel subscriptions that match filters
for (const sub of this.subscriptions.values()) {
if (this.matchesSubscription(event, sub)) {
try {
await sub.handler(event);
} catch {
// Swallow handler errors to avoid breaking the publish loop
}
}
}
}

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The publish method iterates through ALL subscriptions regardless of channel, making the channelIndex unused. This means events are broadcast to all subscribers system-wide, even if they subscribed to different channels. For proper pub/sub semantics, consider limiting event delivery to subscriptions on matching channels. The channelIndex is built but never consulted during publish.

Copilot uses AI. Check for mistakes.
await realtime.unsubscribe(sub1);
expect(realtime.getChannels()).not.toContain('records');
});
});

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test case to verify that subscriptions to different channels don't receive each other's events. This would catch the channel isolation issue in the publish method where it currently broadcasts to all subscriptions regardless of channel.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants