Skip to content

Commit 84042de

Browse files
authored
Merge pull request #946 from objectstack-ai/copilot/implement-service-analytics-plugin
2 parents 69b67c7 + ac2177b commit 84042de

17 files changed

Lines changed: 1596 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3232
now return proper metadata responses instead of throwing 500 errors.
3333

3434
### Added
35+
- **`@objectstack/service-analytics`** — New multi-driver analytics service implementing `IAnalyticsService`.
36+
Uses a **Strategy Pattern** with priority-ordered chain: **P1 NativeSQLStrategy** (pushes queries as
37+
native SQL to Postgres/MySQL drivers), **P2 ObjectQLStrategy** (translates to ObjectQL `aggregate()` AST),
38+
**P3 InMemoryStrategy** (delegates to existing `MemoryAnalyticsService` for dev/test). Includes
39+
`CubeRegistry` for auto-discovery of cubes from manifest definitions and object schema inference,
40+
`AnalyticsServicePlugin` for kernel plugin lifecycle, `generateSql()` dry-run capability, and
41+
`queryCapabilities()` driver probing for dynamic strategy selection. 34 unit tests covering all
42+
strategy branches.
3543
- **Studio system objects visibility** — Studio now auto-registers all system objects (sys_user,
3644
sys_role, sys_audit_log, etc.) from plugin-auth, plugin-security, and plugin-audit at kernel
3745
initialization. The sidebar "System" group dynamically lists all `isSystem=true` objects

ROADMAP.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,13 +532,13 @@ Objects now declare `namespace: 'sys'` and a short `name` (e.g., `name: 'user'`)
532532
| `IWorkflowService` | **P2** | `@objectstack/service-workflow` | State machine + approval processes |
533533
| `IGraphQLService` | **P2** | `@objectstack/service-graphql` | Auto-generated GraphQL from objects |
534534
| `IAIService` | **P2** | `@objectstack/service-ai` | LLM integration (OpenAI/Anthropic/local) |
535-
| `IAnalyticsService` | **P3** | `@objectstack/service-analytics` | BI/OLAP queries |
535+
| `IAnalyticsService` | **P3** | `@objectstack/service-analytics` | ✅ Multi-driver analytics with strategy pattern (NativeSQL/ObjectQL/InMemory), CubeRegistry, generateSql (34 tests) |
536536

537537
- [x] `service-automation` — Implement `IAutomationService` with plugin-based DAG flow engine (CRUD/Logic/HTTP nodes, fault edges, parallel branches, cycle detection, safe eval, timeout, versioning), HTTP API CRUD (9 routes), Client SDK (10 methods), execution history with step-level logging
538538
- [ ] `service-workflow` — Implement `IWorkflowService` with state machine runtime
539539
- [ ] `service-graphql` — Implement `IGraphQLService` with auto-schema generation
540540
- [ ] `service-ai` — Implement `IAIService` with multi-provider LLM routing
541-
- [ ] `service-analytics` — Implement full `IAnalyticsService` beyond memory reference
541+
- [x] `service-analytics` — Implement full `IAnalyticsService` with multi-driver strategy pattern (NativeSQLStrategy P1, ObjectQLStrategy P2, InMemoryStrategy P3), CubeRegistry with auto-inference from object schemas, generateSql dry-run, kernel plugin lifecycle
542542

543543
---
544544

