@engjts/nexus 0.1.8 → 0.1.9
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/package.json +1 -1
- package/BENCHMARK_REPORT.md +0 -343
- package/documentation/01-getting-started.md +0 -240
- package/documentation/02-context.md +0 -335
- package/documentation/03-routing.md +0 -397
- package/documentation/04-middleware.md +0 -483
- package/documentation/05-validation.md +0 -514
- package/documentation/06-error-handling.md +0 -465
- package/documentation/07-performance.md +0 -364
- package/documentation/08-adapters.md +0 -470
- package/documentation/09-api-reference.md +0 -548
- package/documentation/10-examples.md +0 -582
- package/documentation/11-deployment.md +0 -477
- package/documentation/12-sentry.md +0 -620
- package/documentation/13-sentry-data-storage.md +0 -996
- package/documentation/14-sentry-data-reference.md +0 -457
- package/documentation/15-sentry-summary.md +0 -409
- package/documentation/16-alerts-system.md +0 -745
- package/documentation/17-alert-adapters.md +0 -696
- package/documentation/18-alerts-implementation-summary.md +0 -385
- package/documentation/19-class-based-routing.md +0 -840
- package/documentation/20-websocket-realtime.md +0 -813
- package/documentation/21-cache-system.md +0 -510
- package/documentation/22-job-queue.md +0 -772
- package/documentation/23-sentry-plugin.md +0 -551
- package/documentation/24-testing-utilities.md +0 -1287
- package/documentation/25-api-versioning.md +0 -533
- package/documentation/26-context-store.md +0 -607
- package/documentation/27-dependency-injection.md +0 -329
- package/documentation/28-lifecycle-hooks.md +0 -521
- package/documentation/29-package-structure.md +0 -196
- package/documentation/30-plugin-system.md +0 -414
- package/documentation/31-jwt-authentication.md +0 -597
- package/documentation/32-cli.md +0 -268
- package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
- package/documentation/ALERTS-INDEX.md +0 -330
- package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
- package/documentation/README.md +0 -178
- package/documentation/index.html +0 -34
- package/modern_framework_paper.md +0 -1870
- package/public/css/style.css +0 -87
- package/public/index.html +0 -34
- package/public/js/app.js +0 -27
- package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
- package/src/advanced/cache/MultiTierCache.ts +0 -194
- package/src/advanced/cache/RedisCacheStore.ts +0 -341
- package/src/advanced/cache/index.ts +0 -5
- package/src/advanced/cache/types.ts +0 -40
- package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
- package/src/advanced/graphql/index.ts +0 -22
- package/src/advanced/graphql/server.ts +0 -252
- package/src/advanced/graphql/types.ts +0 -42
- package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
- package/src/advanced/jobs/JobQueue.ts +0 -556
- package/src/advanced/jobs/RedisQueueStore.ts +0 -367
- package/src/advanced/jobs/index.ts +0 -5
- package/src/advanced/jobs/types.ts +0 -70
- package/src/advanced/observability/APMManager.ts +0 -163
- package/src/advanced/observability/AlertManager.ts +0 -109
- package/src/advanced/observability/MetricRegistry.ts +0 -151
- package/src/advanced/observability/ObservabilityCenter.ts +0 -304
- package/src/advanced/observability/StructuredLogger.ts +0 -154
- package/src/advanced/observability/TracingManager.ts +0 -117
- package/src/advanced/observability/adapters.ts +0 -304
- package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
- package/src/advanced/observability/index.ts +0 -11
- package/src/advanced/observability/types.ts +0 -174
- package/src/advanced/playground/extractPathParams.ts +0 -6
- package/src/advanced/playground/generateFieldExample.ts +0 -31
- package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
- package/src/advanced/playground/generateSummary.ts +0 -19
- package/src/advanced/playground/getTagFromPath.ts +0 -9
- package/src/advanced/playground/index.ts +0 -8
- package/src/advanced/playground/playground.ts +0 -250
- package/src/advanced/playground/types.ts +0 -49
- package/src/advanced/playground/zodToExample.ts +0 -16
- package/src/advanced/playground/zodToParams.ts +0 -15
- package/src/advanced/postman/buildAuth.ts +0 -31
- package/src/advanced/postman/buildBody.ts +0 -15
- package/src/advanced/postman/buildQueryParams.ts +0 -27
- package/src/advanced/postman/buildRequestItem.ts +0 -36
- package/src/advanced/postman/buildResponses.ts +0 -11
- package/src/advanced/postman/buildUrl.ts +0 -33
- package/src/advanced/postman/capitalize.ts +0 -4
- package/src/advanced/postman/generateCollection.ts +0 -59
- package/src/advanced/postman/generateEnvironment.ts +0 -34
- package/src/advanced/postman/generateExampleFromZod.ts +0 -21
- package/src/advanced/postman/generateFieldExample.ts +0 -45
- package/src/advanced/postman/generateName.ts +0 -20
- package/src/advanced/postman/generateUUID.ts +0 -11
- package/src/advanced/postman/getTagFromPath.ts +0 -10
- package/src/advanced/postman/index.ts +0 -28
- package/src/advanced/postman/postman.ts +0 -156
- package/src/advanced/postman/slugify.ts +0 -7
- package/src/advanced/postman/types.ts +0 -140
- package/src/advanced/realtime/index.ts +0 -18
- package/src/advanced/realtime/websocket.ts +0 -231
- package/src/advanced/sentry/index.ts +0 -1236
- package/src/advanced/sentry/types.ts +0 -355
- package/src/advanced/static/generateDirectoryListing.ts +0 -47
- package/src/advanced/static/generateETag.ts +0 -7
- package/src/advanced/static/getMimeType.ts +0 -9
- package/src/advanced/static/index.ts +0 -32
- package/src/advanced/static/isSafePath.ts +0 -13
- package/src/advanced/static/publicDir.ts +0 -21
- package/src/advanced/static/serveStatic.ts +0 -225
- package/src/advanced/static/spa.ts +0 -24
- package/src/advanced/static/types.ts +0 -159
- package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
- package/src/advanced/swagger/buildOperation.ts +0 -61
- package/src/advanced/swagger/buildParameters.ts +0 -61
- package/src/advanced/swagger/buildRequestBody.ts +0 -21
- package/src/advanced/swagger/buildResponses.ts +0 -54
- package/src/advanced/swagger/capitalize.ts +0 -5
- package/src/advanced/swagger/convertPath.ts +0 -9
- package/src/advanced/swagger/createSwagger.ts +0 -12
- package/src/advanced/swagger/generateOperationId.ts +0 -21
- package/src/advanced/swagger/generateSpec.ts +0 -105
- package/src/advanced/swagger/generateSummary.ts +0 -24
- package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
- package/src/advanced/swagger/generateThemeCss.ts +0 -53
- package/src/advanced/swagger/index.ts +0 -25
- package/src/advanced/swagger/swagger.ts +0 -237
- package/src/advanced/swagger/types.ts +0 -206
- package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
- package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
- package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
- package/src/advanced/testing/factory.ts +0 -509
- package/src/advanced/testing/harness.ts +0 -612
- package/src/advanced/testing/index.ts +0 -430
- package/src/advanced/testing/load-test.ts +0 -618
- package/src/advanced/testing/mock-server.ts +0 -498
- package/src/advanced/testing/mock.ts +0 -670
- package/src/cli/bin.ts +0 -9
- package/src/cli/cli.ts +0 -158
- package/src/cli/commands/add.ts +0 -178
- package/src/cli/commands/build.ts +0 -73
- package/src/cli/commands/create.ts +0 -166
- package/src/cli/commands/dev.ts +0 -85
- package/src/cli/commands/generate.ts +0 -99
- package/src/cli/commands/help.ts +0 -95
- package/src/cli/commands/init.ts +0 -91
- package/src/cli/commands/version.ts +0 -38
- package/src/cli/index.ts +0 -6
- package/src/cli/templates/generators.ts +0 -359
- package/src/cli/templates/index.ts +0 -680
- package/src/cli/utils/exec.ts +0 -52
- package/src/cli/utils/file-system.ts +0 -78
- package/src/cli/utils/logger.ts +0 -111
- package/src/core/adapter.ts +0 -88
- package/src/core/application.ts +0 -1453
- package/src/core/context-pool.ts +0 -79
- package/src/core/context.ts +0 -856
- package/src/core/index.ts +0 -94
- package/src/core/middleware.ts +0 -272
- package/src/core/performance/buffer-pool.ts +0 -108
- package/src/core/performance/middleware-optimizer.ts +0 -162
- package/src/core/plugin/PluginManager.ts +0 -435
- package/src/core/plugin/builder.ts +0 -358
- package/src/core/plugin/index.ts +0 -50
- package/src/core/plugin/types.ts +0 -214
- package/src/core/router/file-router.ts +0 -623
- package/src/core/router/index.ts +0 -260
- package/src/core/router/radix-tree.ts +0 -242
- package/src/core/serializer.ts +0 -397
- package/src/core/store/index.ts +0 -30
- package/src/core/store/registry.ts +0 -178
- package/src/core/store/request-store.ts +0 -240
- package/src/core/store/types.ts +0 -233
- package/src/core/types.ts +0 -616
- package/src/database/adapter.ts +0 -35
- package/src/database/adapters/index.ts +0 -1
- package/src/database/adapters/mysql.ts +0 -669
- package/src/database/database.ts +0 -70
- package/src/database/dialect.ts +0 -388
- package/src/database/index.ts +0 -12
- package/src/database/migrations.ts +0 -86
- package/src/database/optimizer.ts +0 -125
- package/src/database/query-builder.ts +0 -404
- package/src/database/realtime.ts +0 -53
- package/src/database/schema.ts +0 -71
- package/src/database/transactions.ts +0 -56
- package/src/database/types.ts +0 -87
- package/src/deployment/cluster.ts +0 -471
- package/src/deployment/config.ts +0 -454
- package/src/deployment/docker.ts +0 -599
- package/src/deployment/graceful-shutdown.ts +0 -373
- package/src/deployment/index.ts +0 -56
- package/src/index.ts +0 -281
- package/src/security/adapter.ts +0 -318
- package/src/security/auth/JWTPlugin.ts +0 -234
- package/src/security/auth/JWTProvider.ts +0 -316
- package/src/security/auth/adapter.ts +0 -12
- package/src/security/auth/jwt.ts +0 -234
- package/src/security/auth/middleware.ts +0 -188
- package/src/security/csrf.ts +0 -220
- package/src/security/headers.ts +0 -108
- package/src/security/index.ts +0 -60
- package/src/security/rate-limit/adapter.ts +0 -7
- package/src/security/rate-limit/memory.ts +0 -108
- package/src/security/rate-limit/middleware.ts +0 -181
- package/src/security/sanitization.ts +0 -75
- package/src/security/types.ts +0 -240
- package/src/security/utils.ts +0 -52
- package/tsconfig.json +0 -39
|
@@ -1,470 +0,0 @@
|
|
|
1
|
-
# Adapters & Extensibility
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Nexus uses the **Adapter Pattern** to enable extensibility. All core components can be swapped out or extended without modifying the framework itself.
|
|
6
|
-
|
|
7
|
-
## Why Adapters?
|
|
8
|
-
|
|
9
|
-
- ✅ **Pluggable Architecture** - Swap implementations easily
|
|
10
|
-
- ✅ **Future-Proof** - Add features without breaking changes
|
|
11
|
-
- ✅ **Framework Evolution** - Integrate new tools seamlessly
|
|
12
|
-
- ✅ **Custom Implementations** - Build your own adapters
|
|
13
|
-
|
|
14
|
-
## Built-in Adapters
|
|
15
|
-
|
|
16
|
-
### RouterAdapter
|
|
17
|
-
|
|
18
|
-
Interface for custom routing implementations:
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
interface RouterAdapter {
|
|
22
|
-
addRoute(method: string, path: string, handler: Handler): void;
|
|
23
|
-
match(method: string, path: string): RouteMatch | null;
|
|
24
|
-
getRoutes(): Array<{ method: string; path: string }>;
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### ContextAdapter
|
|
29
|
-
|
|
30
|
-
Interface for context creation strategies:
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
interface ContextAdapter {
|
|
34
|
-
createContext(req: IncomingMessage): Promise<Context>;
|
|
35
|
-
resetContext(ctx: Context, req: IncomingMessage): Promise<Context>;
|
|
36
|
-
parseBody(req: IncomingMessage): Promise<any>;
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### ValidationAdapter
|
|
41
|
-
|
|
42
|
-
Interface for schema validation libraries:
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
interface ValidationAdapter {
|
|
46
|
-
validate<T>(schema: any, data: unknown): Promise<T>;
|
|
47
|
-
isEnabled(): boolean;
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Using Adapters
|
|
52
|
-
|
|
53
|
-
### Register an Adapter
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { createApp } from './nexus';
|
|
57
|
-
|
|
58
|
-
const app = createApp();
|
|
59
|
-
|
|
60
|
-
// Register custom adapter
|
|
61
|
-
app.adapter('logger', customLoggerAdapter);
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Retrieve an Adapter
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const logger = app.getAdapter<LoggerAdapter>('logger');
|
|
68
|
-
logger.info('Application started');
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Creating Custom Adapters
|
|
72
|
-
|
|
73
|
-
### Logger Adapter
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import { LoggerAdapter } from './nexus';
|
|
77
|
-
|
|
78
|
-
class ConsoleLogger implements LoggerAdapter {
|
|
79
|
-
info(message: string, meta?: any) {
|
|
80
|
-
console.log(`[INFO] ${message}`, meta || '');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
warn(message: string, meta?: any) {
|
|
84
|
-
console.warn(`[WARN] ${message}`, meta || '');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
error(message: string, error?: Error, meta?: any) {
|
|
88
|
-
console.error(`[ERROR] ${message}`, error, meta || '');
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
debug(message: string, meta?: any) {
|
|
92
|
-
if (process.env.DEBUG) {
|
|
93
|
-
console.debug(`[DEBUG] ${message}`, meta || '');
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Register
|
|
99
|
-
app.adapter('logger', new ConsoleLogger());
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Pino Logger Adapter
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import pino from 'pino';
|
|
106
|
-
import { LoggerAdapter } from './nexus';
|
|
107
|
-
|
|
108
|
-
class PinoLogger implements LoggerAdapter {
|
|
109
|
-
private logger = pino({
|
|
110
|
-
level: process.env.LOG_LEVEL || 'info'
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
info(message: string, meta?: any) {
|
|
114
|
-
this.logger.info(meta, message);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
warn(message: string, meta?: any) {
|
|
118
|
-
this.logger.warn(meta, message);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
error(message: string, error?: Error, meta?: any) {
|
|
122
|
-
this.logger.error({ err: error, ...meta }, message);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
debug(message: string, meta?: any) {
|
|
126
|
-
this.logger.debug(meta, message);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
app.adapter('logger', new PinoLogger());
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Cache Adapter (Redis)
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
import { createClient } from 'redis';
|
|
137
|
-
import { CacheAdapter } from './nexus';
|
|
138
|
-
|
|
139
|
-
class RedisCache implements CacheAdapter {
|
|
140
|
-
private client = createClient();
|
|
141
|
-
|
|
142
|
-
async get<T>(key: string): Promise<T | null> {
|
|
143
|
-
const value = await this.client.get(key);
|
|
144
|
-
return value ? JSON.parse(value) : null;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
|
|
148
|
-
const serialized = JSON.stringify(value);
|
|
149
|
-
if (ttl) {
|
|
150
|
-
await this.client.setEx(key, ttl, serialized);
|
|
151
|
-
} else {
|
|
152
|
-
await this.client.set(key, serialized);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async delete(key: string): Promise<void> {
|
|
157
|
-
await this.client.del(key);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async clear(): Promise<void> {
|
|
161
|
-
await this.client.flushDb();
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Usage
|
|
166
|
-
const cache = new RedisCache();
|
|
167
|
-
app.adapter('cache', cache);
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Session Adapter
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
import { SessionAdapter } from './nexus';
|
|
174
|
-
|
|
175
|
-
interface SessionData {
|
|
176
|
-
userId?: string;
|
|
177
|
-
createdAt: number;
|
|
178
|
-
expiresAt: number;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
class MemorySessionAdapter implements SessionAdapter {
|
|
182
|
-
private sessions = new Map<string, SessionData>();
|
|
183
|
-
|
|
184
|
-
async get(sessionId: string): Promise<SessionData | null> {
|
|
185
|
-
const session = this.sessions.get(sessionId);
|
|
186
|
-
if (!session) return null;
|
|
187
|
-
|
|
188
|
-
// Check expiration
|
|
189
|
-
if (Date.now() > session.expiresAt) {
|
|
190
|
-
this.sessions.delete(sessionId);
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return session;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async set(sessionId: string, data: SessionData): Promise<void> {
|
|
198
|
-
this.sessions.set(sessionId, data);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
async destroy(sessionId: string): Promise<void> {
|
|
202
|
-
this.sessions.delete(sessionId);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
app.adapter('session', new MemorySessionAdapter());
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
## Plugin System
|
|
210
|
-
|
|
211
|
-
### Create a Plugin
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
import { Plugin, Application } from './nexus';
|
|
215
|
-
|
|
216
|
-
const analyticsPlugin: Plugin = {
|
|
217
|
-
name: 'analytics',
|
|
218
|
-
version: '1.0.0',
|
|
219
|
-
|
|
220
|
-
install: (app: Application) => {
|
|
221
|
-
// Add middleware
|
|
222
|
-
app.use(async (ctx, next) => {
|
|
223
|
-
const start = Date.now();
|
|
224
|
-
const response = await next(ctx);
|
|
225
|
-
const duration = Date.now() - start;
|
|
226
|
-
|
|
227
|
-
// Track analytics
|
|
228
|
-
track('request', {
|
|
229
|
-
path: ctx.path,
|
|
230
|
-
method: ctx.method,
|
|
231
|
-
duration,
|
|
232
|
-
status: response.statusCode
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
return response;
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// Add custom routes
|
|
239
|
-
app.get('/_analytics', async (ctx) => {
|
|
240
|
-
return { stats: getAnalytics() };
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
// Use plugin
|
|
246
|
-
app.plugin(analyticsPlugin);
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Authentication Plugin
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
const authPlugin: Plugin = {
|
|
253
|
-
name: 'auth',
|
|
254
|
-
version: '1.0.0',
|
|
255
|
-
|
|
256
|
-
install: (app: Application) => {
|
|
257
|
-
// Register JWT adapter
|
|
258
|
-
app.adapter('jwt', new JWTAdapter({
|
|
259
|
-
secret: process.env.JWT_SECRET!,
|
|
260
|
-
expiresIn: '1h'
|
|
261
|
-
}));
|
|
262
|
-
|
|
263
|
-
// Add auth routes
|
|
264
|
-
app.post('/auth/login', loginHandler);
|
|
265
|
-
app.post('/auth/logout', logoutHandler);
|
|
266
|
-
app.post('/auth/refresh', refreshHandler);
|
|
267
|
-
|
|
268
|
-
// Add auth middleware factory
|
|
269
|
-
(app as any).requireAuth = () => authMiddleware;
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
app.plugin(authPlugin);
|
|
274
|
-
|
|
275
|
-
// Use the plugin
|
|
276
|
-
app.get('/protected', {
|
|
277
|
-
middlewares: [(app as any).requireAuth()],
|
|
278
|
-
handler: async (ctx) => {
|
|
279
|
-
return { user: ctx.user };
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
## Real-World Examples
|
|
285
|
-
|
|
286
|
-
### Database Adapter
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
interface DatabaseAdapter {
|
|
290
|
-
connect(): Promise<void>;
|
|
291
|
-
disconnect(): Promise<void>;
|
|
292
|
-
query<T>(sql: string, params?: any[]): Promise<T[]>;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
class PostgreSQLAdapter implements DatabaseAdapter {
|
|
296
|
-
private pool: Pool;
|
|
297
|
-
|
|
298
|
-
constructor(config: PoolConfig) {
|
|
299
|
-
this.pool = new Pool(config);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
async connect(): Promise<void> {
|
|
303
|
-
await this.pool.connect();
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
async disconnect(): Promise<void> {
|
|
307
|
-
await this.pool.end();
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
async query<T>(sql: string, params?: any[]): Promise<T[]> {
|
|
311
|
-
const result = await this.pool.query(sql, params);
|
|
312
|
-
return result.rows;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Register
|
|
317
|
-
const db = new PostgreSQLAdapter({
|
|
318
|
-
host: process.env.DB_HOST,
|
|
319
|
-
database: process.env.DB_NAME,
|
|
320
|
-
user: process.env.DB_USER,
|
|
321
|
-
password: process.env.DB_PASSWORD
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
app.adapter('database', db);
|
|
325
|
-
|
|
326
|
-
// Use in handlers
|
|
327
|
-
app.get('/users', async (ctx) => {
|
|
328
|
-
const db = app.getAdapter<DatabaseAdapter>('database')!;
|
|
329
|
-
const users = await db.query('SELECT * FROM users');
|
|
330
|
-
return { users };
|
|
331
|
-
});
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### Rate Limiter Adapter
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
interface RateLimiterAdapter {
|
|
338
|
-
check(key: string, limit: number, window: number): Promise<boolean>;
|
|
339
|
-
reset(key: string): Promise<void>;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
class RedisRateLimiter implements RateLimiterAdapter {
|
|
343
|
-
private client: RedisClientType;
|
|
344
|
-
|
|
345
|
-
async check(key: string, limit: number, window: number): Promise<boolean> {
|
|
346
|
-
const count = await this.client.incr(key);
|
|
347
|
-
|
|
348
|
-
if (count === 1) {
|
|
349
|
-
await this.client.expire(key, window);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
return count <= limit;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
async reset(key: string): Promise<void> {
|
|
356
|
-
await this.client.del(key);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
app.adapter('rateLimiter', new RedisRateLimiter());
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
## Adapter Registry
|
|
364
|
-
|
|
365
|
-
### Access the Registry
|
|
366
|
-
|
|
367
|
-
```typescript
|
|
368
|
-
import { AdapterRegistry } from './nexus';
|
|
369
|
-
|
|
370
|
-
const registry = new AdapterRegistry();
|
|
371
|
-
|
|
372
|
-
// Register adapters
|
|
373
|
-
registry.register('logger', loggerAdapter);
|
|
374
|
-
registry.register('cache', cacheAdapter);
|
|
375
|
-
registry.register('session', sessionAdapter);
|
|
376
|
-
|
|
377
|
-
// Retrieve adapters
|
|
378
|
-
const logger = registry.get<LoggerAdapter>('logger');
|
|
379
|
-
const cache = registry.get<CacheAdapter>('cache');
|
|
380
|
-
|
|
381
|
-
// Check if exists
|
|
382
|
-
if (registry.has('logger')) {
|
|
383
|
-
logger?.info('Logger is registered');
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// Remove adapter
|
|
387
|
-
registry.remove('cache');
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
## Best Practices
|
|
391
|
-
|
|
392
|
-
### ✅ DO: Define clear interfaces
|
|
393
|
-
|
|
394
|
-
```typescript
|
|
395
|
-
interface MetricsAdapter {
|
|
396
|
-
increment(metric: string, tags?: Record<string, string>): void;
|
|
397
|
-
gauge(metric: string, value: number, tags?: Record<string, string>): void;
|
|
398
|
-
timing(metric: string, duration: number, tags?: Record<string, string>): void;
|
|
399
|
-
}
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
### ✅ DO: Use dependency injection
|
|
403
|
-
|
|
404
|
-
```typescript
|
|
405
|
-
class UserService {
|
|
406
|
-
constructor(
|
|
407
|
-
private db: DatabaseAdapter,
|
|
408
|
-
private cache: CacheAdapter
|
|
409
|
-
) {}
|
|
410
|
-
|
|
411
|
-
async getUser(id: string) {
|
|
412
|
-
// Try cache first
|
|
413
|
-
const cached = await this.cache.get(`user:${id}`);
|
|
414
|
-
if (cached) return cached;
|
|
415
|
-
|
|
416
|
-
// Query database
|
|
417
|
-
const user = await this.db.query('SELECT * FROM users WHERE id = $1', [id]);
|
|
418
|
-
await this.cache.set(`user:${id}`, user, 300);
|
|
419
|
-
return user;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
### ✅ DO: Make adapters testable
|
|
425
|
-
|
|
426
|
-
```typescript
|
|
427
|
-
class MockCache implements CacheAdapter {
|
|
428
|
-
private store = new Map();
|
|
429
|
-
|
|
430
|
-
async get<T>(key: string): Promise<T | null> {
|
|
431
|
-
return this.store.get(key) || null;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
async set<T>(key: string, value: T): Promise<void> {
|
|
435
|
-
this.store.set(key, value);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
async delete(key: string): Promise<void> {
|
|
439
|
-
this.store.delete(key);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
async clear(): Promise<void> {
|
|
443
|
-
this.store.clear();
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Use in tests
|
|
448
|
-
const mockCache = new MockCache();
|
|
449
|
-
app.adapter('cache', mockCache);
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
## Future Adapters
|
|
453
|
-
|
|
454
|
-
The adapter pattern enables future phases:
|
|
455
|
-
|
|
456
|
-
- 🔐 **Auth Adapters** - JWT, OAuth, Sessions
|
|
457
|
-
- 🗄️ **Database Adapters** - PostgreSQL, MySQL, MongoDB
|
|
458
|
-
- 📨 **Queue Adapters** - Redis, RabbitMQ, SQS
|
|
459
|
-
- 📧 **Email Adapters** - SendGrid, Mailgun, SES
|
|
460
|
-
- 🔍 **Search Adapters** - Elasticsearch, Algolia
|
|
461
|
-
- 📊 **Analytics Adapters** - Google Analytics, Mixpanel
|
|
462
|
-
|
|
463
|
-
## Next Steps
|
|
464
|
-
|
|
465
|
-
- 📖 [API Reference](./09-api-reference.md) - Complete API documentation
|
|
466
|
-
- 💡 [Examples](./10-examples.md) - Real-world use cases
|
|
467
|
-
|
|
468
|
-
---
|
|
469
|
-
|
|
470
|
-
[← Performance](./07-performance.md) | [API Reference →](./09-api-reference.md)
|