@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.
Files changed (136) hide show
  1. package/data/guides/cryptography-and-otp.md +2 -2
  2. package/data/guides/database-setup.md +4 -3
  3. package/data/guides/email-templates.md +3 -3
  4. package/data/guides/getting-started.md +6 -6
  5. package/data/guides/resource-management.md +9 -9
  6. package/data/packages/platform-blob-storage/api/Variable.AWS_S3_PROVIDER_OPTIONS.md +1 -1
  7. package/data/packages/platform-blob-storage/api/Variable.AZURE_BLOB_PROVIDER_OPTIONS.md +1 -1
  8. package/data/packages/platform-blob-storage/api/Variable.BLOB_PROVIDER.md +1 -1
  9. package/data/packages/platform-blob-storage/api/Variable.VERCEL_BLOB_PROVIDER_OPTIONS.md +1 -1
  10. package/data/packages/platform-core/api/Class.ErrorTemplateService.md +1 -1
  11. package/data/packages/platform-core/api/Class.HostService.md +1 -1
  12. package/data/packages/platform-core/api/Variable.ID_GENERATOR_TOKEN.md +1 -1
  13. package/data/packages/platform-core/api/index.md +0 -27
  14. package/data/packages/platform-core/index.md +7 -4
  15. package/data/packages/platform-cryptography/api/Class.BcryptService.md +4 -4
  16. package/data/packages/platform-cryptography/api/Class.OtpService.md +6 -6
  17. package/data/packages/platform-cryptography/api/Variable.BCRYPT_OPTIONS.md +2 -2
  18. package/data/packages/platform-cryptography/api/Variable.MAX_BCRYPT_PASSWORD_BYTES.md +1 -1
  19. package/data/packages/platform-cryptography/api/Variable.MIN_BCRYPT_ROUNDS.md +1 -1
  20. package/data/packages/platform-cryptography/api/Variable.OTP_OPTIONS.md +2 -2
  21. package/data/packages/platform-cryptography/api/Variable.OTP_SERVICE_TOKEN.md +2 -2
  22. package/data/packages/platform-cryptography/api/Variable.TOTP_EPOCH_TOLERANCE.md +1 -1
  23. package/data/packages/platform-cryptography/api/index.md +3 -3
  24. package/data/packages/platform-documents/api/Class.BaseDocumentRenderer.md +32 -1
  25. package/data/packages/platform-documents/api/Class.DocumentEngine.md +4 -4
  26. package/data/packages/platform-documents/api/Class.DocumentModule.md +2 -2
  27. package/data/packages/platform-documents/api/Class.DocxDocumentRenderer2.md +333 -0
  28. package/data/packages/platform-documents/api/Class.PdfDocumentRenderer.md +355 -0
  29. package/data/packages/platform-documents/api/Interface.IDocumentModuleOptions.md +31 -5
  30. package/data/packages/platform-documents/api/Variable.DOCUMENT_MODULE_OPTIONS.md +1 -1
  31. package/data/packages/platform-documents/api/Variable.DOCUMENT_PARSER_TOKEN.md +1 -1
  32. package/data/packages/platform-documents/api/Variable.DOCUMENT_RENDERER_TOKEN.md +1 -1
  33. package/data/packages/platform-documents/api/Variable.IMAGE_PROCESSOR_TOKEN.md +1 -1
  34. package/data/packages/platform-documents/api/index.md +2 -0
  35. package/data/packages/platform-esigning/api/Class.EsigningClientPort.md +1 -1
  36. package/data/packages/platform-health/index.md +128 -0
  37. package/data/packages/platform-mailing/api/Class.DeliveryStrategyBase.md +0 -1
  38. package/data/packages/platform-mailing/api/Class.MailModule.md +1 -1
  39. package/data/packages/platform-mailing/api/Class.TemplateFetchStrategyBase.md +0 -5
  40. package/data/packages/platform-mailing/api/Variable.SMTP_CONFIG_ENTRIES.md +14 -0
  41. package/data/packages/platform-mailing/api/Variable.SMTP_HOST.md +14 -0
  42. package/data/packages/platform-mailing/api/Variable.SMTP_PASSWORD.md +14 -0
  43. package/data/packages/platform-mailing/api/Variable.SMTP_PORT.md +14 -0
  44. package/data/packages/platform-mailing/api/Variable.SMTP_SECURE.md +14 -0
  45. package/data/packages/platform-mailing/api/Variable.SMTP_USER.md +14 -0
  46. package/data/packages/platform-mailing/api/index.md +6 -3
  47. package/data/packages/platform-mapping/index.md +121 -0
  48. package/data/packages/platform-mcp/api/Variable.MCP_MODULE_OPTIONS.md +1 -1
  49. package/data/packages/platform-openapi/api/Class.SwaggerMultiDocumentService.md +4 -4
  50. package/data/packages/platform-resources/index.md +135 -0
  51. package/data/packages/platform-telemetry/api/Variable.TELEMETRY_ENABLED.md +1 -1
  52. package/data/packages/platform-telemetry/api/Variable.TELEMETRY_FACADE.md +1 -1
  53. package/data/packages/platform-telemetry/api/Variable.TELEMETRY_OPTIONS.md +1 -1
  54. package/{src/knowledge/configPattern.js → data/patterns/config-pattern.md} +44 -47
  55. package/{src/knowledge/dtoPattern.js → data/patterns/dto-pattern.md} +58 -61
  56. package/{src/knowledge/errorHandlingPattern.js → data/patterns/error-handling-pattern.md} +35 -38
  57. package/{src/knowledge/guardPattern.js → data/patterns/guard-pattern.md} +35 -38
  58. package/{src/knowledge/mappingPattern.js → data/patterns/mapping-pattern.md} +43 -144
  59. package/data/patterns/module-pattern.md +182 -0
  60. package/data/patterns/query-pattern.md +137 -0
  61. package/data/patterns/repository-pattern.md +208 -0
  62. package/{src/knowledge/testingPattern.js → data/patterns/testing-pattern.md} +37 -40
  63. package/package.json +1 -1
  64. package/src/PatternsLoader.d.ts +12 -0
  65. package/src/PatternsLoader.js +65 -0
  66. package/src/generators/mappingPatternGenerator.d.ts +5 -0
  67. package/src/generators/mappingPatternGenerator.js +107 -0
  68. package/src/generators/modulePatternGenerator.d.ts +5 -0
  69. package/src/generators/modulePatternGenerator.js +107 -0
  70. package/src/generators/queryPatternGenerator.d.ts +4 -0
  71. package/src/generators/queryPatternGenerator.js +83 -0
  72. package/src/generators/repositoryPatternGenerator.d.ts +5 -0
  73. package/src/generators/repositoryPatternGenerator.js +165 -0
  74. package/src/main.js +15 -9
  75. package/src/models/IPatternDoc.d.ts +15 -0
  76. package/src/models/IPatternDoc.js +3 -0
  77. package/src/tools/registerGetConfigPatternTool.d.ts +2 -1
  78. package/src/tools/registerGetConfigPatternTool.js +4 -3
  79. package/src/tools/registerGetDtoPatternTool.d.ts +2 -1
  80. package/src/tools/registerGetDtoPatternTool.js +4 -3
  81. package/src/tools/registerGetErrorHandlingPatternTool.d.ts +2 -1
  82. package/src/tools/registerGetErrorHandlingPatternTool.js +4 -3
  83. package/src/tools/registerGetGuardPatternTool.d.ts +2 -1
  84. package/src/tools/registerGetGuardPatternTool.js +4 -3
  85. package/src/tools/registerGetMappingPatternTool.d.ts +2 -1
  86. package/src/tools/registerGetMappingPatternTool.js +5 -4
  87. package/src/tools/registerGetModulePatternTool.d.ts +2 -1
  88. package/src/tools/registerGetModulePatternTool.js +5 -4
  89. package/src/tools/registerGetQueryPatternTool.d.ts +2 -1
  90. package/src/tools/registerGetQueryPatternTool.js +5 -4
  91. package/src/tools/registerGetRepositoryPatternTool.d.ts +2 -1
  92. package/src/tools/registerGetRepositoryPatternTool.js +5 -4
  93. package/src/tools/registerGetTestingPatternTool.d.ts +2 -1
  94. package/src/tools/registerGetTestingPatternTool.js +4 -3
  95. package/data/packages/platform-core/api/Class.BlobResourceStrategy.md +0 -195
  96. package/data/packages/platform-core/api/Class.EmbeddedResourceStrategy.md +0 -215
  97. package/data/packages/platform-core/api/Class.FileResourceStrategy.md +0 -192
  98. package/data/packages/platform-core/api/Class.HealthModule.md +0 -42
  99. package/data/packages/platform-core/api/Class.HealthOrchestrator.md +0 -64
  100. package/data/packages/platform-core/api/Class.MappingBuilder.md +0 -110
  101. package/data/packages/platform-core/api/Class.MappingModule.md +0 -46
  102. package/data/packages/platform-core/api/Class.MappingNotRegisteredError.md +0 -56
  103. package/data/packages/platform-core/api/Class.MappingProfileBase.md +0 -52
  104. package/data/packages/platform-core/api/Class.MappingService.md +0 -284
  105. package/data/packages/platform-core/api/Class.ResourceManager.md +0 -565
  106. package/data/packages/platform-core/api/Class.ResourceModule.md +0 -46
  107. package/data/packages/platform-core/api/Class.TypeMappingNotRegisteredError.md +0 -57
  108. package/data/packages/platform-core/api/Function.createMappingKey.md +0 -39
  109. package/data/packages/platform-core/api/Interface.IBlobResourceStrategyConfig.md +0 -28
  110. package/data/packages/platform-core/api/Interface.IBlobServiceAdapter.md +0 -40
  111. package/data/packages/platform-core/api/Interface.IFileResourceStrategyConfig.md +0 -72
  112. package/data/packages/platform-core/api/Interface.IHealthCheckResult.md +0 -46
  113. package/data/packages/platform-core/api/Interface.IHealthIndicator.md +0 -41
  114. package/data/packages/platform-core/api/Interface.IMappingBuilder.md +0 -76
  115. package/data/packages/platform-core/api/Interface.IMappingKey.md +0 -58
  116. package/data/packages/platform-core/api/Interface.IMappingProfile.md +0 -32
  117. package/data/packages/platform-core/api/Interface.IResourceManagerConfig.md +0 -89
  118. package/data/packages/platform-core/api/Interface.IResourceMetadata.md +0 -94
  119. package/data/packages/platform-core/api/Interface.IResourceResult.md +0 -34
  120. package/data/packages/platform-core/api/Interface.IResourceStrategy.md +0 -134
  121. package/data/packages/platform-core/api/Variable.HEALTH_INDICATORS_TOKEN.md +0 -14
  122. package/data/packages/platform-mailing/api/Class.BlobTemplateFetchStrategy.md +0 -60
  123. package/data/packages/platform-mailing/api/Class.FileTemplateFetchStrategy.md +0 -58
  124. package/data/packages/platform-mailing/api/Class.LogDeliveryStrategy.md +0 -71
  125. package/src/knowledge/configPattern.d.ts +0 -5
  126. package/src/knowledge/dtoPattern.d.ts +0 -5
  127. package/src/knowledge/errorHandlingPattern.d.ts +0 -5
  128. package/src/knowledge/guardPattern.d.ts +0 -5
  129. package/src/knowledge/mappingPattern.d.ts +0 -6
  130. package/src/knowledge/modulePattern.d.ts +0 -6
  131. package/src/knowledge/modulePattern.js +0 -283
  132. package/src/knowledge/queryPattern.d.ts +0 -6
  133. package/src/knowledge/queryPattern.js +0 -215
  134. package/src/knowledge/repositoryPattern.d.ts +0 -6
  135. package/src/knowledge/repositoryPattern.js +0 -367
  136. 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;