@pattern-stack/codegen 0.2.0
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/CHANGELOG.md +67 -0
- package/README.md +214 -0
- package/dist/runtime/analytics/index.d.ts +6 -0
- package/dist/runtime/analytics/index.js +49 -0
- package/dist/runtime/analytics/index.js.map +1 -0
- package/dist/runtime/analytics/metrics.d.ts +75 -0
- package/dist/runtime/analytics/metrics.js +1 -0
- package/dist/runtime/analytics/metrics.js.map +1 -0
- package/dist/runtime/analytics/packs/crm-entity-measures.d.ts +21 -0
- package/dist/runtime/analytics/packs/crm-entity-measures.js +1 -0
- package/dist/runtime/analytics/packs/crm-entity-measures.js.map +1 -0
- package/dist/runtime/analytics/packs/index.d.ts +3 -0
- package/dist/runtime/analytics/packs/index.js +1 -0
- package/dist/runtime/analytics/packs/index.js.map +1 -0
- package/dist/runtime/analytics/packs/monetary-measures.d.ts +21 -0
- package/dist/runtime/analytics/packs/monetary-measures.js +1 -0
- package/dist/runtime/analytics/packs/monetary-measures.js.map +1 -0
- package/dist/runtime/analytics/specs.d.ts +49 -0
- package/dist/runtime/analytics/specs.js +1 -0
- package/dist/runtime/analytics/specs.js.map +1 -0
- package/dist/runtime/analytics/types.d.ts +85 -0
- package/dist/runtime/analytics/types.js +49 -0
- package/dist/runtime/analytics/types.js.map +1 -0
- package/dist/runtime/base-classes/activity-entity-repository.d.ts +26 -0
- package/dist/runtime/base-classes/activity-entity-repository.js +195 -0
- package/dist/runtime/base-classes/activity-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/activity-entity-service.d.ts +39 -0
- package/dist/runtime/base-classes/activity-entity-service.js +214 -0
- package/dist/runtime/base-classes/activity-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/base-read-use-cases.d.ts +68 -0
- package/dist/runtime/base-classes/base-read-use-cases.js +32 -0
- package/dist/runtime/base-classes/base-read-use-cases.js.map +1 -0
- package/dist/runtime/base-classes/base-repository.d.ts +99 -0
- package/dist/runtime/base-classes/base-repository.js +160 -0
- package/dist/runtime/base-classes/base-repository.js.map +1 -0
- package/dist/runtime/base-classes/base-service.d.ts +98 -0
- package/dist/runtime/base-classes/base-service.js +186 -0
- package/dist/runtime/base-classes/base-service.js.map +1 -0
- package/dist/runtime/base-classes/index.d.ts +18 -0
- package/dist/runtime/base-classes/index.js +617 -0
- package/dist/runtime/base-classes/index.js.map +1 -0
- package/dist/runtime/base-classes/knowledge-entity-repository.d.ts +17 -0
- package/dist/runtime/base-classes/knowledge-entity-repository.js +166 -0
- package/dist/runtime/base-classes/knowledge-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/knowledge-entity-service.d.ts +15 -0
- package/dist/runtime/base-classes/knowledge-entity-service.js +192 -0
- package/dist/runtime/base-classes/knowledge-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/lifecycle-events.d.ts +49 -0
- package/dist/runtime/base-classes/lifecycle-events.js +76 -0
- package/dist/runtime/base-classes/lifecycle-events.js.map +1 -0
- package/dist/runtime/base-classes/metadata-entity-repository.d.ts +27 -0
- package/dist/runtime/base-classes/metadata-entity-repository.js +212 -0
- package/dist/runtime/base-classes/metadata-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/metadata-entity-service.d.ts +39 -0
- package/dist/runtime/base-classes/metadata-entity-service.js +214 -0
- package/dist/runtime/base-classes/metadata-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/synced-entity-repository.d.ts +32 -0
- package/dist/runtime/base-classes/synced-entity-repository.js +203 -0
- package/dist/runtime/base-classes/synced-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/synced-entity-service.d.ts +41 -0
- package/dist/runtime/base-classes/synced-entity-service.js +215 -0
- package/dist/runtime/base-classes/synced-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/with-analytics.d.ts +18 -0
- package/dist/runtime/base-classes/with-analytics.js +11 -0
- package/dist/runtime/base-classes/with-analytics.js.map +1 -0
- package/dist/runtime/constants/tokens.d.ts +29 -0
- package/dist/runtime/constants/tokens.js +8 -0
- package/dist/runtime/constants/tokens.js.map +1 -0
- package/dist/runtime/subsystems/analytics/analytics-query.protocol.d.ts +30 -0
- package/dist/runtime/subsystems/analytics/analytics-query.protocol.js +1 -0
- package/dist/runtime/subsystems/analytics/analytics-query.protocol.js.map +1 -0
- package/dist/runtime/subsystems/analytics/analytics.module.d.ts +34 -0
- package/dist/runtime/subsystems/analytics/analytics.module.js +117 -0
- package/dist/runtime/subsystems/analytics/analytics.module.js.map +1 -0
- package/dist/runtime/subsystems/analytics/analytics.tokens.d.ts +24 -0
- package/dist/runtime/subsystems/analytics/analytics.tokens.js +10 -0
- package/dist/runtime/subsystems/analytics/analytics.tokens.js.map +1 -0
- package/dist/runtime/subsystems/analytics/cube-backend.d.ts +28 -0
- package/dist/runtime/subsystems/analytics/cube-backend.js +71 -0
- package/dist/runtime/subsystems/analytics/cube-backend.js.map +1 -0
- package/dist/runtime/subsystems/analytics/index.d.ts +6 -0
- package/dist/runtime/subsystems/analytics/index.js +122 -0
- package/dist/runtime/subsystems/analytics/index.js.map +1 -0
- package/dist/runtime/subsystems/analytics/noop-backend.d.ts +7 -0
- package/dist/runtime/subsystems/analytics/noop-backend.js +25 -0
- package/dist/runtime/subsystems/analytics/noop-backend.js.map +1 -0
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.d.ts +43 -0
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.js +133 -0
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/cache/cache.memory-backend.d.ts +21 -0
- package/dist/runtime/subsystems/cache/cache.memory-backend.js +100 -0
- package/dist/runtime/subsystems/cache/cache.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/cache/cache.module.d.ts +37 -0
- package/dist/runtime/subsystems/cache/cache.module.js +272 -0
- package/dist/runtime/subsystems/cache/cache.module.js.map +1 -0
- package/dist/runtime/subsystems/cache/cache.protocol.d.ts +42 -0
- package/dist/runtime/subsystems/cache/cache.protocol.js +1 -0
- package/dist/runtime/subsystems/cache/cache.protocol.js.map +1 -0
- package/dist/runtime/subsystems/cache/cache.schema.d.ts +64 -0
- package/dist/runtime/subsystems/cache/cache.schema.js +18 -0
- package/dist/runtime/subsystems/cache/cache.schema.js.map +1 -0
- package/dist/runtime/subsystems/cache/cache.tokens.d.ts +18 -0
- package/dist/runtime/subsystems/cache/cache.tokens.js +8 -0
- package/dist/runtime/subsystems/cache/cache.tokens.js.map +1 -0
- package/dist/runtime/subsystems/cache/index.d.ts +11 -0
- package/dist/runtime/subsystems/cache/index.js +277 -0
- package/dist/runtime/subsystems/cache/index.js.map +1 -0
- package/dist/runtime/subsystems/events/domain-events.schema.d.ts +187 -0
- package/dist/runtime/subsystems/events/domain-events.schema.js +32 -0
- package/dist/runtime/subsystems/events/domain-events.schema.js.map +1 -0
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.d.ts +38 -0
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +199 -0
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/events/event-bus.memory-backend.d.ts +18 -0
- package/dist/runtime/subsystems/events/event-bus.memory-backend.js +71 -0
- package/dist/runtime/subsystems/events/event-bus.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/events/event-bus.protocol.d.ts +52 -0
- package/dist/runtime/subsystems/events/event-bus.protocol.js +1 -0
- package/dist/runtime/subsystems/events/event-bus.protocol.js.map +1 -0
- package/dist/runtime/subsystems/events/event-bus.redis-backend.d.ts +95 -0
- package/dist/runtime/subsystems/events/event-bus.redis-backend.js +229 -0
- package/dist/runtime/subsystems/events/event-bus.redis-backend.js.map +1 -0
- package/dist/runtime/subsystems/events/events.module.d.ts +46 -0
- package/dist/runtime/subsystems/events/events.module.js +531 -0
- package/dist/runtime/subsystems/events/events.module.js.map +1 -0
- package/dist/runtime/subsystems/events/events.tokens.d.ts +19 -0
- package/dist/runtime/subsystems/events/events.tokens.js +8 -0
- package/dist/runtime/subsystems/events/events.tokens.js.map +1 -0
- package/dist/runtime/subsystems/events/index.d.ts +12 -0
- package/dist/runtime/subsystems/events/index.js +536 -0
- package/dist/runtime/subsystems/events/index.js.map +1 -0
- package/dist/runtime/subsystems/index.d.ts +24 -0
- package/dist/runtime/subsystems/index.js +1643 -0
- package/dist/runtime/subsystems/index.js.map +1 -0
- package/dist/runtime/subsystems/jobs/index.d.ts +14 -0
- package/dist/runtime/subsystems/jobs/index.js +680 -0
- package/dist/runtime/subsystems/jobs/index.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.bullmq-backend.d.ts +54 -0
- package/dist/runtime/subsystems/jobs/job-queue.bullmq-backend.js +186 -0
- package/dist/runtime/subsystems/jobs/job-queue.bullmq-backend.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.drizzle-backend.d.ts +38 -0
- package/dist/runtime/subsystems/jobs/job-queue.drizzle-backend.js +228 -0
- package/dist/runtime/subsystems/jobs/job-queue.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.memory-backend.d.ts +12 -0
- package/dist/runtime/subsystems/jobs/job-queue.memory-backend.js +44 -0
- package/dist/runtime/subsystems/jobs/job-queue.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.protocol.d.ts +48 -0
- package/dist/runtime/subsystems/jobs/job-queue.protocol.js +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.protocol.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.redis-backend.d.ts +46 -0
- package/dist/runtime/subsystems/jobs/job-queue.redis-backend.js +187 -0
- package/dist/runtime/subsystems/jobs/job-queue.redis-backend.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-queue.schema.d.ts +237 -0
- package/dist/runtime/subsystems/jobs/job-queue.schema.js +44 -0
- package/dist/runtime/subsystems/jobs/job-queue.schema.js.map +1 -0
- package/dist/runtime/subsystems/jobs/jobs.module.d.ts +18 -0
- package/dist/runtime/subsystems/jobs/jobs.module.js +676 -0
- package/dist/runtime/subsystems/jobs/jobs.module.js.map +1 -0
- package/dist/runtime/subsystems/jobs/jobs.tokens.d.ts +13 -0
- package/dist/runtime/subsystems/jobs/jobs.tokens.js +8 -0
- package/dist/runtime/subsystems/jobs/jobs.tokens.js.map +1 -0
- package/dist/runtime/subsystems/storage/index.d.ts +6 -0
- package/dist/runtime/subsystems/storage/index.js +204 -0
- package/dist/runtime/subsystems/storage/index.js.map +1 -0
- package/dist/runtime/subsystems/storage/storage.local-backend.d.ts +18 -0
- package/dist/runtime/subsystems/storage/storage.local-backend.js +108 -0
- package/dist/runtime/subsystems/storage/storage.local-backend.js.map +1 -0
- package/dist/runtime/subsystems/storage/storage.memory-backend.d.ts +28 -0
- package/dist/runtime/subsystems/storage/storage.memory-backend.js +72 -0
- package/dist/runtime/subsystems/storage/storage.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/storage/storage.module.d.ts +40 -0
- package/dist/runtime/subsystems/storage/storage.module.js +201 -0
- package/dist/runtime/subsystems/storage/storage.module.js.map +1 -0
- package/dist/runtime/subsystems/storage/storage.protocol.d.ts +69 -0
- package/dist/runtime/subsystems/storage/storage.protocol.js +1 -0
- package/dist/runtime/subsystems/storage/storage.protocol.js.map +1 -0
- package/dist/runtime/subsystems/storage/storage.tokens.d.ts +11 -0
- package/dist/runtime/subsystems/storage/storage.tokens.js +6 -0
- package/dist/runtime/subsystems/storage/storage.tokens.js.map +1 -0
- package/dist/runtime/subsystems/storage/storage.utils.d.ts +9 -0
- package/dist/runtime/subsystems/storage/storage.utils.js +18 -0
- package/dist/runtime/subsystems/storage/storage.utils.js.map +1 -0
- package/dist/runtime/types/drizzle.d.ts +17 -0
- package/dist/runtime/types/drizzle.js +1 -0
- package/dist/runtime/types/drizzle.js.map +1 -0
- package/dist/src/cli/index.d.ts +1 -0
- package/dist/src/cli/index.js +7365 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/index.d.ts +2384 -0
- package/dist/src/index.js +2198 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +114 -0
- package/templates/broadcast/new/backend-interface.ejs.t +47 -0
- package/templates/broadcast/new/bridge-listener.ejs.t +67 -0
- package/templates/broadcast/new/channel.ejs.t +77 -0
- package/templates/broadcast/new/index.ejs.t +21 -0
- package/templates/broadcast/new/memory-backend.ejs.t +87 -0
- package/templates/broadcast/new/module.ejs.t +57 -0
- package/templates/broadcast/new/prompt.js +268 -0
- package/templates/broadcast/new/websocket-backend.ejs.t +259 -0
- package/templates/entity/new/backend/application/commands/create.ejs.t +55 -0
- package/templates/entity/new/backend/application/commands/delete.ejs.t +45 -0
- package/templates/entity/new/backend/application/commands/grouped-index.ejs.t +149 -0
- package/templates/entity/new/backend/application/commands/index.ejs.t +15 -0
- package/templates/entity/new/backend/application/commands/update.ejs.t +58 -0
- package/templates/entity/new/backend/application/queries/declarative-queries.ejs.t +36 -0
- package/templates/entity/new/backend/application/queries/get-by-id.ejs.t +42 -0
- package/templates/entity/new/backend/application/queries/grouped-index.ejs.t +81 -0
- package/templates/entity/new/backend/application/queries/index.ejs.t +14 -0
- package/templates/entity/new/backend/application/queries/list.ejs.t +36 -0
- package/templates/entity/new/backend/application/schemas/_inject-index.ejs.t +7 -0
- package/templates/entity/new/backend/application/schemas/dto.ejs.t +45 -0
- package/templates/entity/new/backend/database/_inject-index.ejs.t +7 -0
- package/templates/entity/new/backend/database/electric-migration.ejs.t +21 -0
- package/templates/entity/new/backend/database/repository.ejs.t +450 -0
- package/templates/entity/new/backend/database/schema.ejs.t +248 -0
- package/templates/entity/new/backend/domain/_inject-index.ejs.t +12 -0
- package/templates/entity/new/backend/domain/entity.ejs.t +108 -0
- package/templates/entity/new/backend/domain/grouped-index.ejs.t +163 -0
- package/templates/entity/new/backend/domain/index.ejs.t +15 -0
- package/templates/entity/new/backend/domain/repository-interface.ejs.t +71 -0
- package/templates/entity/new/backend/modules/core/_ensure-anchor-tokens.ejs.t +10 -0
- package/templates/entity/new/backend/modules/core/_inject-token.ejs.t +7 -0
- package/templates/entity/new/backend/modules/core/module.ejs.t +67 -0
- package/templates/entity/new/backend/modules/trpc/module.ejs.t +67 -0
- package/templates/entity/new/backend/presentation/controller.ejs.t +201 -0
- package/templates/entity/new/clean-lite-ps/controller.ejs.t +37 -0
- package/templates/entity/new/clean-lite-ps/dto/create.ejs.t +17 -0
- package/templates/entity/new/clean-lite-ps/dto/output.ejs.t +25 -0
- package/templates/entity/new/clean-lite-ps/dto/update.ejs.t +11 -0
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +52 -0
- package/templates/entity/new/clean-lite-ps/index.ejs.t +20 -0
- package/templates/entity/new/clean-lite-ps/module.ejs.t +43 -0
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +617 -0
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +62 -0
- package/templates/entity/new/clean-lite-ps/service.ejs.t +34 -0
- package/templates/entity/new/clean-lite-ps/use-cases/declarative-queries.ejs.t +34 -0
- package/templates/entity/new/clean-lite-ps/use-cases/find-by-id.ejs.t +16 -0
- package/templates/entity/new/clean-lite-ps/use-cases/list.ejs.t +16 -0
- package/templates/entity/new/frontend/_inject-entities-entry.ejs.t +7 -0
- package/templates/entity/new/frontend/_inject-entities-import.ejs.t +7 -0
- package/templates/entity/new/frontend/collections/_ensure-anchor-collections.ejs.t +10 -0
- package/templates/entity/new/frontend/collections/_inject-index.ejs.t +9 -0
- package/templates/entity/new/frontend/collections/_inject-schema-import.ejs.t +9 -0
- package/templates/entity/new/frontend/collections/collection.ejs.t +61 -0
- package/templates/entity/new/frontend/collections/collections-base.ejs.t +24 -0
- package/templates/entity/new/frontend/entity/collection.ejs.t +172 -0
- package/templates/entity/new/frontend/entity/combined.ejs.t +474 -0
- package/templates/entity/new/frontend/entity/fields.ejs.t +104 -0
- package/templates/entity/new/frontend/entity/hooks.ejs.t +73 -0
- package/templates/entity/new/frontend/entity/index.ejs.t +21 -0
- package/templates/entity/new/frontend/entity/mutation-hooks.ejs.t +84 -0
- package/templates/entity/new/frontend/entity/mutations.ejs.t +38 -0
- package/templates/entity/new/frontend/entity/types.ejs.t +59 -0
- package/templates/entity/new/frontend/generated/_inject-index-export.ejs.t +7 -0
- package/templates/entity/new/frontend/generated/_inject-index-import.ejs.t +7 -0
- package/templates/entity/new/frontend/generated/_inject-index-registry.ejs.t +7 -0
- package/templates/entity/new/frontend/store/_inject-collection-import.ejs.t +9 -0
- package/templates/entity/new/frontend/store/_inject-collections.ejs.t +9 -0
- package/templates/entity/new/frontend/store/_inject-entity.ejs.t +9 -0
- package/templates/entity/new/frontend/store/_inject-import.ejs.t +9 -0
- package/templates/entity/new/frontend/store/_inject-lookups.ejs.t +9 -0
- package/templates/entity/new/frontend/store/_inject-resolve.ejs.t +10 -0
- package/templates/entity/new/frontend/store/hooks.ejs.t +72 -0
- package/templates/entity/new/frontend/unified-entity.ejs.t +28 -0
- package/templates/entity/new/prompt.js +1421 -0
- package/templates/relationship/new/controller.ejs.t +36 -0
- package/templates/relationship/new/dto/create.ejs.t +41 -0
- package/templates/relationship/new/dto/output.ejs.t +44 -0
- package/templates/relationship/new/dto/update.ejs.t +10 -0
- package/templates/relationship/new/entity.ejs.t +98 -0
- package/templates/relationship/new/index.ejs.t +19 -0
- package/templates/relationship/new/module.ejs.t +35 -0
- package/templates/relationship/new/prompt.js +682 -0
- package/templates/relationship/new/repository.ejs.t +54 -0
- package/templates/relationship/new/service.ejs.t +31 -0
- package/templates/relationship/new/use-cases/declarative-queries.ejs.t +34 -0
- package/templates/relationship/new/use-cases/find-by-id.ejs.t +16 -0
- package/templates/relationship/new/use-cases/list.ejs.t +16 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics subsystem — protocol (port)
|
|
3
|
+
*
|
|
4
|
+
* IAnalyticsQuery is the hexagonal port. Services inject this interface via
|
|
5
|
+
* the ANALYTICS_QUERY token. They never depend on a specific backend
|
|
6
|
+
* implementation (cube.js, noop, etc.).
|
|
7
|
+
*/
|
|
8
|
+
interface ResultRow {
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
interface AnalyticsQueryOpts {
|
|
12
|
+
/** Include raw entity IDs in the result set. */
|
|
13
|
+
withIds?: boolean;
|
|
14
|
+
/** Maximum number of rows to return. */
|
|
15
|
+
limit?: number;
|
|
16
|
+
}
|
|
17
|
+
interface IAnalyticsQuery {
|
|
18
|
+
/**
|
|
19
|
+
* Execute an analytics query against the semantic layer.
|
|
20
|
+
*
|
|
21
|
+
* @param cube - Cube name (e.g., 'Orders')
|
|
22
|
+
* @param measures - Measure names (e.g., ['totalRevenue'])
|
|
23
|
+
* @param dimensions - Dimension names (e.g., ['status', 'createdAt'])
|
|
24
|
+
* @param where - Optional filter conditions
|
|
25
|
+
* @param opts - Query options (limit, withIds)
|
|
26
|
+
*/
|
|
27
|
+
execute(cube: string, measures: string[], dimensions: string[], where?: Record<string, any>, opts?: AnalyticsQueryOpts): Promise<ResultRow[]>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type { AnalyticsQueryOpts, IAnalyticsQuery, ResultRow };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=analytics-query.protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AnalyticsModule — DynamicModule factory for the analytics query subsystem.
|
|
5
|
+
*
|
|
6
|
+
* Register once in AppModule:
|
|
7
|
+
* ```typescript
|
|
8
|
+
* @Module({
|
|
9
|
+
* imports: [
|
|
10
|
+
* AnalyticsModule.forRoot({ backend: 'cube' }),
|
|
11
|
+
* ],
|
|
12
|
+
* })
|
|
13
|
+
* export class AppModule {}
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Tests swap to the noop backend without touching application code:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* Test.createTestingModule({
|
|
19
|
+
* imports: [AnalyticsModule.forRoot({ backend: 'noop' })],
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* `global: true` means entity modules do not need to import AnalyticsModule
|
|
24
|
+
* individually — the ANALYTICS_QUERY token is available project-wide.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
interface AnalyticsModuleOptions {
|
|
28
|
+
backend: 'cube' | 'noop';
|
|
29
|
+
}
|
|
30
|
+
declare class AnalyticsModule {
|
|
31
|
+
static forRoot(options?: AnalyticsModuleOptions): DynamicModule;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { AnalyticsModule, type AnalyticsModuleOptions };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
12
|
+
|
|
13
|
+
// runtime/subsystems/analytics/analytics.module.ts
|
|
14
|
+
import { Module } from "@nestjs/common";
|
|
15
|
+
|
|
16
|
+
// runtime/subsystems/analytics/analytics.tokens.ts
|
|
17
|
+
var ANALYTICS_QUERY = "ANALYTICS_QUERY";
|
|
18
|
+
var CUBE_API_URL = /* @__PURE__ */ Symbol("CUBE_API_URL");
|
|
19
|
+
var CUBE_API_SECRET = /* @__PURE__ */ Symbol("CUBE_API_SECRET");
|
|
20
|
+
|
|
21
|
+
// runtime/subsystems/analytics/cube-backend.ts
|
|
22
|
+
import { Inject, Injectable, Logger } from "@nestjs/common";
|
|
23
|
+
var CubeAnalyticsBackend = class {
|
|
24
|
+
constructor(apiUrl, apiSecret) {
|
|
25
|
+
this.apiUrl = apiUrl;
|
|
26
|
+
this.apiSecret = apiSecret;
|
|
27
|
+
}
|
|
28
|
+
apiUrl;
|
|
29
|
+
apiSecret;
|
|
30
|
+
logger = new Logger(CubeAnalyticsBackend.name);
|
|
31
|
+
cubejsApi;
|
|
32
|
+
async onModuleInit() {
|
|
33
|
+
try {
|
|
34
|
+
const { default: cubejs } = await import("@cubejs-client/core");
|
|
35
|
+
this.cubejsApi = cubejs(this.apiSecret, { apiUrl: this.apiUrl });
|
|
36
|
+
} catch {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"CubeAnalyticsBackend requires @cubejs-client/core. Install it: bun add @cubejs-client/core"
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async execute(cube, measures, dimensions, where, opts) {
|
|
43
|
+
if (!this.cubejsApi) {
|
|
44
|
+
this.logger.warn("Cube.js client not initialized \u2014 returning empty result");
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
const query = {
|
|
48
|
+
measures: measures.map((m) => cube + "." + m),
|
|
49
|
+
dimensions: dimensions.map((d) => cube + "." + d)
|
|
50
|
+
};
|
|
51
|
+
if (where && Object.keys(where).length > 0) {
|
|
52
|
+
query.filters = Object.entries(where).map(([member, value]) => ({
|
|
53
|
+
member: cube + "." + member,
|
|
54
|
+
operator: "equals",
|
|
55
|
+
values: Array.isArray(value) ? value : [String(value)]
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
if (opts?.limit) {
|
|
59
|
+
query.limit = opts.limit;
|
|
60
|
+
}
|
|
61
|
+
const resultSet = await this.cubejsApi.load(query);
|
|
62
|
+
return resultSet.tablePivot();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
CubeAnalyticsBackend = __decorateClass([
|
|
66
|
+
Injectable(),
|
|
67
|
+
__decorateParam(0, Inject(CUBE_API_URL)),
|
|
68
|
+
__decorateParam(1, Inject(CUBE_API_SECRET))
|
|
69
|
+
], CubeAnalyticsBackend);
|
|
70
|
+
|
|
71
|
+
// runtime/subsystems/analytics/noop-backend.ts
|
|
72
|
+
import { Injectable as Injectable2 } from "@nestjs/common";
|
|
73
|
+
var NoopAnalyticsBackend = class {
|
|
74
|
+
async execute(_cube, _measures, _dimensions, _where, _opts) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
NoopAnalyticsBackend = __decorateClass([
|
|
79
|
+
Injectable2()
|
|
80
|
+
], NoopAnalyticsBackend);
|
|
81
|
+
|
|
82
|
+
// runtime/subsystems/analytics/analytics.module.ts
|
|
83
|
+
var AnalyticsModule = class {
|
|
84
|
+
static forRoot(options = { backend: "noop" }) {
|
|
85
|
+
if (options.backend === "cube") {
|
|
86
|
+
return {
|
|
87
|
+
module: AnalyticsModule,
|
|
88
|
+
global: true,
|
|
89
|
+
providers: [
|
|
90
|
+
{
|
|
91
|
+
provide: CUBE_API_URL,
|
|
92
|
+
useValue: process.env["CUBE_API_URL"] ?? "http://localhost:4000/cubejs-api/v1"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
provide: CUBE_API_SECRET,
|
|
96
|
+
useValue: process.env["CUBE_API_SECRET"] ?? ""
|
|
97
|
+
},
|
|
98
|
+
{ provide: ANALYTICS_QUERY, useClass: CubeAnalyticsBackend }
|
|
99
|
+
],
|
|
100
|
+
exports: [ANALYTICS_QUERY]
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
module: AnalyticsModule,
|
|
105
|
+
global: true,
|
|
106
|
+
providers: [{ provide: ANALYTICS_QUERY, useClass: NoopAnalyticsBackend }],
|
|
107
|
+
exports: [ANALYTICS_QUERY]
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
AnalyticsModule = __decorateClass([
|
|
112
|
+
Module({})
|
|
113
|
+
], AnalyticsModule);
|
|
114
|
+
export {
|
|
115
|
+
AnalyticsModule
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=analytics.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../runtime/subsystems/analytics/analytics.module.ts","../../../../runtime/subsystems/analytics/analytics.tokens.ts","../../../../runtime/subsystems/analytics/cube-backend.ts","../../../../runtime/subsystems/analytics/noop-backend.ts"],"sourcesContent":["/**\n * AnalyticsModule — DynamicModule factory for the analytics query subsystem.\n *\n * Register once in AppModule:\n * ```typescript\n * @Module({\n * imports: [\n * AnalyticsModule.forRoot({ backend: 'cube' }),\n * ],\n * })\n * export class AppModule {}\n * ```\n *\n * Tests swap to the noop backend without touching application code:\n * ```typescript\n * Test.createTestingModule({\n * imports: [AnalyticsModule.forRoot({ backend: 'noop' })],\n * });\n * ```\n *\n * `global: true` means entity modules do not need to import AnalyticsModule\n * individually — the ANALYTICS_QUERY token is available project-wide.\n */\nimport { Module, type DynamicModule } from '@nestjs/common';\nimport { ANALYTICS_QUERY, CUBE_API_URL, CUBE_API_SECRET } from './analytics.tokens';\nimport { CubeAnalyticsBackend } from './cube-backend';\nimport { NoopAnalyticsBackend } from './noop-backend';\n\nexport interface AnalyticsModuleOptions {\n backend: 'cube' | 'noop';\n}\n\n@Module({})\nexport class AnalyticsModule {\n static forRoot(\n options: AnalyticsModuleOptions = { backend: 'noop' },\n ): DynamicModule {\n if (options.backend === 'cube') {\n return {\n module: AnalyticsModule,\n global: true,\n providers: [\n {\n provide: CUBE_API_URL,\n useValue: process.env['CUBE_API_URL'] ?? 'http://localhost:4000/cubejs-api/v1',\n },\n {\n provide: CUBE_API_SECRET,\n useValue: process.env['CUBE_API_SECRET'] ?? '',\n },\n { provide: ANALYTICS_QUERY, useClass: CubeAnalyticsBackend },\n ],\n exports: [ANALYTICS_QUERY],\n };\n }\n\n return {\n module: AnalyticsModule,\n global: true,\n providers: [{ provide: ANALYTICS_QUERY, useClass: NoopAnalyticsBackend }],\n exports: [ANALYTICS_QUERY],\n };\n }\n}\n","/**\n * Injection tokens for the analytics subsystem.\n *\n * String constants (not Symbols) so they match by value across import\n * boundaries — same convention as events.tokens.ts.\n *\n * Usage in services:\n * ```typescript\n * constructor(@Inject(ANALYTICS_QUERY) private readonly analytics: IAnalyticsQuery) {}\n * ```\n */\nexport const ANALYTICS_QUERY = 'ANALYTICS_QUERY' as const;\n\n/**\n * Injection token for the cube.js API URL.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_URL = Symbol('CUBE_API_URL');\n\n/**\n * Injection token for the cube.js API secret.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_SECRET = Symbol('CUBE_API_SECRET');\n","/**\n * CubeAnalyticsBackend — cube.js backend for the analytics query port.\n *\n * Connects to a running cube.js instance via @cubejs-client/core and\n * translates IAnalyticsQuery calls into cube.js query objects.\n *\n * @cubejs-client/core is an optional peer dependency; lazy-imported so\n * the module loads even if the package isn't installed. Consumers who\n * use the cube backend must install it separately:\n * bun add @cubejs-client/core\n *\n * Provided by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nimport { Inject, Injectable, OnModuleInit, Logger } from '@nestjs/common';\nimport { CUBE_API_URL, CUBE_API_SECRET } from './analytics.tokens';\nimport type {\n AnalyticsQueryOpts,\n IAnalyticsQuery,\n ResultRow,\n} from './analytics-query.protocol';\n\n@Injectable()\nexport class CubeAnalyticsBackend implements IAnalyticsQuery, OnModuleInit {\n private readonly logger = new Logger(CubeAnalyticsBackend.name);\n private cubejsApi: any;\n\n constructor(\n @Inject(CUBE_API_URL) private readonly apiUrl: string,\n @Inject(CUBE_API_SECRET) private readonly apiSecret: string,\n ) {}\n\n async onModuleInit(): Promise<void> {\n try {\n const { default: cubejs } = await import('@cubejs-client/core');\n this.cubejsApi = cubejs(this.apiSecret, { apiUrl: this.apiUrl });\n } catch {\n throw new Error(\n 'CubeAnalyticsBackend requires @cubejs-client/core. Install it: bun add @cubejs-client/core',\n );\n }\n }\n\n async execute(\n cube: string,\n measures: string[],\n dimensions: string[],\n where?: Record<string, any>,\n opts?: AnalyticsQueryOpts,\n ): Promise<ResultRow[]> {\n if (!this.cubejsApi) {\n this.logger.warn('Cube.js client not initialized — returning empty result');\n return [];\n }\n\n const query: Record<string, any> = {\n measures: measures.map((m) => cube + '.' + m),\n dimensions: dimensions.map((d) => cube + '.' + d),\n };\n\n if (where && Object.keys(where).length > 0) {\n query.filters = Object.entries(where).map(([member, value]) => ({\n member: cube + '.' + member,\n operator: 'equals',\n values: Array.isArray(value) ? value : [String(value)],\n }));\n }\n\n if (opts?.limit) {\n query.limit = opts.limit;\n }\n\n const resultSet = await this.cubejsApi.load(query);\n return resultSet.tablePivot() as ResultRow[];\n }\n}\n","/**\n * NoopAnalyticsBackend — no-op backend for the analytics query port.\n *\n * Returns empty arrays for all queries. Use this backend when analytics\n * is disabled or in tests that don't need real analytics data.\n *\n * Provided by AnalyticsModule.forRoot({ backend: 'noop' }).\n */\nimport { Injectable } from '@nestjs/common';\nimport type {\n AnalyticsQueryOpts,\n IAnalyticsQuery,\n ResultRow,\n} from './analytics-query.protocol';\n\n@Injectable()\nexport class NoopAnalyticsBackend implements IAnalyticsQuery {\n async execute(\n _cube: string,\n _measures: string[],\n _dimensions: string[],\n _where?: Record<string, any>,\n _opts?: AnalyticsQueryOpts,\n ): Promise<ResultRow[]> {\n return [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,SAAS,cAAkC;;;ACZpC,IAAM,kBAAkB;AAMxB,IAAM,eAAe,uBAAO,cAAc;AAM1C,IAAM,kBAAkB,uBAAO,iBAAiB;;;ACVvD,SAAS,QAAQ,YAA0B,cAAc;AASlD,IAAM,uBAAN,MAAoE;AAAA,EAIzE,YACyC,QACG,WAC1C;AAFuC;AACG;AAAA,EACzC;AAAA,EAFsC;AAAA,EACG;AAAA,EAL3B,SAAS,IAAI,OAAO,qBAAqB,IAAI;AAAA,EACtD;AAAA,EAOR,MAAM,eAA8B;AAClC,QAAI;AACF,YAAM,EAAE,SAAS,OAAO,IAAI,MAAM,OAAO,qBAAqB;AAC9D,WAAK,YAAY,OAAO,KAAK,WAAW,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QACJ,MACA,UACA,YACA,OACA,MACsB;AACtB,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,OAAO,KAAK,8DAAyD;AAC1E,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,QAA6B;AAAA,MACjC,UAAU,SAAS,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC;AAAA,MAC5C,YAAY,WAAW,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC;AAAA,IAClD;AAEA,QAAI,SAAS,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AAC1C,YAAM,UAAU,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;AAAA,QAC9D,QAAQ,OAAO,MAAM;AAAA,QACrB,UAAU;AAAA,QACV,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC;AAAA,MACvD,EAAE;AAAA,IACJ;AAEA,QAAI,MAAM,OAAO;AACf,YAAM,QAAQ,KAAK;AAAA,IACrB;AAEA,UAAM,YAAY,MAAM,KAAK,UAAU,KAAK,KAAK;AACjD,WAAO,UAAU,WAAW;AAAA,EAC9B;AACF;AApDa,uBAAN;AAAA,EADN,WAAW;AAAA,EAMP,0BAAO,YAAY;AAAA,EACnB,0BAAO,eAAe;AAAA,GANd;;;ACdb,SAAS,cAAAA,mBAAkB;AAQpB,IAAM,uBAAN,MAAsD;AAAA,EAC3D,MAAM,QACJ,OACA,WACA,aACA,QACA,OACsB;AACtB,WAAO,CAAC;AAAA,EACV;AACF;AAVa,uBAAN;AAAA,EADNC,YAAW;AAAA,GACC;;;AHiBN,IAAM,kBAAN,MAAsB;AAAA,EAC3B,OAAO,QACL,UAAkC,EAAE,SAAS,OAAO,GACrC;AACf,QAAI,QAAQ,YAAY,QAAQ;AAC9B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,WAAW;AAAA,UACT;AAAA,YACE,SAAS;AAAA,YACT,UAAU,QAAQ,IAAI,cAAc,KAAK;AAAA,UAC3C;AAAA,UACA;AAAA,YACE,SAAS;AAAA,YACT,UAAU,QAAQ,IAAI,iBAAiB,KAAK;AAAA,UAC9C;AAAA,UACA,EAAE,SAAS,iBAAiB,UAAU,qBAAqB;AAAA,QAC7D;AAAA,QACA,SAAS,CAAC,eAAe;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW,CAAC,EAAE,SAAS,iBAAiB,UAAU,qBAAqB,CAAC;AAAA,MACxE,SAAS,CAAC,eAAe;AAAA,IAC3B;AAAA,EACF;AACF;AA9Ba,kBAAN;AAAA,EADN,OAAO,CAAC,CAAC;AAAA,GACG;","names":["Injectable","Injectable"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injection tokens for the analytics subsystem.
|
|
3
|
+
*
|
|
4
|
+
* String constants (not Symbols) so they match by value across import
|
|
5
|
+
* boundaries — same convention as events.tokens.ts.
|
|
6
|
+
*
|
|
7
|
+
* Usage in services:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* constructor(@Inject(ANALYTICS_QUERY) private readonly analytics: IAnalyticsQuery) {}
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
declare const ANALYTICS_QUERY: "ANALYTICS_QUERY";
|
|
13
|
+
/**
|
|
14
|
+
* Injection token for the cube.js API URL.
|
|
15
|
+
* Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).
|
|
16
|
+
*/
|
|
17
|
+
declare const CUBE_API_URL: unique symbol;
|
|
18
|
+
/**
|
|
19
|
+
* Injection token for the cube.js API secret.
|
|
20
|
+
* Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).
|
|
21
|
+
*/
|
|
22
|
+
declare const CUBE_API_SECRET: unique symbol;
|
|
23
|
+
|
|
24
|
+
export { ANALYTICS_QUERY, CUBE_API_SECRET, CUBE_API_URL };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// runtime/subsystems/analytics/analytics.tokens.ts
|
|
2
|
+
var ANALYTICS_QUERY = "ANALYTICS_QUERY";
|
|
3
|
+
var CUBE_API_URL = /* @__PURE__ */ Symbol("CUBE_API_URL");
|
|
4
|
+
var CUBE_API_SECRET = /* @__PURE__ */ Symbol("CUBE_API_SECRET");
|
|
5
|
+
export {
|
|
6
|
+
ANALYTICS_QUERY,
|
|
7
|
+
CUBE_API_SECRET,
|
|
8
|
+
CUBE_API_URL
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=analytics.tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../runtime/subsystems/analytics/analytics.tokens.ts"],"sourcesContent":["/**\n * Injection tokens for the analytics subsystem.\n *\n * String constants (not Symbols) so they match by value across import\n * boundaries — same convention as events.tokens.ts.\n *\n * Usage in services:\n * ```typescript\n * constructor(@Inject(ANALYTICS_QUERY) private readonly analytics: IAnalyticsQuery) {}\n * ```\n */\nexport const ANALYTICS_QUERY = 'ANALYTICS_QUERY' as const;\n\n/**\n * Injection token for the cube.js API URL.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_URL = Symbol('CUBE_API_URL');\n\n/**\n * Injection token for the cube.js API secret.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_SECRET = Symbol('CUBE_API_SECRET');\n"],"mappings":";AAWO,IAAM,kBAAkB;AAMxB,IAAM,eAAe,uBAAO,cAAc;AAM1C,IAAM,kBAAkB,uBAAO,iBAAiB;","names":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { IAnalyticsQuery, AnalyticsQueryOpts, ResultRow } from './analytics-query.protocol.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CubeAnalyticsBackend — cube.js backend for the analytics query port.
|
|
6
|
+
*
|
|
7
|
+
* Connects to a running cube.js instance via @cubejs-client/core and
|
|
8
|
+
* translates IAnalyticsQuery calls into cube.js query objects.
|
|
9
|
+
*
|
|
10
|
+
* @cubejs-client/core is an optional peer dependency; lazy-imported so
|
|
11
|
+
* the module loads even if the package isn't installed. Consumers who
|
|
12
|
+
* use the cube backend must install it separately:
|
|
13
|
+
* bun add @cubejs-client/core
|
|
14
|
+
*
|
|
15
|
+
* Provided by AnalyticsModule.forRoot({ backend: 'cube' }).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
declare class CubeAnalyticsBackend implements IAnalyticsQuery, OnModuleInit {
|
|
19
|
+
private readonly apiUrl;
|
|
20
|
+
private readonly apiSecret;
|
|
21
|
+
private readonly logger;
|
|
22
|
+
private cubejsApi;
|
|
23
|
+
constructor(apiUrl: string, apiSecret: string);
|
|
24
|
+
onModuleInit(): Promise<void>;
|
|
25
|
+
execute(cube: string, measures: string[], dimensions: string[], where?: Record<string, any>, opts?: AnalyticsQueryOpts): Promise<ResultRow[]>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { CubeAnalyticsBackend };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
12
|
+
|
|
13
|
+
// runtime/subsystems/analytics/cube-backend.ts
|
|
14
|
+
import { Inject, Injectable, Logger } from "@nestjs/common";
|
|
15
|
+
|
|
16
|
+
// runtime/subsystems/analytics/analytics.tokens.ts
|
|
17
|
+
var CUBE_API_URL = /* @__PURE__ */ Symbol("CUBE_API_URL");
|
|
18
|
+
var CUBE_API_SECRET = /* @__PURE__ */ Symbol("CUBE_API_SECRET");
|
|
19
|
+
|
|
20
|
+
// runtime/subsystems/analytics/cube-backend.ts
|
|
21
|
+
var CubeAnalyticsBackend = class {
|
|
22
|
+
constructor(apiUrl, apiSecret) {
|
|
23
|
+
this.apiUrl = apiUrl;
|
|
24
|
+
this.apiSecret = apiSecret;
|
|
25
|
+
}
|
|
26
|
+
apiUrl;
|
|
27
|
+
apiSecret;
|
|
28
|
+
logger = new Logger(CubeAnalyticsBackend.name);
|
|
29
|
+
cubejsApi;
|
|
30
|
+
async onModuleInit() {
|
|
31
|
+
try {
|
|
32
|
+
const { default: cubejs } = await import("@cubejs-client/core");
|
|
33
|
+
this.cubejsApi = cubejs(this.apiSecret, { apiUrl: this.apiUrl });
|
|
34
|
+
} catch {
|
|
35
|
+
throw new Error(
|
|
36
|
+
"CubeAnalyticsBackend requires @cubejs-client/core. Install it: bun add @cubejs-client/core"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async execute(cube, measures, dimensions, where, opts) {
|
|
41
|
+
if (!this.cubejsApi) {
|
|
42
|
+
this.logger.warn("Cube.js client not initialized \u2014 returning empty result");
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const query = {
|
|
46
|
+
measures: measures.map((m) => cube + "." + m),
|
|
47
|
+
dimensions: dimensions.map((d) => cube + "." + d)
|
|
48
|
+
};
|
|
49
|
+
if (where && Object.keys(where).length > 0) {
|
|
50
|
+
query.filters = Object.entries(where).map(([member, value]) => ({
|
|
51
|
+
member: cube + "." + member,
|
|
52
|
+
operator: "equals",
|
|
53
|
+
values: Array.isArray(value) ? value : [String(value)]
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
if (opts?.limit) {
|
|
57
|
+
query.limit = opts.limit;
|
|
58
|
+
}
|
|
59
|
+
const resultSet = await this.cubejsApi.load(query);
|
|
60
|
+
return resultSet.tablePivot();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
CubeAnalyticsBackend = __decorateClass([
|
|
64
|
+
Injectable(),
|
|
65
|
+
__decorateParam(0, Inject(CUBE_API_URL)),
|
|
66
|
+
__decorateParam(1, Inject(CUBE_API_SECRET))
|
|
67
|
+
], CubeAnalyticsBackend);
|
|
68
|
+
export {
|
|
69
|
+
CubeAnalyticsBackend
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=cube-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../runtime/subsystems/analytics/cube-backend.ts","../../../../runtime/subsystems/analytics/analytics.tokens.ts"],"sourcesContent":["/**\n * CubeAnalyticsBackend — cube.js backend for the analytics query port.\n *\n * Connects to a running cube.js instance via @cubejs-client/core and\n * translates IAnalyticsQuery calls into cube.js query objects.\n *\n * @cubejs-client/core is an optional peer dependency; lazy-imported so\n * the module loads even if the package isn't installed. Consumers who\n * use the cube backend must install it separately:\n * bun add @cubejs-client/core\n *\n * Provided by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nimport { Inject, Injectable, OnModuleInit, Logger } from '@nestjs/common';\nimport { CUBE_API_URL, CUBE_API_SECRET } from './analytics.tokens';\nimport type {\n AnalyticsQueryOpts,\n IAnalyticsQuery,\n ResultRow,\n} from './analytics-query.protocol';\n\n@Injectable()\nexport class CubeAnalyticsBackend implements IAnalyticsQuery, OnModuleInit {\n private readonly logger = new Logger(CubeAnalyticsBackend.name);\n private cubejsApi: any;\n\n constructor(\n @Inject(CUBE_API_URL) private readonly apiUrl: string,\n @Inject(CUBE_API_SECRET) private readonly apiSecret: string,\n ) {}\n\n async onModuleInit(): Promise<void> {\n try {\n const { default: cubejs } = await import('@cubejs-client/core');\n this.cubejsApi = cubejs(this.apiSecret, { apiUrl: this.apiUrl });\n } catch {\n throw new Error(\n 'CubeAnalyticsBackend requires @cubejs-client/core. Install it: bun add @cubejs-client/core',\n );\n }\n }\n\n async execute(\n cube: string,\n measures: string[],\n dimensions: string[],\n where?: Record<string, any>,\n opts?: AnalyticsQueryOpts,\n ): Promise<ResultRow[]> {\n if (!this.cubejsApi) {\n this.logger.warn('Cube.js client not initialized — returning empty result');\n return [];\n }\n\n const query: Record<string, any> = {\n measures: measures.map((m) => cube + '.' + m),\n dimensions: dimensions.map((d) => cube + '.' + d),\n };\n\n if (where && Object.keys(where).length > 0) {\n query.filters = Object.entries(where).map(([member, value]) => ({\n member: cube + '.' + member,\n operator: 'equals',\n values: Array.isArray(value) ? value : [String(value)],\n }));\n }\n\n if (opts?.limit) {\n query.limit = opts.limit;\n }\n\n const resultSet = await this.cubejsApi.load(query);\n return resultSet.tablePivot() as ResultRow[];\n }\n}\n","/**\n * Injection tokens for the analytics subsystem.\n *\n * String constants (not Symbols) so they match by value across import\n * boundaries — same convention as events.tokens.ts.\n *\n * Usage in services:\n * ```typescript\n * constructor(@Inject(ANALYTICS_QUERY) private readonly analytics: IAnalyticsQuery) {}\n * ```\n */\nexport const ANALYTICS_QUERY = 'ANALYTICS_QUERY' as const;\n\n/**\n * Injection token for the cube.js API URL.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_URL = Symbol('CUBE_API_URL');\n\n/**\n * Injection token for the cube.js API secret.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_SECRET = Symbol('CUBE_API_SECRET');\n"],"mappings":";;;;;;;;;;;;;AAaA,SAAS,QAAQ,YAA0B,cAAc;;;ACIlD,IAAM,eAAe,uBAAO,cAAc;AAM1C,IAAM,kBAAkB,uBAAO,iBAAiB;;;ADDhD,IAAM,uBAAN,MAAoE;AAAA,EAIzE,YACyC,QACG,WAC1C;AAFuC;AACG;AAAA,EACzC;AAAA,EAFsC;AAAA,EACG;AAAA,EAL3B,SAAS,IAAI,OAAO,qBAAqB,IAAI;AAAA,EACtD;AAAA,EAOR,MAAM,eAA8B;AAClC,QAAI;AACF,YAAM,EAAE,SAAS,OAAO,IAAI,MAAM,OAAO,qBAAqB;AAC9D,WAAK,YAAY,OAAO,KAAK,WAAW,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QACJ,MACA,UACA,YACA,OACA,MACsB;AACtB,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,OAAO,KAAK,8DAAyD;AAC1E,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,QAA6B;AAAA,MACjC,UAAU,SAAS,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC;AAAA,MAC5C,YAAY,WAAW,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC;AAAA,IAClD;AAEA,QAAI,SAAS,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AAC1C,YAAM,UAAU,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;AAAA,QAC9D,QAAQ,OAAO,MAAM;AAAA,QACrB,UAAU;AAAA,QACV,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC;AAAA,MACvD,EAAE;AAAA,IACJ;AAEA,QAAI,MAAM,OAAO;AACf,YAAM,QAAQ,KAAK;AAAA,IACrB;AAEA,UAAM,YAAY,MAAM,KAAK,UAAU,KAAK,KAAK;AACjD,WAAO,UAAU,WAAW;AAAA,EAC9B;AACF;AApDa,uBAAN;AAAA,EADN,WAAW;AAAA,EAMP,0BAAO,YAAY;AAAA,EACnB,0BAAO,eAAe;AAAA,GANd;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AnalyticsQueryOpts, IAnalyticsQuery, ResultRow } from './analytics-query.protocol.js';
|
|
2
|
+
export { ANALYTICS_QUERY, CUBE_API_SECRET, CUBE_API_URL } from './analytics.tokens.js';
|
|
3
|
+
export { AnalyticsModule, AnalyticsModuleOptions } from './analytics.module.js';
|
|
4
|
+
export { CubeAnalyticsBackend } from './cube-backend.js';
|
|
5
|
+
export { NoopAnalyticsBackend } from './noop-backend.js';
|
|
6
|
+
import '@nestjs/common';
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
12
|
+
|
|
13
|
+
// runtime/subsystems/analytics/analytics.tokens.ts
|
|
14
|
+
var ANALYTICS_QUERY = "ANALYTICS_QUERY";
|
|
15
|
+
var CUBE_API_URL = /* @__PURE__ */ Symbol("CUBE_API_URL");
|
|
16
|
+
var CUBE_API_SECRET = /* @__PURE__ */ Symbol("CUBE_API_SECRET");
|
|
17
|
+
|
|
18
|
+
// runtime/subsystems/analytics/analytics.module.ts
|
|
19
|
+
import { Module } from "@nestjs/common";
|
|
20
|
+
|
|
21
|
+
// runtime/subsystems/analytics/cube-backend.ts
|
|
22
|
+
import { Inject, Injectable, Logger } from "@nestjs/common";
|
|
23
|
+
var CubeAnalyticsBackend = class {
|
|
24
|
+
constructor(apiUrl, apiSecret) {
|
|
25
|
+
this.apiUrl = apiUrl;
|
|
26
|
+
this.apiSecret = apiSecret;
|
|
27
|
+
}
|
|
28
|
+
apiUrl;
|
|
29
|
+
apiSecret;
|
|
30
|
+
logger = new Logger(CubeAnalyticsBackend.name);
|
|
31
|
+
cubejsApi;
|
|
32
|
+
async onModuleInit() {
|
|
33
|
+
try {
|
|
34
|
+
const { default: cubejs } = await import("@cubejs-client/core");
|
|
35
|
+
this.cubejsApi = cubejs(this.apiSecret, { apiUrl: this.apiUrl });
|
|
36
|
+
} catch {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"CubeAnalyticsBackend requires @cubejs-client/core. Install it: bun add @cubejs-client/core"
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async execute(cube, measures, dimensions, where, opts) {
|
|
43
|
+
if (!this.cubejsApi) {
|
|
44
|
+
this.logger.warn("Cube.js client not initialized \u2014 returning empty result");
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
const query = {
|
|
48
|
+
measures: measures.map((m) => cube + "." + m),
|
|
49
|
+
dimensions: dimensions.map((d) => cube + "." + d)
|
|
50
|
+
};
|
|
51
|
+
if (where && Object.keys(where).length > 0) {
|
|
52
|
+
query.filters = Object.entries(where).map(([member, value]) => ({
|
|
53
|
+
member: cube + "." + member,
|
|
54
|
+
operator: "equals",
|
|
55
|
+
values: Array.isArray(value) ? value : [String(value)]
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
if (opts?.limit) {
|
|
59
|
+
query.limit = opts.limit;
|
|
60
|
+
}
|
|
61
|
+
const resultSet = await this.cubejsApi.load(query);
|
|
62
|
+
return resultSet.tablePivot();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
CubeAnalyticsBackend = __decorateClass([
|
|
66
|
+
Injectable(),
|
|
67
|
+
__decorateParam(0, Inject(CUBE_API_URL)),
|
|
68
|
+
__decorateParam(1, Inject(CUBE_API_SECRET))
|
|
69
|
+
], CubeAnalyticsBackend);
|
|
70
|
+
|
|
71
|
+
// runtime/subsystems/analytics/noop-backend.ts
|
|
72
|
+
import { Injectable as Injectable2 } from "@nestjs/common";
|
|
73
|
+
var NoopAnalyticsBackend = class {
|
|
74
|
+
async execute(_cube, _measures, _dimensions, _where, _opts) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
NoopAnalyticsBackend = __decorateClass([
|
|
79
|
+
Injectable2()
|
|
80
|
+
], NoopAnalyticsBackend);
|
|
81
|
+
|
|
82
|
+
// runtime/subsystems/analytics/analytics.module.ts
|
|
83
|
+
var AnalyticsModule = class {
|
|
84
|
+
static forRoot(options = { backend: "noop" }) {
|
|
85
|
+
if (options.backend === "cube") {
|
|
86
|
+
return {
|
|
87
|
+
module: AnalyticsModule,
|
|
88
|
+
global: true,
|
|
89
|
+
providers: [
|
|
90
|
+
{
|
|
91
|
+
provide: CUBE_API_URL,
|
|
92
|
+
useValue: process.env["CUBE_API_URL"] ?? "http://localhost:4000/cubejs-api/v1"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
provide: CUBE_API_SECRET,
|
|
96
|
+
useValue: process.env["CUBE_API_SECRET"] ?? ""
|
|
97
|
+
},
|
|
98
|
+
{ provide: ANALYTICS_QUERY, useClass: CubeAnalyticsBackend }
|
|
99
|
+
],
|
|
100
|
+
exports: [ANALYTICS_QUERY]
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
module: AnalyticsModule,
|
|
105
|
+
global: true,
|
|
106
|
+
providers: [{ provide: ANALYTICS_QUERY, useClass: NoopAnalyticsBackend }],
|
|
107
|
+
exports: [ANALYTICS_QUERY]
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
AnalyticsModule = __decorateClass([
|
|
112
|
+
Module({})
|
|
113
|
+
], AnalyticsModule);
|
|
114
|
+
export {
|
|
115
|
+
ANALYTICS_QUERY,
|
|
116
|
+
AnalyticsModule,
|
|
117
|
+
CUBE_API_SECRET,
|
|
118
|
+
CUBE_API_URL,
|
|
119
|
+
CubeAnalyticsBackend,
|
|
120
|
+
NoopAnalyticsBackend
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../runtime/subsystems/analytics/analytics.tokens.ts","../../../../runtime/subsystems/analytics/analytics.module.ts","../../../../runtime/subsystems/analytics/cube-backend.ts","../../../../runtime/subsystems/analytics/noop-backend.ts"],"sourcesContent":["/**\n * Injection tokens for the analytics subsystem.\n *\n * String constants (not Symbols) so they match by value across import\n * boundaries — same convention as events.tokens.ts.\n *\n * Usage in services:\n * ```typescript\n * constructor(@Inject(ANALYTICS_QUERY) private readonly analytics: IAnalyticsQuery) {}\n * ```\n */\nexport const ANALYTICS_QUERY = 'ANALYTICS_QUERY' as const;\n\n/**\n * Injection token for the cube.js API URL.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_URL = Symbol('CUBE_API_URL');\n\n/**\n * Injection token for the cube.js API secret.\n * Provided automatically by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nexport const CUBE_API_SECRET = Symbol('CUBE_API_SECRET');\n","/**\n * AnalyticsModule — DynamicModule factory for the analytics query subsystem.\n *\n * Register once in AppModule:\n * ```typescript\n * @Module({\n * imports: [\n * AnalyticsModule.forRoot({ backend: 'cube' }),\n * ],\n * })\n * export class AppModule {}\n * ```\n *\n * Tests swap to the noop backend without touching application code:\n * ```typescript\n * Test.createTestingModule({\n * imports: [AnalyticsModule.forRoot({ backend: 'noop' })],\n * });\n * ```\n *\n * `global: true` means entity modules do not need to import AnalyticsModule\n * individually — the ANALYTICS_QUERY token is available project-wide.\n */\nimport { Module, type DynamicModule } from '@nestjs/common';\nimport { ANALYTICS_QUERY, CUBE_API_URL, CUBE_API_SECRET } from './analytics.tokens';\nimport { CubeAnalyticsBackend } from './cube-backend';\nimport { NoopAnalyticsBackend } from './noop-backend';\n\nexport interface AnalyticsModuleOptions {\n backend: 'cube' | 'noop';\n}\n\n@Module({})\nexport class AnalyticsModule {\n static forRoot(\n options: AnalyticsModuleOptions = { backend: 'noop' },\n ): DynamicModule {\n if (options.backend === 'cube') {\n return {\n module: AnalyticsModule,\n global: true,\n providers: [\n {\n provide: CUBE_API_URL,\n useValue: process.env['CUBE_API_URL'] ?? 'http://localhost:4000/cubejs-api/v1',\n },\n {\n provide: CUBE_API_SECRET,\n useValue: process.env['CUBE_API_SECRET'] ?? '',\n },\n { provide: ANALYTICS_QUERY, useClass: CubeAnalyticsBackend },\n ],\n exports: [ANALYTICS_QUERY],\n };\n }\n\n return {\n module: AnalyticsModule,\n global: true,\n providers: [{ provide: ANALYTICS_QUERY, useClass: NoopAnalyticsBackend }],\n exports: [ANALYTICS_QUERY],\n };\n }\n}\n","/**\n * CubeAnalyticsBackend — cube.js backend for the analytics query port.\n *\n * Connects to a running cube.js instance via @cubejs-client/core and\n * translates IAnalyticsQuery calls into cube.js query objects.\n *\n * @cubejs-client/core is an optional peer dependency; lazy-imported so\n * the module loads even if the package isn't installed. Consumers who\n * use the cube backend must install it separately:\n * bun add @cubejs-client/core\n *\n * Provided by AnalyticsModule.forRoot({ backend: 'cube' }).\n */\nimport { Inject, Injectable, OnModuleInit, Logger } from '@nestjs/common';\nimport { CUBE_API_URL, CUBE_API_SECRET } from './analytics.tokens';\nimport type {\n AnalyticsQueryOpts,\n IAnalyticsQuery,\n ResultRow,\n} from './analytics-query.protocol';\n\n@Injectable()\nexport class CubeAnalyticsBackend implements IAnalyticsQuery, OnModuleInit {\n private readonly logger = new Logger(CubeAnalyticsBackend.name);\n private cubejsApi: any;\n\n constructor(\n @Inject(CUBE_API_URL) private readonly apiUrl: string,\n @Inject(CUBE_API_SECRET) private readonly apiSecret: string,\n ) {}\n\n async onModuleInit(): Promise<void> {\n try {\n const { default: cubejs } = await import('@cubejs-client/core');\n this.cubejsApi = cubejs(this.apiSecret, { apiUrl: this.apiUrl });\n } catch {\n throw new Error(\n 'CubeAnalyticsBackend requires @cubejs-client/core. Install it: bun add @cubejs-client/core',\n );\n }\n }\n\n async execute(\n cube: string,\n measures: string[],\n dimensions: string[],\n where?: Record<string, any>,\n opts?: AnalyticsQueryOpts,\n ): Promise<ResultRow[]> {\n if (!this.cubejsApi) {\n this.logger.warn('Cube.js client not initialized — returning empty result');\n return [];\n }\n\n const query: Record<string, any> = {\n measures: measures.map((m) => cube + '.' + m),\n dimensions: dimensions.map((d) => cube + '.' + d),\n };\n\n if (where && Object.keys(where).length > 0) {\n query.filters = Object.entries(where).map(([member, value]) => ({\n member: cube + '.' + member,\n operator: 'equals',\n values: Array.isArray(value) ? value : [String(value)],\n }));\n }\n\n if (opts?.limit) {\n query.limit = opts.limit;\n }\n\n const resultSet = await this.cubejsApi.load(query);\n return resultSet.tablePivot() as ResultRow[];\n }\n}\n","/**\n * NoopAnalyticsBackend — no-op backend for the analytics query port.\n *\n * Returns empty arrays for all queries. Use this backend when analytics\n * is disabled or in tests that don't need real analytics data.\n *\n * Provided by AnalyticsModule.forRoot({ backend: 'noop' }).\n */\nimport { Injectable } from '@nestjs/common';\nimport type {\n AnalyticsQueryOpts,\n IAnalyticsQuery,\n ResultRow,\n} from './analytics-query.protocol';\n\n@Injectable()\nexport class NoopAnalyticsBackend implements IAnalyticsQuery {\n async execute(\n _cube: string,\n _measures: string[],\n _dimensions: string[],\n _where?: Record<string, any>,\n _opts?: AnalyticsQueryOpts,\n ): Promise<ResultRow[]> {\n return [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAWO,IAAM,kBAAkB;AAMxB,IAAM,eAAe,uBAAO,cAAc;AAM1C,IAAM,kBAAkB,uBAAO,iBAAiB;;;ACAvD,SAAS,cAAkC;;;ACV3C,SAAS,QAAQ,YAA0B,cAAc;AASlD,IAAM,uBAAN,MAAoE;AAAA,EAIzE,YACyC,QACG,WAC1C;AAFuC;AACG;AAAA,EACzC;AAAA,EAFsC;AAAA,EACG;AAAA,EAL3B,SAAS,IAAI,OAAO,qBAAqB,IAAI;AAAA,EACtD;AAAA,EAOR,MAAM,eAA8B;AAClC,QAAI;AACF,YAAM,EAAE,SAAS,OAAO,IAAI,MAAM,OAAO,qBAAqB;AAC9D,WAAK,YAAY,OAAO,KAAK,WAAW,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QACJ,MACA,UACA,YACA,OACA,MACsB;AACtB,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,OAAO,KAAK,8DAAyD;AAC1E,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,QAA6B;AAAA,MACjC,UAAU,SAAS,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC;AAAA,MAC5C,YAAY,WAAW,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC;AAAA,IAClD;AAEA,QAAI,SAAS,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AAC1C,YAAM,UAAU,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;AAAA,QAC9D,QAAQ,OAAO,MAAM;AAAA,QACrB,UAAU;AAAA,QACV,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC;AAAA,MACvD,EAAE;AAAA,IACJ;AAEA,QAAI,MAAM,OAAO;AACf,YAAM,QAAQ,KAAK;AAAA,IACrB;AAEA,UAAM,YAAY,MAAM,KAAK,UAAU,KAAK,KAAK;AACjD,WAAO,UAAU,WAAW;AAAA,EAC9B;AACF;AApDa,uBAAN;AAAA,EADN,WAAW;AAAA,EAMP,0BAAO,YAAY;AAAA,EACnB,0BAAO,eAAe;AAAA,GANd;;;ACdb,SAAS,cAAAA,mBAAkB;AAQpB,IAAM,uBAAN,MAAsD;AAAA,EAC3D,MAAM,QACJ,OACA,WACA,aACA,QACA,OACsB;AACtB,WAAO,CAAC;AAAA,EACV;AACF;AAVa,uBAAN;AAAA,EADNC,YAAW;AAAA,GACC;;;AFiBN,IAAM,kBAAN,MAAsB;AAAA,EAC3B,OAAO,QACL,UAAkC,EAAE,SAAS,OAAO,GACrC;AACf,QAAI,QAAQ,YAAY,QAAQ;AAC9B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,WAAW;AAAA,UACT;AAAA,YACE,SAAS;AAAA,YACT,UAAU,QAAQ,IAAI,cAAc,KAAK;AAAA,UAC3C;AAAA,UACA;AAAA,YACE,SAAS;AAAA,YACT,UAAU,QAAQ,IAAI,iBAAiB,KAAK;AAAA,UAC9C;AAAA,UACA,EAAE,SAAS,iBAAiB,UAAU,qBAAqB;AAAA,QAC7D;AAAA,QACA,SAAS,CAAC,eAAe;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW,CAAC,EAAE,SAAS,iBAAiB,UAAU,qBAAqB,CAAC;AAAA,MACxE,SAAS,CAAC,eAAe;AAAA,IAC3B;AAAA,EACF;AACF;AA9Ba,kBAAN;AAAA,EADN,OAAO,CAAC,CAAC;AAAA,GACG;","names":["Injectable","Injectable"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IAnalyticsQuery, AnalyticsQueryOpts, ResultRow } from './analytics-query.protocol.js';
|
|
2
|
+
|
|
3
|
+
declare class NoopAnalyticsBackend implements IAnalyticsQuery {
|
|
4
|
+
execute(_cube: string, _measures: string[], _dimensions: string[], _where?: Record<string, any>, _opts?: AnalyticsQueryOpts): Promise<ResultRow[]>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export { NoopAnalyticsBackend };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// runtime/subsystems/analytics/noop-backend.ts
|
|
13
|
+
import { Injectable } from "@nestjs/common";
|
|
14
|
+
var NoopAnalyticsBackend = class {
|
|
15
|
+
async execute(_cube, _measures, _dimensions, _where, _opts) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
NoopAnalyticsBackend = __decorateClass([
|
|
20
|
+
Injectable()
|
|
21
|
+
], NoopAnalyticsBackend);
|
|
22
|
+
export {
|
|
23
|
+
NoopAnalyticsBackend
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=noop-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../runtime/subsystems/analytics/noop-backend.ts"],"sourcesContent":["/**\n * NoopAnalyticsBackend — no-op backend for the analytics query port.\n *\n * Returns empty arrays for all queries. Use this backend when analytics\n * is disabled or in tests that don't need real analytics data.\n *\n * Provided by AnalyticsModule.forRoot({ backend: 'noop' }).\n */\nimport { Injectable } from '@nestjs/common';\nimport type {\n AnalyticsQueryOpts,\n IAnalyticsQuery,\n ResultRow,\n} from './analytics-query.protocol';\n\n@Injectable()\nexport class NoopAnalyticsBackend implements IAnalyticsQuery {\n async execute(\n _cube: string,\n _measures: string[],\n _dimensions: string[],\n _where?: Record<string, any>,\n _opts?: AnalyticsQueryOpts,\n ): Promise<ResultRow[]> {\n return [];\n }\n}\n"],"mappings":";;;;;;;;;;;;AAQA,SAAS,kBAAkB;AAQpB,IAAM,uBAAN,MAAsD;AAAA,EAC3D,MAAM,QACJ,OACA,WACA,aACA,QACA,OACsB;AACtB,WAAO,CAAC;AAAA,EACV;AACF;AAVa,uBAAN;AAAA,EADN,WAAW;AAAA,GACC;","names":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import { DrizzleClient } from '../../types/drizzle.js';
|
|
3
|
+
import { ICacheService } from './cache.protocol.js';
|
|
4
|
+
export { CACHE_DEFAULT_TTL } from './cache.tokens.js';
|
|
5
|
+
import 'drizzle-orm/node-postgres';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* DrizzleCacheService — Postgres-backed ICacheService via Drizzle ORM.
|
|
9
|
+
*
|
|
10
|
+
* Storage: `cache_entries` table with key (text pk), value (jsonb), expiresAt (timestamp).
|
|
11
|
+
* TTL enforcement: reads filter by `expiresAt > now() OR expiresAt IS NULL`.
|
|
12
|
+
* Prefix invalidation: `DELETE WHERE key LIKE 'escaped_prefix%'`.
|
|
13
|
+
*
|
|
14
|
+
* Lifecycle:
|
|
15
|
+
* - OnModuleInit: starts periodic cleanup of expired entries.
|
|
16
|
+
* Uses the Jobs subsystem if available (optional injection); falls back to setInterval.
|
|
17
|
+
* - OnModuleDestroy: clears the setInterval timer if used.
|
|
18
|
+
*
|
|
19
|
+
* Error behavior per ADR-008:
|
|
20
|
+
* - get() / has() return null/false on any error (never throw for reads).
|
|
21
|
+
* - set() / delete() / invalidateByPrefix() throw on failure.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
declare class DrizzleCacheService implements ICacheService, OnModuleInit, OnModuleDestroy {
|
|
25
|
+
private readonly db;
|
|
26
|
+
private readonly defaultTtl;
|
|
27
|
+
private cleanupTimer;
|
|
28
|
+
/** In-flight getOrSet promises — keyed by cache key to deduplicate stampedes. */
|
|
29
|
+
private readonly inflight;
|
|
30
|
+
constructor(db: DrizzleClient, defaultTtl?: number | null);
|
|
31
|
+
onModuleInit(): Promise<void>;
|
|
32
|
+
onModuleDestroy(): Promise<void>;
|
|
33
|
+
get<T = unknown>(key: string): Promise<T | null>;
|
|
34
|
+
set<T = unknown>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
35
|
+
delete(key: string): Promise<void>;
|
|
36
|
+
invalidateByPrefix(prefix: string): Promise<number>;
|
|
37
|
+
has(key: string): Promise<boolean>;
|
|
38
|
+
getOrSet<T = unknown>(key: string, factory: () => Promise<T>, ttlSeconds?: number): Promise<T>;
|
|
39
|
+
/** Remove all expired entries. Called by the cleanup timer. */
|
|
40
|
+
private deleteExpired;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { DrizzleCacheService };
|