@@ -855,7 +855,7 @@ Final polish and advanced features.
855855
| 5 | HTTP Server | `IHttpServer` || `@objectstack/plugin-hono-server``@objectstack/service-http` in v4.0 | Hono-based server |
856856
| 6 | Logger | `Logger` || `@objectstack/core` | Pino-based structured logging |
857857
| 7 | Service Registry | `IServiceRegistry` || `@objectstack/core` | Built into ObjectKernel |
858-
| 8 | Analytics Service | `IAnalyticsService` | 🟡 | `@objectstack/driver-memory` | Memory reference only |
858+
| 8 | Analytics Service | `IAnalyticsService` | | `@objectstack/service-analytics` | Multi-driver strategy pattern (NativeSQL/ObjectQL/InMemory), CubeRegistry, generateSql (34 tests) |
859859
| 9 | Plugin Lifecycle | `IPluginLifecycleEvents` | 🟡 | `@objectstack/core` | Partial in kernel |
860860
| 10 | Cache Service | `ICacheService` || `@objectstack/service-cache` | Memory + Redis skeleton |
861861
| 11 | Queue Service | `IQueueService` || `@objectstack/service-queue` | Memory + BullMQ skeleton |
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import type { AnalyticsQuery, AnalyticsResult, AnalyticsStrategy, StrategyContext } from '@objectstack/spec/contracts';
4+
5+
/**
6+
* InMemoryStrategy — Priority 3
7+
*
8+
* Delegates to an existing `IAnalyticsService` instance that was registered
9+
* as a fallback (typically `MemoryAnalyticsService` from this package).
10+
*
11+
* This is the lowest-priority strategy, used in:
12+
* - `dev` / `test` environments
13+
* - Any runtime where the backing driver is in-memory
14+
*/
15+
export class InMemoryStrategy implements AnalyticsStrategy {
16+
readonly name = 'InMemoryStrategy';
17+
readonly priority = 30;
18+
19+
canHandle(query: AnalyticsQuery, ctx: StrategyContext): boolean {
20+
if (!query.cube) return false;
21+
// Can handle when a fallback service exists
22+
if (ctx.fallbackService) return true;
23+
// Or when the driver is flagged as in-memory
24+
const caps = ctx.queryCapabilities(query.cube);
25+
return caps.inMemory;
26+
}
27+
28+
async execute(query: AnalyticsQuery, ctx: StrategyContext): Promise<AnalyticsResult> {
29+
if (!ctx.fallbackService) {
30+
throw new Error(
31+
`[InMemoryStrategy] No fallback analytics service available for cube "${query.cube}". ` +
32+
'Register a MemoryAnalyticsService or configure a driver with analytics support.'
33+
);
34+
}
35+
return ctx.fallbackService.query(query);
36+
}
37+
38+
async generateSql(query: AnalyticsQuery, ctx: StrategyContext): Promise<{ sql: string; params: unknown[] }> {
39+
if (ctx.fallbackService?.generateSql) {
40+
return ctx.fallbackService.generateSql(query);
41+
}
42+
return {
43+
sql: `-- InMemoryStrategy: SQL generation not supported for cube "${query.cube}"`,
44+
params: [],
45+
};
46+
}
47+
}

packages/plugins/driver-memory/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export { LocalStoragePersistenceAdapter } from './persistence/local-storage-adap
1111
export { MemoryAnalyticsService } from './memory-analytics.js';
1212
export type { MemoryAnalyticsConfig } from './memory-analytics.js';
1313

14+
export { InMemoryStrategy } from './in-memory-strategy.js';
15+
1416
export default {
1517
id: 'com.objectstack.driver.memory',
1618
version: '1.0.0',
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Changelog — @objectstack/service-analytics
2+
3+
All notable changes to this package will be documented in this file.
4+
5+
## [3.2.9] — 2026-03-22
6+
7+
### Added
8+
9+
- Initial implementation of `@objectstack/service-analytics`
10+
- `AnalyticsService` orchestrator implementing `IAnalyticsService`
11+
- Strategy pattern with priority chain:
12+
- **P1 — NativeSQLStrategy**: Pushes queries as native SQL to SQL-capable drivers (Postgres, MySQL, etc.)
13+
- **P2 — ObjectQLStrategy**: Translates analytics queries into ObjectQL `engine.aggregate()` calls
14+
- **P3 — InMemoryStrategy**: Delegates to any registered `IAnalyticsService` (e.g., `MemoryAnalyticsService`)
15+
- `CubeRegistry` for auto-discovery and registration of cubes from manifest definitions and object schema inference
16+
- `AnalyticsServicePlugin` for kernel plugin lifecycle integration
17+
- `queryCapabilities()` driver capability probing for strategy selection
18+
- `generateSql()` dry-run SQL generation across all strategies
19+
- Unit tests covering all strategy branches
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "@objectstack/service-analytics",
3+
"version": "3.2.9",
4+
"license": "Apache-2.0",
5+
"description": "Analytics Service for ObjectStack — implements IAnalyticsService with multi-driver strategy pattern (NativeSQL, ObjectQL, InMemory)",
6+
"type": "module",
7+
"main": "dist/index.js",
8+
"types": "dist/index.d.ts",
9+
"exports": {
10+
".": {
11+
"types": "./dist/index.d.ts",
12+
"import": "./dist/index.mjs",
13+
"require": "./dist/index.js"
14+
}
15+
},
16+
"scripts": {
17+
"build": "tsup --config ../../../tsup.config.ts",
18+
"test": "vitest run"
19+
},
20+
"dependencies": {
21+
"@objectstack/core": "workspace:*",
22+
"@objectstack/spec": "workspace:*"
23+
},
24+
"devDependencies": {
25+
"typescript": "^5.0.0",
26+
"vitest": "^4.1.0",
27+
"@types/node": "^25.5.0"
28+
}
29+
}

0 commit comments

Comments
 (0)