@breadstone/archipel-mcp 0.0.21 → 0.0.22
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/data/guides/cryptography-and-otp.md +2 -2
- package/data/guides/database-setup.md +4 -3
- package/data/guides/email-templates.md +3 -3
- package/data/guides/getting-started.md +6 -6
- package/data/guides/resource-management.md +9 -9
- package/data/packages/platform-blob-storage/api/Variable.AWS_S3_PROVIDER_OPTIONS.md +1 -1
- package/data/packages/platform-blob-storage/api/Variable.AZURE_BLOB_PROVIDER_OPTIONS.md +1 -1
- package/data/packages/platform-blob-storage/api/Variable.BLOB_PROVIDER.md +1 -1
- package/data/packages/platform-blob-storage/api/Variable.VERCEL_BLOB_PROVIDER_OPTIONS.md +1 -1
- package/data/packages/platform-core/api/Class.ErrorTemplateService.md +1 -1
- package/data/packages/platform-core/api/Class.HostService.md +1 -1
- package/data/packages/platform-core/api/Variable.ID_GENERATOR_TOKEN.md +1 -1
- package/data/packages/platform-core/api/index.md +0 -27
- package/data/packages/platform-core/index.md +7 -4
- package/data/packages/platform-cryptography/api/Class.BcryptService.md +4 -4
- package/data/packages/platform-cryptography/api/Class.OtpService.md +6 -6
- package/data/packages/platform-cryptography/api/Variable.BCRYPT_OPTIONS.md +2 -2
- package/data/packages/platform-cryptography/api/Variable.MAX_BCRYPT_PASSWORD_BYTES.md +1 -1
- package/data/packages/platform-cryptography/api/Variable.MIN_BCRYPT_ROUNDS.md +1 -1
- package/data/packages/platform-cryptography/api/Variable.OTP_OPTIONS.md +2 -2
- package/data/packages/platform-cryptography/api/Variable.OTP_SERVICE_TOKEN.md +2 -2
- package/data/packages/platform-cryptography/api/Variable.TOTP_EPOCH_TOLERANCE.md +1 -1
- package/data/packages/platform-cryptography/api/index.md +3 -3
- package/data/packages/platform-documents/api/Class.BaseDocumentRenderer.md +32 -1
- package/data/packages/platform-documents/api/Class.DocumentEngine.md +4 -4
- package/data/packages/platform-documents/api/Class.DocumentModule.md +2 -2
- package/data/packages/platform-documents/api/Class.DocxDocumentRenderer2.md +333 -0
- package/data/packages/platform-documents/api/Class.PdfDocumentRenderer.md +355 -0
- package/data/packages/platform-documents/api/Interface.IDocumentModuleOptions.md +31 -5
- package/data/packages/platform-documents/api/Variable.DOCUMENT_MODULE_OPTIONS.md +1 -1
- package/data/packages/platform-documents/api/Variable.DOCUMENT_PARSER_TOKEN.md +1 -1
- package/data/packages/platform-documents/api/Variable.DOCUMENT_RENDERER_TOKEN.md +1 -1
- package/data/packages/platform-documents/api/Variable.IMAGE_PROCESSOR_TOKEN.md +1 -1
- package/data/packages/platform-documents/api/index.md +2 -0
- package/data/packages/platform-esigning/api/Class.EsigningClientPort.md +1 -1
- package/data/packages/platform-health/index.md +128 -0
- package/data/packages/platform-mailing/api/Class.DeliveryStrategyBase.md +0 -1
- package/data/packages/platform-mailing/api/Class.MailModule.md +1 -1
- package/data/packages/platform-mailing/api/Class.TemplateFetchStrategyBase.md +0 -5
- package/data/packages/platform-mailing/api/Variable.SMTP_CONFIG_ENTRIES.md +14 -0
- package/data/packages/platform-mailing/api/Variable.SMTP_HOST.md +14 -0
- package/data/packages/platform-mailing/api/Variable.SMTP_PASSWORD.md +14 -0
- package/data/packages/platform-mailing/api/Variable.SMTP_PORT.md +14 -0
- package/data/packages/platform-mailing/api/Variable.SMTP_SECURE.md +14 -0
- package/data/packages/platform-mailing/api/Variable.SMTP_USER.md +14 -0
- package/data/packages/platform-mailing/api/index.md +6 -3
- package/data/packages/platform-mapping/index.md +121 -0
- package/data/packages/platform-mcp/api/Variable.MCP_MODULE_OPTIONS.md +1 -1
- package/data/packages/platform-openapi/api/Class.SwaggerMultiDocumentService.md +4 -4
- package/data/packages/platform-resources/index.md +135 -0
- package/data/packages/platform-telemetry/api/Variable.TELEMETRY_ENABLED.md +1 -1
- package/data/packages/platform-telemetry/api/Variable.TELEMETRY_FACADE.md +1 -1
- package/data/packages/platform-telemetry/api/Variable.TELEMETRY_OPTIONS.md +1 -1
- package/{src/knowledge/configPattern.js → data/patterns/config-pattern.md} +44 -47
- package/{src/knowledge/dtoPattern.js → data/patterns/dto-pattern.md} +58 -61
- package/{src/knowledge/errorHandlingPattern.js → data/patterns/error-handling-pattern.md} +35 -38
- package/{src/knowledge/guardPattern.js → data/patterns/guard-pattern.md} +35 -38
- package/{src/knowledge/mappingPattern.js → data/patterns/mapping-pattern.md} +43 -144
- package/data/patterns/module-pattern.md +182 -0
- package/data/patterns/query-pattern.md +137 -0
- package/data/patterns/repository-pattern.md +208 -0
- package/{src/knowledge/testingPattern.js → data/patterns/testing-pattern.md} +37 -40
- package/package.json +1 -1
- package/src/PatternsLoader.d.ts +12 -0
- package/src/PatternsLoader.js +65 -0
- package/src/generators/mappingPatternGenerator.d.ts +5 -0
- package/src/generators/mappingPatternGenerator.js +107 -0
- package/src/generators/modulePatternGenerator.d.ts +5 -0
- package/src/generators/modulePatternGenerator.js +107 -0
- package/src/generators/queryPatternGenerator.d.ts +4 -0
- package/src/generators/queryPatternGenerator.js +83 -0
- package/src/generators/repositoryPatternGenerator.d.ts +5 -0
- package/src/generators/repositoryPatternGenerator.js +165 -0
- package/src/main.js +15 -9
- package/src/models/IPatternDoc.d.ts +15 -0
- package/src/models/IPatternDoc.js +3 -0
- package/src/tools/registerGetConfigPatternTool.d.ts +2 -1
- package/src/tools/registerGetConfigPatternTool.js +4 -3
- package/src/tools/registerGetDtoPatternTool.d.ts +2 -1
- package/src/tools/registerGetDtoPatternTool.js +4 -3
- package/src/tools/registerGetErrorHandlingPatternTool.d.ts +2 -1
- package/src/tools/registerGetErrorHandlingPatternTool.js +4 -3
- package/src/tools/registerGetGuardPatternTool.d.ts +2 -1
- package/src/tools/registerGetGuardPatternTool.js +4 -3
- package/src/tools/registerGetMappingPatternTool.d.ts +2 -1
- package/src/tools/registerGetMappingPatternTool.js +5 -4
- package/src/tools/registerGetModulePatternTool.d.ts +2 -1
- package/src/tools/registerGetModulePatternTool.js +5 -4
- package/src/tools/registerGetQueryPatternTool.d.ts +2 -1
- package/src/tools/registerGetQueryPatternTool.js +5 -4
- package/src/tools/registerGetRepositoryPatternTool.d.ts +2 -1
- package/src/tools/registerGetRepositoryPatternTool.js +5 -4
- package/src/tools/registerGetTestingPatternTool.d.ts +2 -1
- package/src/tools/registerGetTestingPatternTool.js +4 -3
- package/data/packages/platform-core/api/Class.BlobResourceStrategy.md +0 -195
- package/data/packages/platform-core/api/Class.EmbeddedResourceStrategy.md +0 -215
- package/data/packages/platform-core/api/Class.FileResourceStrategy.md +0 -192
- package/data/packages/platform-core/api/Class.HealthModule.md +0 -42
- package/data/packages/platform-core/api/Class.HealthOrchestrator.md +0 -64
- package/data/packages/platform-core/api/Class.MappingBuilder.md +0 -110
- package/data/packages/platform-core/api/Class.MappingModule.md +0 -46
- package/data/packages/platform-core/api/Class.MappingNotRegisteredError.md +0 -56
- package/data/packages/platform-core/api/Class.MappingProfileBase.md +0 -52
- package/data/packages/platform-core/api/Class.MappingService.md +0 -284
- package/data/packages/platform-core/api/Class.ResourceManager.md +0 -565
- package/data/packages/platform-core/api/Class.ResourceModule.md +0 -46
- package/data/packages/platform-core/api/Class.TypeMappingNotRegisteredError.md +0 -57
- package/data/packages/platform-core/api/Function.createMappingKey.md +0 -39
- package/data/packages/platform-core/api/Interface.IBlobResourceStrategyConfig.md +0 -28
- package/data/packages/platform-core/api/Interface.IBlobServiceAdapter.md +0 -40
- package/data/packages/platform-core/api/Interface.IFileResourceStrategyConfig.md +0 -72
- package/data/packages/platform-core/api/Interface.IHealthCheckResult.md +0 -46
- package/data/packages/platform-core/api/Interface.IHealthIndicator.md +0 -41
- package/data/packages/platform-core/api/Interface.IMappingBuilder.md +0 -76
- package/data/packages/platform-core/api/Interface.IMappingKey.md +0 -58
- package/data/packages/platform-core/api/Interface.IMappingProfile.md +0 -32
- package/data/packages/platform-core/api/Interface.IResourceManagerConfig.md +0 -89
- package/data/packages/platform-core/api/Interface.IResourceMetadata.md +0 -94
- package/data/packages/platform-core/api/Interface.IResourceResult.md +0 -34
- package/data/packages/platform-core/api/Interface.IResourceStrategy.md +0 -134
- package/data/packages/platform-core/api/Variable.HEALTH_INDICATORS_TOKEN.md +0 -14
- package/data/packages/platform-mailing/api/Class.BlobTemplateFetchStrategy.md +0 -60
- package/data/packages/platform-mailing/api/Class.FileTemplateFetchStrategy.md +0 -58
- package/data/packages/platform-mailing/api/Class.LogDeliveryStrategy.md +0 -71
- package/src/knowledge/configPattern.d.ts +0 -5
- package/src/knowledge/dtoPattern.d.ts +0 -5
- package/src/knowledge/errorHandlingPattern.d.ts +0 -5
- package/src/knowledge/guardPattern.d.ts +0 -5
- package/src/knowledge/mappingPattern.d.ts +0 -6
- package/src/knowledge/modulePattern.d.ts +0 -6
- package/src/knowledge/modulePattern.js +0 -283
- package/src/knowledge/queryPattern.d.ts +0 -6
- package/src/knowledge/queryPattern.js +0 -215
- package/src/knowledge/repositoryPattern.d.ts +0 -6
- package/src/knowledge/repositoryPattern.js +0 -367
- package/src/knowledge/testingPattern.d.ts +0 -5
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Static knowledge content for the Archipel dynamic module pattern.
|
|
4
|
-
* Returned by the get-module-pattern tool.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.MODULE_PATTERN_WITH_CONTEXT = exports.MODULE_PATTERN_KNOWLEDGE = void 0;
|
|
8
|
-
exports.MODULE_PATTERN_KNOWLEDGE = `# Archipel Dynamic Module Pattern
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
Archipel platform libraries use **NestJS dynamic modules** with a \`register()\` factory
|
|
13
|
-
method and **port/adapter dependency inversion**. Each library defines abstract port
|
|
14
|
-
classes. The consuming application provides concrete implementations at registration time.
|
|
15
|
-
|
|
16
|
-
This pattern keeps platform libraries free of product-specific logic while allowing
|
|
17
|
-
full customization through dependency injection.
|
|
18
|
-
|
|
19
|
-
## Pattern Structure
|
|
20
|
-
|
|
21
|
-
### 1. Abstract Port (Contract)
|
|
22
|
-
|
|
23
|
-
\`\`\`typescript
|
|
24
|
-
// contracts/FeatureAccessPort.ts
|
|
25
|
-
|
|
26
|
-
export abstract class FeatureAccessPort {
|
|
27
|
-
|
|
28
|
-
public abstract checkAccess(userId: string, featureKey: string): Promise<IFeatureAccessResult>;
|
|
29
|
-
|
|
30
|
-
public abstract recordUsage(userId: string, featureKey: string): Promise<void>;
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
\`\`\`
|
|
34
|
-
|
|
35
|
-
Ports are **abstract classes** (not interfaces) so they can serve as NestJS injection tokens.
|
|
36
|
-
|
|
37
|
-
### 2. Options Interface
|
|
38
|
-
|
|
39
|
-
\`\`\`typescript
|
|
40
|
-
// interfaces/IPaymentModuleOptions.ts
|
|
41
|
-
|
|
42
|
-
export interface IPaymentModuleOptions {
|
|
43
|
-
/**
|
|
44
|
-
* Concrete implementation of the FeatureAccessPort.
|
|
45
|
-
*/
|
|
46
|
-
featureAccess?: Type<FeatureAccessPort>;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* When true the module is registered globally.
|
|
50
|
-
*/
|
|
51
|
-
isGlobal?: boolean;
|
|
52
|
-
}
|
|
53
|
-
\`\`\`
|
|
54
|
-
|
|
55
|
-
### 3. Dynamic Module with register()
|
|
56
|
-
|
|
57
|
-
\`\`\`typescript
|
|
58
|
-
// PaymentModule.ts
|
|
59
|
-
import { ConfigModule } from '@breadstone/archipel-platform-core';
|
|
60
|
-
import { type DynamicModule, Module, type Type } from '@nestjs/common';
|
|
61
|
-
|
|
62
|
-
@Module({})
|
|
63
|
-
export class PaymentModule {
|
|
64
|
-
|
|
65
|
-
public static register(options?: IPaymentModuleOptions): DynamicModule {
|
|
66
|
-
const providers = [StripeClient, FeatureGuard, FeatureUsageInterceptor];
|
|
67
|
-
|
|
68
|
-
if (options?.featureAccess) {
|
|
69
|
-
providers.push({
|
|
70
|
-
provide: FeatureAccessPort,
|
|
71
|
-
useClass: options.featureAccess,
|
|
72
|
-
} as never);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
global: options?.isGlobal ?? false,
|
|
77
|
-
module: PaymentModule,
|
|
78
|
-
imports: [ConfigModule.register('platform-payments', PLATFORM_PAYMENTS_CONFIG_ENTRIES)],
|
|
79
|
-
providers: providers,
|
|
80
|
-
exports: [StripeClient, FeatureGuard, FeatureUsageInterceptor],
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
\`\`\`
|
|
86
|
-
|
|
87
|
-
### 4. Consumer Registration
|
|
88
|
-
|
|
89
|
-
\`\`\`typescript
|
|
90
|
-
// In the consuming application:
|
|
91
|
-
@Module({
|
|
92
|
-
imports: [
|
|
93
|
-
PaymentModule.register({
|
|
94
|
-
featureAccess: MyFeatureAccessAdapter,
|
|
95
|
-
isGlobal: true,
|
|
96
|
-
}),
|
|
97
|
-
],
|
|
98
|
-
})
|
|
99
|
-
export class AppModule {}
|
|
100
|
-
\`\`\`
|
|
101
|
-
|
|
102
|
-
## Variants in the Codebase
|
|
103
|
-
|
|
104
|
-
### Simple: PaymentModule
|
|
105
|
-
|
|
106
|
-
- 1 optional port (\`featureAccess\`)
|
|
107
|
-
- Optional \`isGlobal\` flag
|
|
108
|
-
- Config via \`ConfigModule.register()\`
|
|
109
|
-
|
|
110
|
-
### Complex: AuthModule
|
|
111
|
-
|
|
112
|
-
- 4 required ports (\`authSubject\`, \`mfaSubject\`, \`sessionPersistence\`, \`verificationSubject\`)
|
|
113
|
-
- 2 optional ports (\`socialAuth\`, \`tokenEnricher\`)
|
|
114
|
-
- Conditional strategy registration (social OAuth only when \`socialAuth\` provided)
|
|
115
|
-
- Imports: PassportModule, JwtModule, MappingModule, EventModule, IdentifierModule
|
|
116
|
-
- Middleware configuration via \`configure(consumer)\`
|
|
117
|
-
|
|
118
|
-
### Provider-based: BlobModule
|
|
119
|
-
|
|
120
|
-
- Uses \`forRoot()\` instead of \`register()\` (global by default)
|
|
121
|
-
- Discriminated union for provider selection: \`{ kind: 'Vercel' }\` or \`{ kind: 'Custom', useClass: ... }\`
|
|
122
|
-
- Optional persistence ports (\`objectPersistence\`, \`variantPersistence\`)
|
|
123
|
-
|
|
124
|
-
### Infrastructure: DatabaseModule
|
|
125
|
-
|
|
126
|
-
- Both \`forRoot()\` (global) and \`register()\` (scoped) variants
|
|
127
|
-
- Factory provider for PrismaService with extensions
|
|
128
|
-
- Health indicator bootstrapping
|
|
129
|
-
|
|
130
|
-
### Async: McpModule
|
|
131
|
-
|
|
132
|
-
- \`register(options)\` for synchronous configuration
|
|
133
|
-
- \`registerAsync({ useFactory, inject })\` for async (e.g., reading config at runtime)
|
|
134
|
-
- \`registerAsync({ useClass })\` for factory class pattern
|
|
135
|
-
- \`registerAsync({ useExisting })\` for reusing an existing factory
|
|
136
|
-
|
|
137
|
-
## ConfigModule Integration
|
|
138
|
-
|
|
139
|
-
Every library module imports \`ConfigModule.register()\` to declare its configuration
|
|
140
|
-
dependencies:
|
|
141
|
-
|
|
142
|
-
\`\`\`typescript
|
|
143
|
-
imports: [ConfigModule.register('platform-payments', PLATFORM_PAYMENTS_CONFIG_ENTRIES)]
|
|
144
|
-
\`\`\`
|
|
145
|
-
|
|
146
|
-
This registers typed config keys into the global \`ConfigRegistry\` for validation
|
|
147
|
-
and discovery.
|
|
148
|
-
|
|
149
|
-
## MappingModule Integration
|
|
150
|
-
|
|
151
|
-
Modules that need object mapping import \`MappingModule.withProfiles()\`:
|
|
152
|
-
|
|
153
|
-
\`\`\`typescript
|
|
154
|
-
imports: [MappingModule.withProfiles([SessionMappingProfile])]
|
|
155
|
-
\`\`\`
|
|
156
|
-
|
|
157
|
-
## Health Indicator Pattern
|
|
158
|
-
|
|
159
|
-
Infrastructure modules (Database, Blob) register health indicators:
|
|
160
|
-
|
|
161
|
-
\`\`\`typescript
|
|
162
|
-
providers: [
|
|
163
|
-
BlobHealthIndicator,
|
|
164
|
-
{
|
|
165
|
-
provide: 'BLOB_HEALTH_INDICATOR_BOOTSTRAP',
|
|
166
|
-
useFactory: (orchestrator: HealthOrchestrator, indicator: BlobHealthIndicator) => {
|
|
167
|
-
orchestrator.registerIndicator(indicator);
|
|
168
|
-
return true;
|
|
169
|
-
},
|
|
170
|
-
inject: [HealthOrchestrator, BlobHealthIndicator],
|
|
171
|
-
},
|
|
172
|
-
]
|
|
173
|
-
\`\`\`
|
|
174
|
-
|
|
175
|
-
## Rules
|
|
176
|
-
|
|
177
|
-
1. **Ports are abstract classes** — not interfaces — so they work as DI tokens.
|
|
178
|
-
2. **\`register()\` for stateless config**, \`registerAsync()\` when config depends on runtime values.
|
|
179
|
-
3. **\`forRoot()\` for global singletons** (database, blob storage), \`register()\` for scoped modules.
|
|
180
|
-
4. **Always import ConfigModule.register()** to declare environment dependencies.
|
|
181
|
-
5. **Optional ports use conditional provider registration** (\`if (options?.port)\`).
|
|
182
|
-
6. **Required ports are listed in the options interface** without optional markers.
|
|
183
|
-
7. **Exports should list concrete services, guards, interceptors** — not internal implementation details.
|
|
184
|
-
`;
|
|
185
|
-
const MODULE_PATTERN_WITH_CONTEXT = (moduleName, ports) => `
|
|
186
|
-
## Example: Dynamic Module "${moduleName}"
|
|
187
|
-
|
|
188
|
-
With ports: ${ports.map((p) => `\`${p}\``).join(', ')}
|
|
189
|
-
|
|
190
|
-
### Port Definitions
|
|
191
|
-
|
|
192
|
-
${ports
|
|
193
|
-
.map((port) => `\`\`\`typescript
|
|
194
|
-
// contracts/${port}.ts
|
|
195
|
-
|
|
196
|
-
export abstract class ${port} {
|
|
197
|
-
|
|
198
|
-
// Define abstract methods for the port contract
|
|
199
|
-
public abstract execute(/* args */): Promise<void>;
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
\`\`\``)
|
|
203
|
-
.join('\n\n')}
|
|
204
|
-
|
|
205
|
-
### Options Interface
|
|
206
|
-
|
|
207
|
-
\`\`\`typescript
|
|
208
|
-
// interfaces/I${moduleName}Options.ts
|
|
209
|
-
import { Type } from '@nestjs/common';
|
|
210
|
-
${ports.map((port) => `import { ${port} } from '../contracts/${port}';`).join('\n')}
|
|
211
|
-
|
|
212
|
-
export interface I${moduleName}Options {
|
|
213
|
-
${ports.map((port) => ` ${lowerFirstChar(port)}: Type<${port}>;`).join('\n')}
|
|
214
|
-
isGlobal?: boolean;
|
|
215
|
-
}
|
|
216
|
-
\`\`\`
|
|
217
|
-
|
|
218
|
-
### Module Class
|
|
219
|
-
|
|
220
|
-
\`\`\`typescript
|
|
221
|
-
// ${moduleName}.ts
|
|
222
|
-
import { ConfigModule } from '@breadstone/archipel-platform-core';
|
|
223
|
-
import { type DynamicModule, Module, type Type } from '@nestjs/common';
|
|
224
|
-
import { I${moduleName}Options } from './interfaces/I${moduleName}Options';
|
|
225
|
-
${ports.map((port) => `import { ${port} } from './contracts/${port}';`).join('\n')}
|
|
226
|
-
|
|
227
|
-
@Module({})
|
|
228
|
-
export class ${moduleName} {
|
|
229
|
-
|
|
230
|
-
public static register(options: I${moduleName}Options): DynamicModule {
|
|
231
|
-
const portProviders = [
|
|
232
|
-
${ports.map((port) => ` { provide: ${port}, useClass: options.${lowerFirstChar(port)} },`).join('\n')}
|
|
233
|
-
];
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
global: options.isGlobal ?? false,
|
|
237
|
-
module: ${moduleName},
|
|
238
|
-
imports: [
|
|
239
|
-
ConfigModule.register('${toKebabCase(moduleName)}', PLATFORM_${toUpperSnakeCase(moduleName)}_CONFIG_ENTRIES),
|
|
240
|
-
],
|
|
241
|
-
providers: [
|
|
242
|
-
...portProviders,
|
|
243
|
-
// Add services, guards, interceptors here
|
|
244
|
-
],
|
|
245
|
-
exports: [
|
|
246
|
-
// Export public services, guards, interceptors
|
|
247
|
-
],
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
\`\`\`
|
|
253
|
-
|
|
254
|
-
### Consumer Usage
|
|
255
|
-
|
|
256
|
-
\`\`\`typescript
|
|
257
|
-
@Module({
|
|
258
|
-
imports: [
|
|
259
|
-
${moduleName}.register({
|
|
260
|
-
${ports.map((port) => ` ${lowerFirstChar(port)}: My${port}Adapter,`).join('\n')}
|
|
261
|
-
}),
|
|
262
|
-
],
|
|
263
|
-
})
|
|
264
|
-
export class AppModule {}
|
|
265
|
-
\`\`\`
|
|
266
|
-
`;
|
|
267
|
-
exports.MODULE_PATTERN_WITH_CONTEXT = MODULE_PATTERN_WITH_CONTEXT;
|
|
268
|
-
function lowerFirstChar(str) {
|
|
269
|
-
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
270
|
-
}
|
|
271
|
-
function toKebabCase(name) {
|
|
272
|
-
return name
|
|
273
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
274
|
-
.toLowerCase()
|
|
275
|
-
.replace(/module$/, '');
|
|
276
|
-
}
|
|
277
|
-
function toUpperSnakeCase(name) {
|
|
278
|
-
return name
|
|
279
|
-
.replace(/([a-z])([A-Z])/g, '$1_$2')
|
|
280
|
-
.toUpperCase()
|
|
281
|
-
.replace(/MODULE$/, '');
|
|
282
|
-
}
|
|
283
|
-
//# sourceMappingURL=modulePattern.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static knowledge content for the Archipel query pattern.
|
|
3
|
-
* Returned by the get-query-pattern tool.
|
|
4
|
-
*/
|
|
5
|
-
export declare const QUERY_PATTERN_KNOWLEDGE = "# Archipel Query Pattern (v1)\n\n## Overview\n\nIn Archipel, data access follows the **Repository + Query** pattern. Repositories never expose\nraw Prisma delegate methods to services. Instead, every data operation is wrapped in a\n**query factory function** that returns an `IRepositoryQuery` object. Services call\n`repository.execute(someQuery(...))` \u2014 never `repository.findFirst(...)` directly.\n\n## Core Interface\n\n```typescript\nexport interface IRepositoryQuery<TDelegate, TResult> {\n readonly name: string;\n run(model: TDelegate): Promise<TResult>;\n}\n```\n\n- `TDelegate` \u2014 the Prisma delegate type (e.g. `Prisma.UserDelegate`)\n- `TResult` \u2014 the query's return type\n- `name` \u2014 identifier used for logging and debugging\n\n## Factory Function\n\n```typescript\nimport { IRepositoryQuery } from '@breadstone/archipel-platform-database';\n\nexport function query<TDelegate, TResult>(\n name: string,\n run: (model: TDelegate) => Promise<TResult>,\n): IRepositoryQuery<TDelegate, TResult> {\n return { name, run };\n}\n```\n\n## Type Extraction\n\n```typescript\nexport type QueryResultType<T> = T extends IRepositoryQuery<unknown, infer R> ? R : never;\n```\n\nUse this to derive the result type from a query factory without duplicating types:\n```typescript\ntype UserProfileResult = QueryResultType<ReturnType<typeof findUserProfileQuery>>;\n```\n\n## How to Write a Query\n\n### Step 1: Define the query factory function\n\nEach query is a **named function** that returns an `IRepositoryQuery`. The function may accept\nparameters \u2014 these become the query's runtime arguments.\n\n```typescript\nimport { Prisma } from '@prisma/client';\nimport { query } from '@breadstone/archipel-platform-database';\n\nexport function findUserByEmailQuery(email: string) {\n return query<Prisma.UserDelegate, { id: string; email: string; name: string } | null>(\n 'findUserByEmail',\n (model) =>\n model.findFirst({\n where: { email },\n select: { id: true, email: true, name: true },\n }),\n );\n}\n```\n\n### Step 2: Call from a service via repository.execute()\n\n```typescript\n// In the service:\nconst user = await this._userRepository.execute(findUserByEmailQuery(email));\n```\n\n### Step 3: Extract result type if needed for mapping\n\n```typescript\ntype FindUserByEmailResult = QueryResultType<ReturnType<typeof findUserByEmailQuery>>;\n```\n\n## Transactional Queries\n\nFor operations that span multiple models, use `transactionalQuery`:\n\n```typescript\nimport { Prisma } from '@prisma/client';\nimport { transactionalQuery } from '@breadstone/archipel-platform-database';\n\nexport function createOrderWithItemsQuery(data: { userId: string; items: Array<{ productId: string; quantity: number }> }) {\n return transactionalQuery<{ orderId: string }>(\n 'createOrderWithItems',\n async (tx: Prisma.TransactionClient) => {\n const order = await tx.order.create({\n data: { userId: data.userId },\n select: { id: true },\n });\n\n await tx.orderItem.createMany({\n data: data.items.map((item) => ({\n orderId: order.id,\n productId: item.productId,\n quantity: item.quantity,\n })),\n });\n\n return { orderId: order.id };\n },\n );\n}\n```\n\nCalled via:\n```typescript\nconst result = await this._orderRepository.executeTransactional(\n createOrderWithItemsQuery({ userId, items }),\n);\n```\n\n## Rules\n\n1. **Never call Prisma delegate methods directly from services.** Always go through `execute(query)`.\n2. **Always select only the fields you need.** Use `select` \u2014 never return full records.\n3. **Query names must be descriptive.** Use the pattern: `verbModelByConditionQuery`\n (e.g. `findUserByEmailQuery`, `countOrdersByStatusQuery`, `updateUserNameQuery`).\n4. **One query per file** for non-trivial queries. Small related queries may share a file.\n5. **Type the result explicitly.** The second generic parameter of `query()` should be an inline\n object type or a dedicated interface matching the `select` shape.\n6. **Each query factory is a standalone function** (not a class method). Import `query` from\n `@breadstone/archipel-platform-database`.\n";
|
|
6
|
-
export declare const QUERY_PATTERN_WITH_MODEL: (modelName: string, fields: string[]) => string;
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Static knowledge content for the Archipel query pattern.
|
|
4
|
-
* Returned by the get-query-pattern tool.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.QUERY_PATTERN_WITH_MODEL = exports.QUERY_PATTERN_KNOWLEDGE = void 0;
|
|
8
|
-
exports.QUERY_PATTERN_KNOWLEDGE = `# Archipel Query Pattern (v1)
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
In Archipel, data access follows the **Repository + Query** pattern. Repositories never expose
|
|
13
|
-
raw Prisma delegate methods to services. Instead, every data operation is wrapped in a
|
|
14
|
-
**query factory function** that returns an \`IRepositoryQuery\` object. Services call
|
|
15
|
-
\`repository.execute(someQuery(...))\` — never \`repository.findFirst(...)\` directly.
|
|
16
|
-
|
|
17
|
-
## Core Interface
|
|
18
|
-
|
|
19
|
-
\`\`\`typescript
|
|
20
|
-
export interface IRepositoryQuery<TDelegate, TResult> {
|
|
21
|
-
readonly name: string;
|
|
22
|
-
run(model: TDelegate): Promise<TResult>;
|
|
23
|
-
}
|
|
24
|
-
\`\`\`
|
|
25
|
-
|
|
26
|
-
- \`TDelegate\` — the Prisma delegate type (e.g. \`Prisma.UserDelegate\`)
|
|
27
|
-
- \`TResult\` — the query's return type
|
|
28
|
-
- \`name\` — identifier used for logging and debugging
|
|
29
|
-
|
|
30
|
-
## Factory Function
|
|
31
|
-
|
|
32
|
-
\`\`\`typescript
|
|
33
|
-
import { IRepositoryQuery } from '@breadstone/archipel-platform-database';
|
|
34
|
-
|
|
35
|
-
export function query<TDelegate, TResult>(
|
|
36
|
-
name: string,
|
|
37
|
-
run: (model: TDelegate) => Promise<TResult>,
|
|
38
|
-
): IRepositoryQuery<TDelegate, TResult> {
|
|
39
|
-
return { name, run };
|
|
40
|
-
}
|
|
41
|
-
\`\`\`
|
|
42
|
-
|
|
43
|
-
## Type Extraction
|
|
44
|
-
|
|
45
|
-
\`\`\`typescript
|
|
46
|
-
export type QueryResultType<T> = T extends IRepositoryQuery<unknown, infer R> ? R : never;
|
|
47
|
-
\`\`\`
|
|
48
|
-
|
|
49
|
-
Use this to derive the result type from a query factory without duplicating types:
|
|
50
|
-
\`\`\`typescript
|
|
51
|
-
type UserProfileResult = QueryResultType<ReturnType<typeof findUserProfileQuery>>;
|
|
52
|
-
\`\`\`
|
|
53
|
-
|
|
54
|
-
## How to Write a Query
|
|
55
|
-
|
|
56
|
-
### Step 1: Define the query factory function
|
|
57
|
-
|
|
58
|
-
Each query is a **named function** that returns an \`IRepositoryQuery\`. The function may accept
|
|
59
|
-
parameters — these become the query's runtime arguments.
|
|
60
|
-
|
|
61
|
-
\`\`\`typescript
|
|
62
|
-
import { Prisma } from '@prisma/client';
|
|
63
|
-
import { query } from '@breadstone/archipel-platform-database';
|
|
64
|
-
|
|
65
|
-
export function findUserByEmailQuery(email: string) {
|
|
66
|
-
return query<Prisma.UserDelegate, { id: string; email: string; name: string } | null>(
|
|
67
|
-
'findUserByEmail',
|
|
68
|
-
(model) =>
|
|
69
|
-
model.findFirst({
|
|
70
|
-
where: { email },
|
|
71
|
-
select: { id: true, email: true, name: true },
|
|
72
|
-
}),
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
\`\`\`
|
|
76
|
-
|
|
77
|
-
### Step 2: Call from a service via repository.execute()
|
|
78
|
-
|
|
79
|
-
\`\`\`typescript
|
|
80
|
-
// In the service:
|
|
81
|
-
const user = await this._userRepository.execute(findUserByEmailQuery(email));
|
|
82
|
-
\`\`\`
|
|
83
|
-
|
|
84
|
-
### Step 3: Extract result type if needed for mapping
|
|
85
|
-
|
|
86
|
-
\`\`\`typescript
|
|
87
|
-
type FindUserByEmailResult = QueryResultType<ReturnType<typeof findUserByEmailQuery>>;
|
|
88
|
-
\`\`\`
|
|
89
|
-
|
|
90
|
-
## Transactional Queries
|
|
91
|
-
|
|
92
|
-
For operations that span multiple models, use \`transactionalQuery\`:
|
|
93
|
-
|
|
94
|
-
\`\`\`typescript
|
|
95
|
-
import { Prisma } from '@prisma/client';
|
|
96
|
-
import { transactionalQuery } from '@breadstone/archipel-platform-database';
|
|
97
|
-
|
|
98
|
-
export function createOrderWithItemsQuery(data: { userId: string; items: Array<{ productId: string; quantity: number }> }) {
|
|
99
|
-
return transactionalQuery<{ orderId: string }>(
|
|
100
|
-
'createOrderWithItems',
|
|
101
|
-
async (tx: Prisma.TransactionClient) => {
|
|
102
|
-
const order = await tx.order.create({
|
|
103
|
-
data: { userId: data.userId },
|
|
104
|
-
select: { id: true },
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
await tx.orderItem.createMany({
|
|
108
|
-
data: data.items.map((item) => ({
|
|
109
|
-
orderId: order.id,
|
|
110
|
-
productId: item.productId,
|
|
111
|
-
quantity: item.quantity,
|
|
112
|
-
})),
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
return { orderId: order.id };
|
|
116
|
-
},
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
\`\`\`
|
|
120
|
-
|
|
121
|
-
Called via:
|
|
122
|
-
\`\`\`typescript
|
|
123
|
-
const result = await this._orderRepository.executeTransactional(
|
|
124
|
-
createOrderWithItemsQuery({ userId, items }),
|
|
125
|
-
);
|
|
126
|
-
\`\`\`
|
|
127
|
-
|
|
128
|
-
## Rules
|
|
129
|
-
|
|
130
|
-
1. **Never call Prisma delegate methods directly from services.** Always go through \`execute(query)\`.
|
|
131
|
-
2. **Always select only the fields you need.** Use \`select\` — never return full records.
|
|
132
|
-
3. **Query names must be descriptive.** Use the pattern: \`verbModelByConditionQuery\`
|
|
133
|
-
(e.g. \`findUserByEmailQuery\`, \`countOrdersByStatusQuery\`, \`updateUserNameQuery\`).
|
|
134
|
-
4. **One query per file** for non-trivial queries. Small related queries may share a file.
|
|
135
|
-
5. **Type the result explicitly.** The second generic parameter of \`query()\` should be an inline
|
|
136
|
-
object type or a dedicated interface matching the \`select\` shape.
|
|
137
|
-
6. **Each query factory is a standalone function** (not a class method). Import \`query\` from
|
|
138
|
-
\`@breadstone/archipel-platform-database\`.
|
|
139
|
-
`;
|
|
140
|
-
const QUERY_PATTERN_WITH_MODEL = (modelName, fields) => `
|
|
141
|
-
## Example: Queries for \\"${modelName}\\"
|
|
142
|
-
|
|
143
|
-
Given a Prisma model \`${modelName}\` with fields: ${fields.map((f) => `\`${f}\``).join(', ')}
|
|
144
|
-
|
|
145
|
-
### findFirst query
|
|
146
|
-
\`\`\`typescript
|
|
147
|
-
import { Prisma } from '@prisma/client';
|
|
148
|
-
import { query } from '@breadstone/archipel-platform-database';
|
|
149
|
-
|
|
150
|
-
export function find${modelName}ByIdQuery(id: string) {
|
|
151
|
-
return query<Prisma.${modelName}Delegate, { ${fields.map((f) => `${f}: ${inferFieldType(f)}`).join('; ')} } | null>(
|
|
152
|
-
'find${modelName}ById',
|
|
153
|
-
(model) =>
|
|
154
|
-
model.findFirst({
|
|
155
|
-
where: { id },
|
|
156
|
-
select: { ${fields.map((f) => `${f}: true`).join(', ')} },
|
|
157
|
-
}),
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
\`\`\`
|
|
161
|
-
|
|
162
|
-
### findMany query
|
|
163
|
-
\`\`\`typescript
|
|
164
|
-
export function findAll${modelName}sQuery(skip = 0, take = 20) {
|
|
165
|
-
return query<Prisma.${modelName}Delegate, Array<{ ${fields.map((f) => `${f}: ${inferFieldType(f)}`).join('; ')} }>>(
|
|
166
|
-
'findAll${modelName}s',
|
|
167
|
-
(model) =>
|
|
168
|
-
model.findMany({
|
|
169
|
-
skip,
|
|
170
|
-
take,
|
|
171
|
-
select: { ${fields.map((f) => `${f}: true`).join(', ')} },
|
|
172
|
-
orderBy: { ${fields.includes('createdAt') ? 'createdAt' : fields[0]}: 'desc' },
|
|
173
|
-
}),
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
\`\`\`
|
|
177
|
-
|
|
178
|
-
### count query
|
|
179
|
-
\`\`\`typescript
|
|
180
|
-
export function count${modelName}sQuery() {
|
|
181
|
-
return query<Prisma.${modelName}Delegate, number>(
|
|
182
|
-
'count${modelName}s',
|
|
183
|
-
(model) => model.count(),
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
\`\`\`
|
|
187
|
-
|
|
188
|
-
### Service usage
|
|
189
|
-
\`\`\`typescript
|
|
190
|
-
// In a service method:
|
|
191
|
-
const item = await this._${lowerFirst(modelName)}Repository.execute(find${modelName}ByIdQuery(id));
|
|
192
|
-
const items = await this._${lowerFirst(modelName)}Repository.execute(findAll${modelName}sQuery(0, 50));
|
|
193
|
-
const total = await this._${lowerFirst(modelName)}Repository.execute(count${modelName}sQuery());
|
|
194
|
-
\`\`\`
|
|
195
|
-
`;
|
|
196
|
-
exports.QUERY_PATTERN_WITH_MODEL = QUERY_PATTERN_WITH_MODEL;
|
|
197
|
-
function inferFieldType(fieldName) {
|
|
198
|
-
if (fieldName === 'id')
|
|
199
|
-
return 'string';
|
|
200
|
-
if (fieldName.endsWith('Id'))
|
|
201
|
-
return 'string';
|
|
202
|
-
if (fieldName.endsWith('At') || fieldName === 'createdAt' || fieldName === 'updatedAt')
|
|
203
|
-
return 'Date';
|
|
204
|
-
if (fieldName.startsWith('is') || fieldName.startsWith('has'))
|
|
205
|
-
return 'boolean';
|
|
206
|
-
if (fieldName === 'count' || fieldName === 'quantity' || fieldName === 'amount' || fieldName === 'order')
|
|
207
|
-
return 'number';
|
|
208
|
-
if (fieldName === 'email' || fieldName === 'name' || fieldName === 'title' || fieldName === 'description')
|
|
209
|
-
return 'string';
|
|
210
|
-
return 'unknown';
|
|
211
|
-
}
|
|
212
|
-
function lowerFirst(str) {
|
|
213
|
-
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
214
|
-
}
|
|
215
|
-
//# sourceMappingURL=queryPattern.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static knowledge content for the Archipel repository class pattern.
|
|
3
|
-
* Returned by the get-repository-pattern tool.
|
|
4
|
-
*/
|
|
5
|
-
export declare const REPOSITORY_PATTERN_KNOWLEDGE = "# Archipel Repository Pattern\n\n## Overview\n\nEvery Prisma model gets a dedicated **Repository class** extending `RepositoryBase`.\nRepositories are the ONLY code that touches Prisma delegates. Services never call\nPrisma directly \u2014 they call `repository.execute(someQuery(...))` or\n`repository.executeTransactional(someTxQuery(...))`.\n\n## RepositoryBase Signature\n\n```typescript\nimport { RepositoryBase } from '@breadstone/archipel-platform-database';\n\nexport abstract class RepositoryBase<\n TDelegate extends Record<RepositoryOperations, (args: any) => Promise<any>>,\n TArgs extends Record<RepositoryOperations, unknown>,\n TReturn extends Record<RepositoryOperations, unknown>,\n TEntity = unknown\n>\n```\n\n### Generic Parameters\n\n| Param | Purpose | Example |\n|-------|---------|---------|\n| `TDelegate` | Prisma delegate type from generated client | `Prisma.UserDelegate` |\n| `TArgs` | Argument shapes for each operation | `Prisma.UserFindManyArgs`, etc. |\n| `TReturn` | Return shapes for each operation | `User`, `User[]`, etc. |\n| `TEntity` | Domain entity interface (optional) | `IUserEntity` |\n\n### Helper Types\n\n```typescript\nimport { DelegateArgs, DelegateReturnTypes } from '@breadstone/archipel-platform-database';\n\n// These extract args and return types from a delegate automatically:\ntype UserArgs = DelegateArgs<Prisma.UserDelegate>;\ntype UserReturns = DelegateReturnTypes<Prisma.UserDelegate>;\n```\n\n## How to Create a Repository\n\n### Step 1: Create the repository class\n\n```typescript\n// repositories/UserRepository.ts\nimport { Injectable } from '@nestjs/common';\nimport { Prisma } from '@prisma/client';\nimport {\n DatabaseService,\n DelegateArgs,\n DelegateReturnTypes,\n RepositoryBase,\n} from '@breadstone/archipel-platform-database';\n\n@Injectable()\nexport class UserRepository extends RepositoryBase<\n Prisma.UserDelegate,\n DelegateArgs<Prisma.UserDelegate>,\n DelegateReturnTypes<Prisma.UserDelegate>,\n IUserEntity\n> {\n\n // #region Ctor\n\n public constructor(db: DatabaseService) {\n super(db, db.client.user);\n }\n\n // #endregion\n\n}\n```\n\nThe constructor receives `DatabaseService` and passes both the service and the\nPrisma delegate (`db.client.user`) to the base class.\n\n### Step 2: Register as a provider in a module\n\n```typescript\n@Module({\n imports: [DatabaseModule.register()],\n providers: [UserRepository, UserService],\n exports: [UserService],\n})\nexport class UserModule {}\n```\n\n### Step 3: Inject into a service\n\n```typescript\n@Injectable()\nexport class UserService {\n\n // #region Fields\n\n private readonly _userRepository: UserRepository;\n\n // #endregion\n\n // #region Ctor\n\n public constructor(userRepository: UserRepository) {\n this._userRepository = userRepository;\n }\n\n // #endregion\n\n // #region Methods\n\n public async findById(id: string): Promise<IUserEntity | null> {\n return this._userRepository.execute(findUserByIdQuery(id));\n }\n\n public async findAll(skip = 0, take = 20): Promise<IUserEntity[]> {\n return this._userRepository.execute(findAllUsersQuery(skip, take));\n }\n\n // #endregion\n\n}\n```\n\n## Key Methods on RepositoryBase\n\n### execute(query)\n\nPrimary method for data access. Delegates to a query object.\n\n```typescript\npublic execute<TResult>(query: IRepositoryQuery<TDelegate, TResult>): Promise<TResult>\n```\n\n### executeTransactional(query)\n\nFor multi-model operations within a transaction.\n\n```typescript\npublic executeTransactional<TResult>(query: ITransactionalRepositoryQuery<TResult>): Promise<TResult>\n```\n\n### Direct Methods (for legacy or internal use only)\n\nThe base class also exposes `findUnique`, `findMany`, `findFirst`, `create`,\n`createMany`, `update`, `updateMany`, `upsert`, `delete`, `deleteMany`,\n`aggregate`, `count`, `groupBy`, `merge`.\n\n**Important:** New code should use `execute(query)` exclusively.\nDirect method calls are available but violate the query pattern convention.\n\n### findMany with Pagination\n\n```typescript\n// Direct method (legacy)\nconst results = await this._repository.findMany(args, { page: 1, perPage: 20 });\n```\n\n## Error Handling\n\nAll Prisma errors are caught by the base class `tryCatch` wrapper and re-thrown\nas `RepositoryError`:\n\n- `PrismaClientKnownRequestError` \u2192 `RepositoryError` with code `'R_KNOWN'`\n- `PrismaClientUnknownRequestError` \u2192 `RepositoryError` with code `'R_UNKNOWN'`\n- Other errors are re-thrown unchanged\n\nThe global `RepositoryExceptionFilter` catches `RepositoryError` and returns\nHTTP 500 with a structured envelope.\n\n## Query Integration\n\nRepositories work with query factories from the query pattern:\n\n```typescript\n// queries/findUserByIdQuery.ts\nimport { Prisma } from '@prisma/client';\nimport { query } from '@breadstone/archipel-platform-database';\n\nexport function findUserByIdQuery(id: string) {\n return query<Prisma.UserDelegate, IUserEntity | null>(\n 'findUserById',\n (model) => model.findFirst({\n where: { id },\n select: { id: true, email: true, name: true, createdAt: true },\n }),\n );\n}\n\n// Service usage:\nconst user = await this._userRepository.execute(findUserByIdQuery(id));\n```\n\n## Rules\n\n1. **One repository per Prisma model** \u2014 e.g. `UserRepository`, `OrderRepository`.\n2. **Constructor receives `DatabaseService`** and passes the delegate via `db.client.<model>`.\n3. **Use `DelegateArgs` and `DelegateReturnTypes`** helper types for the RepositoryBase generics.\n4. **New code uses `execute(query)`** \u2014 never direct calls like `repository.findFirst()` from services.\n5. **Register as provider** in the feature module, import `DatabaseModule.register()`.\n6. **Repositories are `@Injectable()`** \u2014 they participate in NestJS DI.\n7. **Domain entity interface as fourth generic** (`TEntity`) is optional but recommended.\n";
|
|
6
|
-
export declare const REPOSITORY_PATTERN_WITH_MODEL: (modelName: string, fields: string[]) => string;
|