nestjs-ddd-cli 2.2.1 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +247 -408
- package/ddd.schema.json +111 -0
- package/dist/commands/aggregate-validator.d.ts +9 -0
- package/dist/commands/aggregate-validator.js +953 -0
- package/dist/commands/aggregate-validator.js.map +1 -0
- package/dist/commands/ai-assist.d.ts +8 -0
- package/dist/commands/ai-assist.js +337 -0
- package/dist/commands/ai-assist.js.map +1 -0
- package/dist/commands/api-contracts.d.ts +9 -0
- package/dist/commands/api-contracts.js +1368 -0
- package/dist/commands/api-contracts.js.map +1 -0
- package/dist/commands/api-docs.d.ts +8 -0
- package/dist/commands/api-docs.js +408 -0
- package/dist/commands/api-docs.js.map +1 -0
- package/dist/commands/api-versioning.d.ts +11 -0
- package/dist/commands/api-versioning.js +643 -0
- package/dist/commands/api-versioning.js.map +1 -0
- package/dist/commands/audit-logging.d.ts +9 -0
- package/dist/commands/audit-logging.js +1129 -0
- package/dist/commands/audit-logging.js.map +1 -0
- package/dist/commands/batch-generate.d.ts +10 -0
- package/dist/commands/batch-generate.js +405 -0
- package/dist/commands/batch-generate.js.map +1 -0
- package/dist/commands/caching-strategies.d.ts +9 -0
- package/dist/commands/caching-strategies.js +874 -0
- package/dist/commands/caching-strategies.js.map +1 -0
- package/dist/commands/code-analyzer.d.ts +42 -0
- package/dist/commands/code-analyzer.js +474 -0
- package/dist/commands/code-analyzer.js.map +1 -0
- package/dist/commands/database-seeding.d.ts +6 -0
- package/dist/commands/database-seeding.js +621 -0
- package/dist/commands/database-seeding.js.map +1 -0
- package/dist/commands/db-optimization.d.ts +7 -0
- package/dist/commands/db-optimization.js +687 -0
- package/dist/commands/db-optimization.js.map +1 -0
- package/dist/commands/dependency-graph.d.ts +6 -0
- package/dist/commands/dependency-graph.js +329 -0
- package/dist/commands/dependency-graph.js.map +1 -0
- package/dist/commands/doctor-enhanced.d.ts +22 -0
- package/dist/commands/doctor-enhanced.js +543 -0
- package/dist/commands/doctor-enhanced.js.map +1 -0
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.js +151 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/env-manager.d.ts +6 -0
- package/dist/commands/env-manager.js +419 -0
- package/dist/commands/env-manager.js.map +1 -0
- package/dist/commands/event-sourcing-full.d.ts +10 -0
- package/dist/commands/event-sourcing-full.js +1107 -0
- package/dist/commands/event-sourcing-full.js.map +1 -0
- package/dist/commands/feature-flags.d.ts +9 -0
- package/dist/commands/feature-flags.js +824 -0
- package/dist/commands/feature-flags.js.map +1 -0
- package/dist/commands/filter-dsl.d.ts +10 -0
- package/dist/commands/filter-dsl.js +1407 -0
- package/dist/commands/filter-dsl.js.map +1 -0
- package/dist/commands/generate-all.js +485 -32
- package/dist/commands/generate-all.js.map +1 -1
- package/dist/commands/generate-deployment.d.ts +8 -0
- package/dist/commands/generate-deployment.js +746 -0
- package/dist/commands/generate-deployment.js.map +1 -0
- package/dist/commands/generate-domain-service.d.ts +14 -0
- package/dist/commands/generate-domain-service.js +796 -0
- package/dist/commands/generate-domain-service.js.map +1 -0
- package/dist/commands/generate-entity.js +82 -24
- package/dist/commands/generate-entity.js.map +1 -1
- package/dist/commands/generate-from-schema.d.ts +56 -0
- package/dist/commands/generate-from-schema.js +222 -0
- package/dist/commands/generate-from-schema.js.map +1 -0
- package/dist/commands/generate-orchestrator.d.ts +14 -0
- package/dist/commands/generate-orchestrator.js +887 -0
- package/dist/commands/generate-orchestrator.js.map +1 -0
- package/dist/commands/generate-repository.d.ts +14 -0
- package/dist/commands/generate-repository.js +1019 -0
- package/dist/commands/generate-repository.js.map +1 -0
- package/dist/commands/generate-shared.d.ts +4 -0
- package/dist/commands/generate-shared.js +388 -0
- package/dist/commands/generate-shared.js.map +1 -0
- package/dist/commands/generate-value-object.d.ts +32 -0
- package/dist/commands/generate-value-object.js +700 -0
- package/dist/commands/generate-value-object.js.map +1 -0
- package/dist/commands/graphql-subscriptions.d.ts +6 -0
- package/dist/commands/graphql-subscriptions.js +607 -0
- package/dist/commands/graphql-subscriptions.js.map +1 -0
- package/dist/commands/graphql-types.d.ts +5 -0
- package/dist/commands/graphql-types.js +423 -0
- package/dist/commands/graphql-types.js.map +1 -0
- package/dist/commands/health-probes-advanced.d.ts +6 -0
- package/dist/commands/health-probes-advanced.js +655 -0
- package/dist/commands/health-probes-advanced.js.map +1 -0
- package/dist/commands/i18n-setup.d.ts +10 -0
- package/dist/commands/i18n-setup.js +677 -0
- package/dist/commands/i18n-setup.js.map +1 -0
- package/dist/commands/init-config.d.ts +6 -0
- package/dist/commands/init-config.js +370 -0
- package/dist/commands/init-config.js.map +1 -0
- package/dist/commands/init-project.js +56 -6
- package/dist/commands/init-project.js.map +1 -1
- package/dist/commands/interactive-scaffold.d.ts +5 -0
- package/dist/commands/interactive-scaffold.js +271 -0
- package/dist/commands/interactive-scaffold.js.map +1 -0
- package/dist/commands/metrics-prometheus.d.ts +6 -0
- package/dist/commands/metrics-prometheus.js +681 -0
- package/dist/commands/metrics-prometheus.js.map +1 -0
- package/dist/commands/migration-engine.d.ts +6 -0
- package/dist/commands/migration-engine.js +446 -0
- package/dist/commands/migration-engine.js.map +1 -0
- package/dist/commands/migration.d.ts +12 -0
- package/dist/commands/migration.js +484 -0
- package/dist/commands/migration.js.map +1 -0
- package/dist/commands/monorepo.d.ts +8 -0
- package/dist/commands/monorepo.js +483 -0
- package/dist/commands/monorepo.js.map +1 -0
- package/dist/commands/multi-database.d.ts +5 -0
- package/dist/commands/multi-database.js +439 -0
- package/dist/commands/multi-database.js.map +1 -0
- package/dist/commands/observability-tracing.d.ts +10 -0
- package/dist/commands/observability-tracing.js +740 -0
- package/dist/commands/observability-tracing.js.map +1 -0
- package/dist/commands/openapi-export.d.ts +8 -0
- package/dist/commands/openapi-export.js +359 -0
- package/dist/commands/openapi-export.js.map +1 -0
- package/dist/commands/perf-analyzer.d.ts +8 -0
- package/dist/commands/perf-analyzer.js +423 -0
- package/dist/commands/perf-analyzer.js.map +1 -0
- package/dist/commands/rate-limiting.d.ts +10 -0
- package/dist/commands/rate-limiting.js +953 -0
- package/dist/commands/rate-limiting.js.map +1 -0
- package/dist/commands/recipe-plugin.d.ts +56 -0
- package/dist/commands/recipe-plugin.js +315 -0
- package/dist/commands/recipe-plugin.js.map +1 -0
- package/dist/commands/recipe.d.ts +6 -0
- package/dist/commands/recipe.js +3941 -0
- package/dist/commands/recipe.js.map +1 -0
- package/dist/commands/recipes/elasticsearch.recipe.d.ts +1 -0
- package/dist/commands/recipes/elasticsearch.recipe.js +761 -0
- package/dist/commands/recipes/elasticsearch.recipe.js.map +1 -0
- package/dist/commands/recipes/event-sourcing.recipe.d.ts +1 -0
- package/dist/commands/recipes/event-sourcing.recipe.js +889 -0
- package/dist/commands/recipes/event-sourcing.recipe.js.map +1 -0
- package/dist/commands/recipes/index.d.ts +7 -0
- package/dist/commands/recipes/index.js +24 -0
- package/dist/commands/recipes/index.js.map +1 -0
- package/dist/commands/recipes/message-queue.recipe.d.ts +1 -0
- package/dist/commands/recipes/message-queue.recipe.js +706 -0
- package/dist/commands/recipes/message-queue.recipe.js.map +1 -0
- package/dist/commands/recipes/middleware.recipe.d.ts +1 -0
- package/dist/commands/recipes/middleware.recipe.js +383 -0
- package/dist/commands/recipes/middleware.recipe.js.map +1 -0
- package/dist/commands/recipes/multi-tenancy.recipe.d.ts +1 -0
- package/dist/commands/recipes/multi-tenancy.recipe.js +520 -0
- package/dist/commands/recipes/multi-tenancy.recipe.js.map +1 -0
- package/dist/commands/recipes/oauth2.recipe.d.ts +1 -0
- package/dist/commands/recipes/oauth2.recipe.js +472 -0
- package/dist/commands/recipes/oauth2.recipe.js.map +1 -0
- package/dist/commands/recipes/websocket.recipe.d.ts +1 -0
- package/dist/commands/recipes/websocket.recipe.js +453 -0
- package/dist/commands/recipes/websocket.recipe.js.map +1 -0
- package/dist/commands/resilience-patterns.d.ts +13 -0
- package/dist/commands/resilience-patterns.js +1029 -0
- package/dist/commands/resilience-patterns.js.map +1 -0
- package/dist/commands/security-patterns.d.ts +11 -0
- package/dist/commands/security-patterns.js +2233 -0
- package/dist/commands/security-patterns.js.map +1 -0
- package/dist/commands/template-debug.d.ts +27 -0
- package/dist/commands/template-debug.js +388 -0
- package/dist/commands/template-debug.js.map +1 -0
- package/dist/commands/test-factory-full.d.ts +9 -0
- package/dist/commands/test-factory-full.js +1570 -0
- package/dist/commands/test-factory-full.js.map +1 -0
- package/dist/commands/test-scaffold.d.ts +7 -0
- package/dist/commands/test-scaffold.js +621 -0
- package/dist/commands/test-scaffold.js.map +1 -0
- package/dist/index.js +1088 -0
- package/dist/index.js.map +1 -1
- package/dist/templates/ai-context/CLAUDE.md.hbs +158 -0
- package/dist/templates/ai-context/conventions.md.hbs +154 -0
- package/dist/templates/command/create-command.hbs +6 -14
- package/dist/templates/command/delete-command.hbs +19 -0
- package/dist/templates/command/update-command.hbs +24 -0
- package/dist/templates/controller/controller.hbs +64 -17
- package/dist/templates/dto/create-dto.hbs +29 -5
- package/dist/templates/dto/filter-dto.hbs +52 -0
- package/dist/templates/dto/filter-query.dto.hbs +148 -0
- package/dist/templates/dto/paginated-response.dto.hbs +29 -0
- package/dist/templates/dto/pagination-query.dto.hbs +30 -0
- package/dist/templates/dto/response-dto.hbs +38 -0
- package/dist/templates/dto/update-dto.hbs +11 -0
- package/dist/templates/entity/entity.hbs +32 -1
- package/dist/templates/event/domain-event.hbs +33 -7
- package/dist/templates/event/event-handler.hbs +40 -0
- package/dist/templates/exception/base-exceptions.hbs +69 -0
- package/dist/templates/exception/entity-not-found.exception.hbs +7 -0
- package/dist/templates/mapper/mapper.hbs +49 -24
- package/dist/templates/module/module.hbs +34 -10
- package/dist/templates/orm-entity/orm-entity.hbs +63 -12
- package/dist/templates/prisma/prisma-mapper.hbs +71 -0
- package/dist/templates/prisma/prisma-repository.hbs +114 -0
- package/dist/templates/prisma/prisma-schema.hbs +20 -0
- package/dist/templates/prisma/prisma-service.hbs +51 -0
- package/dist/templates/query/get-all.query.hbs +50 -0
- package/dist/templates/query/get-by-id.query.hbs +31 -0
- package/dist/templates/repository/repository.hbs +55 -13
- package/dist/templates/resolver/graphql-input.hbs +54 -0
- package/dist/templates/resolver/graphql-type.hbs +58 -0
- package/dist/templates/resolver/pagination-args.hbs +33 -0
- package/dist/templates/resolver/resolver.hbs +62 -0
- package/dist/templates/shared/prisma-query-builder.util.hbs +189 -0
- package/dist/templates/shared/query-builder.util.hbs +218 -0
- package/dist/templates/test/controller.spec.hbs +124 -0
- package/dist/templates/test/repository.spec.hbs +158 -0
- package/dist/templates/test/usecase.spec.hbs +116 -0
- package/dist/templates/usecase/create-usecase.hbs +19 -7
- package/dist/templates/usecase/delete-usecase.hbs +17 -0
- package/dist/templates/usecase/update-usecase.hbs +31 -0
- package/dist/utils/config.utils.d.ts +45 -0
- package/dist/utils/config.utils.js +211 -0
- package/dist/utils/config.utils.js.map +1 -0
- package/dist/utils/error.utils.d.ts +145 -0
- package/dist/utils/error.utils.js +422 -0
- package/dist/utils/error.utils.js.map +1 -0
- package/dist/utils/field.utils.d.ts +54 -0
- package/dist/utils/field.utils.js +389 -0
- package/dist/utils/field.utils.js.map +1 -0
- package/dist/utils/file.utils.d.ts +19 -8
- package/dist/utils/file.utils.js +135 -4
- package/dist/utils/file.utils.js.map +1 -1
- package/dist/utils/idempotency.utils.d.ts +123 -0
- package/dist/utils/idempotency.utils.js +444 -0
- package/dist/utils/idempotency.utils.js.map +1 -0
- package/dist/utils/naming.utils.js +24 -5
- package/dist/utils/naming.utils.js.map +1 -1
- package/dist/utils/performance.utils.d.ts +37 -0
- package/dist/utils/performance.utils.js +158 -0
- package/dist/utils/performance.utils.js.map +1 -0
- package/dist/utils/relation.utils.d.ts +92 -0
- package/dist/utils/relation.utils.js +388 -0
- package/dist/utils/relation.utils.js.map +1 -0
- package/dist/utils/rollback.utils.d.ts +49 -0
- package/dist/utils/rollback.utils.js +306 -0
- package/dist/utils/rollback.utils.js.map +1 -0
- package/dist/utils/schema.utils.d.ts +123 -0
- package/dist/utils/schema.utils.js +419 -0
- package/dist/utils/schema.utils.js.map +1 -0
- package/dist/utils/security.utils.d.ts +57 -0
- package/dist/utils/security.utils.js +315 -0
- package/dist/utils/security.utils.js.map +1 -0
- package/dist/utils/template-engine.utils.d.ts +80 -0
- package/dist/utils/template-engine.utils.js +463 -0
- package/dist/utils/template-engine.utils.js.map +1 -0
- package/dist/utils/validation-registry.utils.d.ts +160 -0
- package/dist/utils/validation-registry.utils.js +526 -0
- package/dist/utils/validation-registry.utils.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.setupGraphQLSubscriptions = setupGraphQLSubscriptions;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const naming_utils_1 = require("../utils/naming.utils");
|
|
44
|
+
async function setupGraphQLSubscriptions(basePath, options = {}) {
|
|
45
|
+
console.log(chalk_1.default.bold.blue('\n📡 Setting up GraphQL Subscriptions\n'));
|
|
46
|
+
const moduleName = options.module || 'shared';
|
|
47
|
+
const pascalName = (0, naming_utils_1.toPascalCase)(moduleName);
|
|
48
|
+
const camelName = (0, naming_utils_1.toCamelCase)(moduleName);
|
|
49
|
+
const kebabName = (0, naming_utils_1.toKebabCase)(moduleName);
|
|
50
|
+
const events = options.events || ['created', 'updated', 'deleted'];
|
|
51
|
+
const useRedis = options.useRedis !== false;
|
|
52
|
+
const baseDir = path.join(basePath, 'src', kebabName, 'infrastructure', 'graphql');
|
|
53
|
+
fs.mkdirSync(baseDir, { recursive: true });
|
|
54
|
+
// PubSub service
|
|
55
|
+
const pubSubContent = `import { Injectable, OnModuleDestroy } from '@nestjs/common';
|
|
56
|
+
import { PubSub } from 'graphql-subscriptions';
|
|
57
|
+
${useRedis ? "import { RedisPubSub } from 'graphql-redis-subscriptions';\nimport Redis from 'ioredis';" : ''}
|
|
58
|
+
|
|
59
|
+
export type SubscriptionPayload<T> = {
|
|
60
|
+
data: T;
|
|
61
|
+
metadata: {
|
|
62
|
+
timestamp: Date;
|
|
63
|
+
correlationId?: string;
|
|
64
|
+
userId?: string;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* PubSub service for GraphQL subscriptions
|
|
70
|
+
* ${useRedis ? 'Uses Redis for distributed pub/sub' : 'Uses in-memory pub/sub (single instance only)'}
|
|
71
|
+
*/
|
|
72
|
+
@Injectable()
|
|
73
|
+
export class PubSubService implements OnModuleDestroy {
|
|
74
|
+
private readonly pubSub: PubSub${useRedis ? ' | RedisPubSub' : ''};
|
|
75
|
+
${useRedis ? ` private readonly redisPublisher?: Redis;
|
|
76
|
+
private readonly redisSubscriber?: Redis;` : ''}
|
|
77
|
+
|
|
78
|
+
constructor() {
|
|
79
|
+
${useRedis ? ` const redisOptions = {
|
|
80
|
+
host: process.env.REDIS_HOST || 'localhost',
|
|
81
|
+
port: parseInt(process.env.REDIS_PORT || '6379', 10),
|
|
82
|
+
password: process.env.REDIS_PASSWORD,
|
|
83
|
+
retryStrategy: (times: number) => Math.min(times * 50, 2000),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
if (process.env.USE_REDIS_PUBSUB === 'true') {
|
|
87
|
+
this.redisPublisher = new Redis(redisOptions);
|
|
88
|
+
this.redisSubscriber = new Redis(redisOptions);
|
|
89
|
+
|
|
90
|
+
this.pubSub = new RedisPubSub({
|
|
91
|
+
publisher: this.redisPublisher,
|
|
92
|
+
subscriber: this.redisSubscriber,
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
this.pubSub = new PubSub();
|
|
96
|
+
}` : ' this.pubSub = new PubSub();'}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async onModuleDestroy(): Promise<void> {
|
|
100
|
+
${useRedis ? ` if (this.redisPublisher) {
|
|
101
|
+
await this.redisPublisher.quit();
|
|
102
|
+
}
|
|
103
|
+
if (this.redisSubscriber) {
|
|
104
|
+
await this.redisSubscriber.quit();
|
|
105
|
+
}` : ' // In-memory PubSub doesn\'t need cleanup'}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Publish an event
|
|
110
|
+
*/
|
|
111
|
+
async publish<T>(trigger: string, payload: SubscriptionPayload<T>): Promise<void> {
|
|
112
|
+
await this.pubSub.publish(trigger, {
|
|
113
|
+
[trigger]: payload,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Subscribe to an event
|
|
119
|
+
*/
|
|
120
|
+
asyncIterator<T>(triggers: string | string[]): AsyncIterator<T> {
|
|
121
|
+
return this.pubSub.asyncIterator(triggers);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Create a filtered subscription
|
|
126
|
+
*/
|
|
127
|
+
asyncIteratorWithFilter<T>(
|
|
128
|
+
triggers: string | string[],
|
|
129
|
+
filterFn: (payload: T, variables: any, context: any) => boolean | Promise<boolean>,
|
|
130
|
+
): AsyncIterator<T> {
|
|
131
|
+
const asyncIterator = this.pubSub.asyncIterator<T>(triggers);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
...asyncIterator,
|
|
135
|
+
next: async () => {
|
|
136
|
+
while (true) {
|
|
137
|
+
const result = await asyncIterator.next();
|
|
138
|
+
if (result.done) {
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
// Filter logic would be applied by resolver
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
`;
|
|
149
|
+
fs.writeFileSync(path.join(baseDir, 'pubsub.service.ts'), pubSubContent);
|
|
150
|
+
// Subscription events
|
|
151
|
+
const subscriptionEventsContent = `/**
|
|
152
|
+
* Subscription event triggers for ${pascalName}
|
|
153
|
+
*/
|
|
154
|
+
export const ${pascalName}SubscriptionEvents = {
|
|
155
|
+
${events.map(event => ` ${event.toUpperCase()}: '${camelName}${(0, naming_utils_1.toPascalCase)(event)}',`).join('\n')}
|
|
156
|
+
} as const;
|
|
157
|
+
|
|
158
|
+
export type ${pascalName}SubscriptionEvent = typeof ${pascalName}SubscriptionEvents[keyof typeof ${pascalName}SubscriptionEvents];
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Subscription payload types
|
|
162
|
+
*/
|
|
163
|
+
export interface ${pascalName}CreatedPayload {
|
|
164
|
+
${camelName}Created: {
|
|
165
|
+
data: {
|
|
166
|
+
id: string;
|
|
167
|
+
// Add your entity fields here
|
|
168
|
+
};
|
|
169
|
+
metadata: {
|
|
170
|
+
timestamp: Date;
|
|
171
|
+
correlationId?: string;
|
|
172
|
+
userId?: string;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface ${pascalName}UpdatedPayload {
|
|
178
|
+
${camelName}Updated: {
|
|
179
|
+
data: {
|
|
180
|
+
id: string;
|
|
181
|
+
changes: Record<string, { old: any; new: any }>;
|
|
182
|
+
};
|
|
183
|
+
metadata: {
|
|
184
|
+
timestamp: Date;
|
|
185
|
+
correlationId?: string;
|
|
186
|
+
userId?: string;
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface ${pascalName}DeletedPayload {
|
|
192
|
+
${camelName}Deleted: {
|
|
193
|
+
data: {
|
|
194
|
+
id: string;
|
|
195
|
+
};
|
|
196
|
+
metadata: {
|
|
197
|
+
timestamp: Date;
|
|
198
|
+
correlationId?: string;
|
|
199
|
+
userId?: string;
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
204
|
+
fs.writeFileSync(path.join(baseDir, 'subscription-events.ts'), subscriptionEventsContent);
|
|
205
|
+
// Subscription resolver
|
|
206
|
+
const subscriptionResolverContent = `import { Resolver, Subscription, Args, Context } from '@nestjs/graphql';
|
|
207
|
+
import { UseGuards } from '@nestjs/common';
|
|
208
|
+
import { PubSubService } from './pubsub.service';
|
|
209
|
+
import { ${pascalName}SubscriptionEvents } from './subscription-events';
|
|
210
|
+
|
|
211
|
+
// Uncomment and import your GraphQL types
|
|
212
|
+
// import { ${pascalName} } from '../types/${kebabName}.type';
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* GraphQL subscription resolver for ${pascalName}
|
|
216
|
+
*/
|
|
217
|
+
@Resolver()
|
|
218
|
+
export class ${pascalName}SubscriptionResolver {
|
|
219
|
+
constructor(private readonly pubSubService: PubSubService) {}
|
|
220
|
+
|
|
221
|
+
${events.map(event => {
|
|
222
|
+
const eventName = `${camelName}${(0, naming_utils_1.toPascalCase)(event)}`;
|
|
223
|
+
const payloadType = `${pascalName}${(0, naming_utils_1.toPascalCase)(event)}Payload`;
|
|
224
|
+
return `
|
|
225
|
+
/**
|
|
226
|
+
* Subscribe to ${event} events
|
|
227
|
+
*/
|
|
228
|
+
@Subscription(() => Object, { // Replace Object with your GraphQL type
|
|
229
|
+
name: '${eventName}',
|
|
230
|
+
description: 'Subscribe to ${pascalName} ${event} events',
|
|
231
|
+
filter: (payload, variables, context) => {
|
|
232
|
+
// Add custom filtering logic here
|
|
233
|
+
// Example: filter by ID
|
|
234
|
+
if (variables.id && payload.${eventName}.data.id !== variables.id) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
238
|
+
},
|
|
239
|
+
resolve: (payload) => payload.${eventName},
|
|
240
|
+
})
|
|
241
|
+
// @UseGuards(GqlAuthGuard) // Uncomment to require authentication
|
|
242
|
+
${eventName}(
|
|
243
|
+
@Args('id', { nullable: true }) id?: string,
|
|
244
|
+
@Context() context?: any,
|
|
245
|
+
): AsyncIterator<any> {
|
|
246
|
+
return this.pubSubService.asyncIterator(${pascalName}SubscriptionEvents.${event.toUpperCase()});
|
|
247
|
+
}`;
|
|
248
|
+
}).join('\n')}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Subscribe to all ${pascalName} events
|
|
252
|
+
*/
|
|
253
|
+
@Subscription(() => Object, {
|
|
254
|
+
name: '${camelName}Events',
|
|
255
|
+
description: 'Subscribe to all ${pascalName} events',
|
|
256
|
+
resolve: (payload) => {
|
|
257
|
+
// Return the payload with event type
|
|
258
|
+
const eventType = Object.keys(payload)[0];
|
|
259
|
+
return {
|
|
260
|
+
type: eventType,
|
|
261
|
+
...payload[eventType],
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
})
|
|
265
|
+
${camelName}Events(): AsyncIterator<any> {
|
|
266
|
+
return this.pubSubService.asyncIterator(
|
|
267
|
+
Object.values(${pascalName}SubscriptionEvents),
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
fs.writeFileSync(path.join(baseDir, `${kebabName}-subscription.resolver.ts`), subscriptionResolverContent);
|
|
273
|
+
// Event publisher service
|
|
274
|
+
const eventPublisherContent = `import { Injectable, Logger } from '@nestjs/common';
|
|
275
|
+
import { PubSubService, SubscriptionPayload } from './pubsub.service';
|
|
276
|
+
import { ${pascalName}SubscriptionEvents } from './subscription-events';
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Service for publishing ${pascalName} subscription events
|
|
280
|
+
*/
|
|
281
|
+
@Injectable()
|
|
282
|
+
export class ${pascalName}EventPublisher {
|
|
283
|
+
private readonly logger = new Logger(${pascalName}EventPublisher.name);
|
|
284
|
+
|
|
285
|
+
constructor(private readonly pubSubService: PubSubService) {}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Publish ${camelName} created event
|
|
289
|
+
*/
|
|
290
|
+
async publishCreated(
|
|
291
|
+
data: { id: string; [key: string]: any },
|
|
292
|
+
metadata?: { correlationId?: string; userId?: string },
|
|
293
|
+
): Promise<void> {
|
|
294
|
+
const payload: SubscriptionPayload<typeof data> = {
|
|
295
|
+
data,
|
|
296
|
+
metadata: {
|
|
297
|
+
timestamp: new Date(),
|
|
298
|
+
...metadata,
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
this.logger.debug(\`Publishing ${camelName}Created event for ID: \${data.id}\`);
|
|
303
|
+
await this.pubSubService.publish(${pascalName}SubscriptionEvents.CREATED, payload);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Publish ${camelName} updated event
|
|
308
|
+
*/
|
|
309
|
+
async publishUpdated(
|
|
310
|
+
data: { id: string; changes: Record<string, { old: any; new: any }> },
|
|
311
|
+
metadata?: { correlationId?: string; userId?: string },
|
|
312
|
+
): Promise<void> {
|
|
313
|
+
const payload: SubscriptionPayload<typeof data> = {
|
|
314
|
+
data,
|
|
315
|
+
metadata: {
|
|
316
|
+
timestamp: new Date(),
|
|
317
|
+
...metadata,
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
this.logger.debug(\`Publishing ${camelName}Updated event for ID: \${data.id}\`);
|
|
322
|
+
await this.pubSubService.publish(${pascalName}SubscriptionEvents.UPDATED, payload);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Publish ${camelName} deleted event
|
|
327
|
+
*/
|
|
328
|
+
async publishDeleted(
|
|
329
|
+
data: { id: string },
|
|
330
|
+
metadata?: { correlationId?: string; userId?: string },
|
|
331
|
+
): Promise<void> {
|
|
332
|
+
const payload: SubscriptionPayload<typeof data> = {
|
|
333
|
+
data,
|
|
334
|
+
metadata: {
|
|
335
|
+
timestamp: new Date(),
|
|
336
|
+
...metadata,
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
this.logger.debug(\`Publishing ${camelName}Deleted event for ID: \${data.id}\`);
|
|
341
|
+
await this.pubSubService.publish(${pascalName}SubscriptionEvents.DELETED, payload);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Publish custom event
|
|
346
|
+
*/
|
|
347
|
+
async publishCustom<T>(
|
|
348
|
+
eventName: string,
|
|
349
|
+
data: T,
|
|
350
|
+
metadata?: { correlationId?: string; userId?: string },
|
|
351
|
+
): Promise<void> {
|
|
352
|
+
const payload: SubscriptionPayload<T> = {
|
|
353
|
+
data,
|
|
354
|
+
metadata: {
|
|
355
|
+
timestamp: new Date(),
|
|
356
|
+
...metadata,
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
this.logger.debug(\`Publishing custom event: \${eventName}\`);
|
|
361
|
+
await this.pubSubService.publish(eventName, payload);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
`;
|
|
365
|
+
fs.writeFileSync(path.join(baseDir, `${kebabName}-event-publisher.ts`), eventPublisherContent);
|
|
366
|
+
// WebSocket connection manager
|
|
367
|
+
const connectionManagerContent = `import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common';
|
|
368
|
+
|
|
369
|
+
interface ConnectionInfo {
|
|
370
|
+
id: string;
|
|
371
|
+
userId?: string;
|
|
372
|
+
connectedAt: Date;
|
|
373
|
+
subscriptions: Set<string>;
|
|
374
|
+
metadata: Record<string, any>;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Manages WebSocket connections for GraphQL subscriptions
|
|
379
|
+
*/
|
|
380
|
+
@Injectable()
|
|
381
|
+
export class ConnectionManager implements OnModuleDestroy {
|
|
382
|
+
private readonly logger = new Logger(ConnectionManager.name);
|
|
383
|
+
private readonly connections: Map<string, ConnectionInfo> = new Map();
|
|
384
|
+
|
|
385
|
+
async onModuleDestroy(): Promise<void> {
|
|
386
|
+
this.connections.clear();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Register a new connection
|
|
391
|
+
*/
|
|
392
|
+
addConnection(connectionId: string, userId?: string, metadata?: Record<string, any>): void {
|
|
393
|
+
this.connections.set(connectionId, {
|
|
394
|
+
id: connectionId,
|
|
395
|
+
userId,
|
|
396
|
+
connectedAt: new Date(),
|
|
397
|
+
subscriptions: new Set(),
|
|
398
|
+
metadata: metadata || {},
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
this.logger.debug(\`Connection added: \${connectionId} (user: \${userId || 'anonymous'})\`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Remove a connection
|
|
406
|
+
*/
|
|
407
|
+
removeConnection(connectionId: string): void {
|
|
408
|
+
this.connections.delete(connectionId);
|
|
409
|
+
this.logger.debug(\`Connection removed: \${connectionId}\`);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Add subscription to connection
|
|
414
|
+
*/
|
|
415
|
+
addSubscription(connectionId: string, subscriptionId: string): void {
|
|
416
|
+
const connection = this.connections.get(connectionId);
|
|
417
|
+
if (connection) {
|
|
418
|
+
connection.subscriptions.add(subscriptionId);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Remove subscription from connection
|
|
424
|
+
*/
|
|
425
|
+
removeSubscription(connectionId: string, subscriptionId: string): void {
|
|
426
|
+
const connection = this.connections.get(connectionId);
|
|
427
|
+
if (connection) {
|
|
428
|
+
connection.subscriptions.delete(subscriptionId);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Get connection by ID
|
|
434
|
+
*/
|
|
435
|
+
getConnection(connectionId: string): ConnectionInfo | undefined {
|
|
436
|
+
return this.connections.get(connectionId);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Get all connections for a user
|
|
441
|
+
*/
|
|
442
|
+
getConnectionsByUserId(userId: string): ConnectionInfo[] {
|
|
443
|
+
return Array.from(this.connections.values()).filter(
|
|
444
|
+
(conn) => conn.userId === userId,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Get all active connections
|
|
450
|
+
*/
|
|
451
|
+
getAllConnections(): ConnectionInfo[] {
|
|
452
|
+
return Array.from(this.connections.values());
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Get connection count
|
|
457
|
+
*/
|
|
458
|
+
getConnectionCount(): number {
|
|
459
|
+
return this.connections.size;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Get connections subscribed to a specific event
|
|
464
|
+
*/
|
|
465
|
+
getConnectionsBySubscription(subscriptionName: string): ConnectionInfo[] {
|
|
466
|
+
return Array.from(this.connections.values()).filter(
|
|
467
|
+
(conn) => conn.subscriptions.has(subscriptionName),
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Update connection metadata
|
|
473
|
+
*/
|
|
474
|
+
updateMetadata(connectionId: string, metadata: Record<string, any>): void {
|
|
475
|
+
const connection = this.connections.get(connectionId);
|
|
476
|
+
if (connection) {
|
|
477
|
+
connection.metadata = { ...connection.metadata, ...metadata };
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Check if user has active connection
|
|
483
|
+
*/
|
|
484
|
+
isUserConnected(userId: string): boolean {
|
|
485
|
+
return Array.from(this.connections.values()).some(
|
|
486
|
+
(conn) => conn.userId === userId,
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
`;
|
|
491
|
+
fs.writeFileSync(path.join(baseDir, 'connection-manager.ts'), connectionManagerContent);
|
|
492
|
+
// Subscription guard
|
|
493
|
+
const subscriptionGuardContent = `import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common';
|
|
494
|
+
import { GqlExecutionContext } from '@nestjs/graphql';
|
|
495
|
+
import { Observable } from 'rxjs';
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Guard for GraphQL subscriptions
|
|
499
|
+
* Validates connection parameters and authentication
|
|
500
|
+
*/
|
|
501
|
+
@Injectable()
|
|
502
|
+
export class SubscriptionGuard implements CanActivate {
|
|
503
|
+
private readonly logger = new Logger(SubscriptionGuard.name);
|
|
504
|
+
|
|
505
|
+
canActivate(
|
|
506
|
+
context: ExecutionContext,
|
|
507
|
+
): boolean | Promise<boolean> | Observable<boolean> {
|
|
508
|
+
const gqlContext = GqlExecutionContext.create(context);
|
|
509
|
+
const ctx = gqlContext.getContext();
|
|
510
|
+
|
|
511
|
+
// For WebSocket connections, check connection params
|
|
512
|
+
if (ctx.connection) {
|
|
513
|
+
return this.validateConnection(ctx.connection);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// For regular subscriptions
|
|
517
|
+
return this.validateSubscription(ctx);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
private validateConnection(connection: any): boolean {
|
|
521
|
+
const { context } = connection;
|
|
522
|
+
|
|
523
|
+
// Check if authentication is required
|
|
524
|
+
if (process.env.REQUIRE_SUBSCRIPTION_AUTH === 'true') {
|
|
525
|
+
if (!context?.user) {
|
|
526
|
+
this.logger.warn('Subscription connection rejected: no authenticated user');
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private validateSubscription(ctx: any): boolean {
|
|
535
|
+
// Add custom validation logic here
|
|
536
|
+
// Example: check rate limits, validate permissions, etc.
|
|
537
|
+
return true;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Decorator to require specific permission for subscription
|
|
543
|
+
*/
|
|
544
|
+
export function RequireSubscriptionPermission(permission: string): MethodDecorator {
|
|
545
|
+
return (target, propertyKey, descriptor) => {
|
|
546
|
+
const originalMethod = descriptor.value as Function;
|
|
547
|
+
|
|
548
|
+
(descriptor as any).value = function (...args: any[]) {
|
|
549
|
+
const context = args.find((arg) => arg?.connection || arg?.req);
|
|
550
|
+
const user = context?.connection?.context?.user || context?.req?.user;
|
|
551
|
+
|
|
552
|
+
if (!user?.permissions?.includes(permission)) {
|
|
553
|
+
throw new Error(\`Permission denied: \${permission} required\`);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return originalMethod.apply(this, args);
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
return descriptor;
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
`;
|
|
563
|
+
fs.writeFileSync(path.join(baseDir, 'subscription.guard.ts'), subscriptionGuardContent);
|
|
564
|
+
// GraphQL subscriptions module
|
|
565
|
+
const subscriptionsModuleContent = `import { Module, Global } from '@nestjs/common';
|
|
566
|
+
import { PubSubService } from './pubsub.service';
|
|
567
|
+
import { ${pascalName}SubscriptionResolver } from './${kebabName}-subscription.resolver';
|
|
568
|
+
import { ${pascalName}EventPublisher } from './${kebabName}-event-publisher';
|
|
569
|
+
import { ConnectionManager } from './connection-manager';
|
|
570
|
+
import { SubscriptionGuard } from './subscription.guard';
|
|
571
|
+
|
|
572
|
+
@Global()
|
|
573
|
+
@Module({
|
|
574
|
+
providers: [
|
|
575
|
+
PubSubService,
|
|
576
|
+
${pascalName}SubscriptionResolver,
|
|
577
|
+
${pascalName}EventPublisher,
|
|
578
|
+
ConnectionManager,
|
|
579
|
+
SubscriptionGuard,
|
|
580
|
+
],
|
|
581
|
+
exports: [
|
|
582
|
+
PubSubService,
|
|
583
|
+
${pascalName}EventPublisher,
|
|
584
|
+
ConnectionManager,
|
|
585
|
+
],
|
|
586
|
+
})
|
|
587
|
+
export class ${pascalName}SubscriptionsModule {}
|
|
588
|
+
`;
|
|
589
|
+
fs.writeFileSync(path.join(baseDir, 'subscriptions.module.ts'), subscriptionsModuleContent);
|
|
590
|
+
console.log(chalk_1.default.green(` ✓ Created PubSub service`));
|
|
591
|
+
console.log(chalk_1.default.green(` ✓ Created subscription events`));
|
|
592
|
+
console.log(chalk_1.default.green(` ✓ Created subscription resolver`));
|
|
593
|
+
console.log(chalk_1.default.green(` ✓ Created event publisher`));
|
|
594
|
+
console.log(chalk_1.default.green(` ✓ Created connection manager`));
|
|
595
|
+
console.log(chalk_1.default.green(` ✓ Created subscription guard`));
|
|
596
|
+
console.log(chalk_1.default.green(` ✓ Created subscriptions module`));
|
|
597
|
+
console.log(chalk_1.default.bold.green(`\n✅ GraphQL subscriptions setup complete for ${pascalName}`));
|
|
598
|
+
console.log(chalk_1.default.cyan(`Generated files in: ${baseDir}`));
|
|
599
|
+
console.log(chalk_1.default.gray(' - pubsub.service.ts (PubSub service)'));
|
|
600
|
+
console.log(chalk_1.default.gray(' - subscription-events.ts (Event definitions)'));
|
|
601
|
+
console.log(chalk_1.default.gray(` - ${kebabName}-subscription.resolver.ts (Subscription resolver)`));
|
|
602
|
+
console.log(chalk_1.default.gray(` - ${kebabName}-event-publisher.ts (Event publisher)`));
|
|
603
|
+
console.log(chalk_1.default.gray(' - connection-manager.ts (WebSocket connections)'));
|
|
604
|
+
console.log(chalk_1.default.gray(' - subscription.guard.ts (Auth guard)'));
|
|
605
|
+
console.log(chalk_1.default.gray(' - subscriptions.module.ts (Module definition)'));
|
|
606
|
+
}
|
|
607
|
+
//# sourceMappingURL=graphql-subscriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-subscriptions.js","sourceRoot":"","sources":["../../src/commands/graphql-subscriptions.ts"],"names":[],"mappings":"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"}
|