@honestjs/rpc-plugin 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -10
- package/dist/index.d.mts +88 -51
- package/dist/index.d.ts +88 -51
- package/dist/index.js +337 -150
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +329 -145
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -32,11 +32,28 @@ interface RPCPluginOptions {
|
|
|
32
32
|
readonly tsConfigPath?: string // Path to tsconfig.json (default: 'tsconfig.json')
|
|
33
33
|
readonly outputDir?: string // Output directory for generated files (default: './generated/rpc')
|
|
34
34
|
readonly generateOnInit?: boolean // Generate files on initialization (default: true)
|
|
35
|
+
readonly openapi?: OpenApiOptions | boolean // Enable OpenAPI spec generation (default: false)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface OpenApiOptions {
|
|
39
|
+
readonly title?: string // API title (default: 'API')
|
|
40
|
+
readonly version?: string // API version (default: '1.0.0')
|
|
41
|
+
readonly description?: string // API description (default: '')
|
|
42
|
+
readonly servers?: readonly { url: string; description?: string }[] // Server list
|
|
43
|
+
readonly outputFile?: string // Output filename (default: 'openapi.json')
|
|
35
44
|
}
|
|
36
45
|
```
|
|
37
46
|
|
|
38
47
|
## What It Generates
|
|
39
48
|
|
|
49
|
+
The plugin generates files in the output directory (default: `./generated/rpc`):
|
|
50
|
+
|
|
51
|
+
| File | Description | When generated |
|
|
52
|
+
| --------------- | -------------------------------------------- | --------------------- |
|
|
53
|
+
| `client.ts` | Type-safe RPC client with all DTOs | Always |
|
|
54
|
+
| `openapi.json` | OpenAPI 3.0.3 specification | When `openapi` is set |
|
|
55
|
+
| `.rpc-checksum` | Hash of source files for incremental caching | Always |
|
|
56
|
+
|
|
40
57
|
### TypeScript RPC Client (`client.ts`)
|
|
41
58
|
|
|
42
59
|
The plugin generates a single comprehensive file that includes both the client and all type definitions:
|
|
@@ -80,7 +97,7 @@ The generated `client.ts` file contains everything you need:
|
|
|
80
97
|
|
|
81
98
|
- **ApiClient class** with all your controller methods
|
|
82
99
|
- **Type definitions** for requests, responses, and DTOs
|
|
83
|
-
- **Utility types** like RequestOptions
|
|
100
|
+
- **Utility types** like RequestOptions
|
|
84
101
|
- **Generated interfaces** from your controller types
|
|
85
102
|
|
|
86
103
|
## Custom Fetch Functions
|
|
@@ -173,6 +190,67 @@ const testApiClient = new ApiClient('http://test.com', {
|
|
|
173
190
|
expect(mockFetch).toHaveBeenCalledWith('http://test.com/api/v1/users/123', expect.objectContaining({ method: 'GET' }))
|
|
174
191
|
```
|
|
175
192
|
|
|
193
|
+
## OpenAPI Spec Generation
|
|
194
|
+
|
|
195
|
+
The plugin can produce an OpenAPI 3.0.3 JSON specification alongside the client. This is useful for Swagger UI, documentation portals, and third-party integrations. No extra dependencies are needed — the spec is built from the same route and schema data used for client generation.
|
|
196
|
+
|
|
197
|
+
### Enable with defaults
|
|
198
|
+
|
|
199
|
+
Pass `true` to use all default values:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
new RPCPlugin({
|
|
203
|
+
openapi: true
|
|
204
|
+
})
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Custom options
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
new RPCPlugin({
|
|
211
|
+
openapi: {
|
|
212
|
+
title: 'My Service API',
|
|
213
|
+
version: '2.1.0',
|
|
214
|
+
description: 'User management service',
|
|
215
|
+
servers: [
|
|
216
|
+
{ url: 'https://api.example.com', description: 'Production' },
|
|
217
|
+
{ url: 'http://localhost:3000', description: 'Local' }
|
|
218
|
+
],
|
|
219
|
+
outputFile: 'api-spec.json'
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The generated spec includes:
|
|
225
|
+
|
|
226
|
+
- **Paths** derived from your controller routes
|
|
227
|
+
- **Parameters** (path, query) with correct types
|
|
228
|
+
- **Request bodies** referencing component schemas for DTOs
|
|
229
|
+
- **Responses** with schema references and array type support
|
|
230
|
+
- **Component schemas** extracted from `ts-json-schema-generator` output
|
|
231
|
+
- **Tags** derived from controller names
|
|
232
|
+
|
|
233
|
+
## Hash-based Caching
|
|
234
|
+
|
|
235
|
+
On startup the plugin hashes all controller source files (SHA-256) and stores the checksum in `.rpc-checksum` inside the output directory. On subsequent runs, if the hash matches and the expected output files already exist, the expensive analysis and generation pipeline is skipped entirely. This significantly reduces startup time in large projects.
|
|
236
|
+
|
|
237
|
+
Caching is automatic and requires no configuration. To force regeneration:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// Manual call — defaults to force=true, always regenerates
|
|
241
|
+
await rpcPlugin.analyze()
|
|
242
|
+
|
|
243
|
+
// Explicit cache bypass
|
|
244
|
+
await rpcPlugin.analyze(true)
|
|
245
|
+
|
|
246
|
+
// Respect the cache (same behavior as automatic startup)
|
|
247
|
+
await rpcPlugin.analyze(false)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
You can also delete `.rpc-checksum` from the output directory to clear the cache.
|
|
251
|
+
|
|
252
|
+
> **Note:** The hash covers controller files matched by the `controllerPattern` glob. If you only change a DTO/model file that lives outside that pattern, the cache won't invalidate automatically. Use `analyze()` or delete `.rpc-checksum` in that case.
|
|
253
|
+
|
|
176
254
|
## How It Works
|
|
177
255
|
|
|
178
256
|
### 1. Route Analysis
|
|
@@ -196,6 +274,19 @@ expect(mockFetch).toHaveBeenCalledWith('http://test.com/api/v1/users/123', expec
|
|
|
196
274
|
- Creates parameter validation and typing
|
|
197
275
|
- Builds the complete RPC client with proper error handling
|
|
198
276
|
|
|
277
|
+
### 4. OpenAPI Generation (optional)
|
|
278
|
+
|
|
279
|
+
- Converts route and schema data to OpenAPI 3.0.3 paths and components
|
|
280
|
+
- Maps `@Param()`, `@Query()`, and `@Body()` decorators to the correct OpenAPI parameter locations
|
|
281
|
+
- References component schemas via `$ref` for DTOs
|
|
282
|
+
- Outputs a single JSON file ready for Swagger UI or any OpenAPI-compatible tool
|
|
283
|
+
|
|
284
|
+
### 5. Incremental Caching
|
|
285
|
+
|
|
286
|
+
- Hashes all matched controller files after glob resolution
|
|
287
|
+
- Compares against the stored `.rpc-checksum`
|
|
288
|
+
- Skips steps 1–4 when files are unchanged and output already exists
|
|
289
|
+
|
|
199
290
|
## Example Generated Output
|
|
200
291
|
|
|
201
292
|
### Generated Client
|
|
@@ -204,15 +295,20 @@ expect(mockFetch).toHaveBeenCalledWith('http://test.com/api/v1/users/123', expec
|
|
|
204
295
|
export class ApiClient {
|
|
205
296
|
get users() {
|
|
206
297
|
return {
|
|
207
|
-
create: async (
|
|
298
|
+
create: async <Result = User>(
|
|
208
299
|
options: RequestOptions<{ name: string; email: string }, undefined, undefined, undefined>
|
|
209
|
-
)
|
|
210
|
-
return this.request('POST', `/api/v1/users/`, options)
|
|
300
|
+
) => {
|
|
301
|
+
return this.request<Result>('POST', `/api/v1/users/`, options)
|
|
211
302
|
},
|
|
212
|
-
list: async (
|
|
303
|
+
list: async <Result = User[]>(
|
|
213
304
|
options?: RequestOptions<undefined, { page: number; limit: number }, undefined, undefined>
|
|
214
|
-
)
|
|
215
|
-
return this.request('GET', `/api/v1/users/`, options)
|
|
305
|
+
) => {
|
|
306
|
+
return this.request<Result>('GET', `/api/v1/users/`, options)
|
|
307
|
+
},
|
|
308
|
+
getById: async <Result = User>(
|
|
309
|
+
options: RequestOptions<undefined, { id: string }, undefined, undefined>
|
|
310
|
+
) => {
|
|
311
|
+
return this.request<Result>('GET', `/api/v1/users/:id`, options)
|
|
216
312
|
}
|
|
217
313
|
}
|
|
218
314
|
}
|
|
@@ -232,12 +328,15 @@ export type RequestOptions<
|
|
|
232
328
|
|
|
233
329
|
## Plugin Lifecycle
|
|
234
330
|
|
|
235
|
-
The plugin automatically generates files when your HonestJS application starts up (if `generateOnInit` is true).
|
|
236
|
-
|
|
331
|
+
The plugin automatically generates files when your HonestJS application starts up (if `generateOnInit` is true). On
|
|
332
|
+
subsequent startups, the hash-based cache will skip regeneration if controller files haven't changed.
|
|
333
|
+
|
|
334
|
+
You can also manually trigger generation:
|
|
237
335
|
|
|
238
336
|
```typescript
|
|
239
337
|
const rpcPlugin = new RPCPlugin()
|
|
240
|
-
await rpcPlugin.analyze() //
|
|
338
|
+
await rpcPlugin.analyze() // Force regeneration (bypasses cache)
|
|
339
|
+
await rpcPlugin.analyze(false) // Respect cache
|
|
241
340
|
```
|
|
242
341
|
|
|
243
342
|
## Advanced Usage
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RouteInfo, ParameterMetadata, IPlugin, Application } from 'honestjs';
|
|
2
2
|
import { Hono } from 'hono';
|
|
3
|
-
import { Type } from 'ts-morph';
|
|
3
|
+
import { Project, Type } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Parameter metadata with enhanced type information
|
|
@@ -9,6 +9,8 @@ interface ParameterMetadataWithType extends ParameterMetadata {
|
|
|
9
9
|
readonly type: string;
|
|
10
10
|
readonly required: boolean;
|
|
11
11
|
readonly name: string;
|
|
12
|
+
/** Original decorator kind: 'body', 'param', 'query', 'header', etc. */
|
|
13
|
+
readonly decoratorType: string;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Extended route information with comprehensive type data
|
|
@@ -49,35 +51,19 @@ interface GeneratedClientInfo {
|
|
|
49
51
|
/**
|
|
50
52
|
* Clean separation of concerns for request options
|
|
51
53
|
*/
|
|
52
|
-
type RequestOptions<TParams =
|
|
53
|
-
params?: never;
|
|
54
|
-
} : {
|
|
54
|
+
type RequestOptions<TParams = undefined, TQuery = undefined, TBody = undefined, THeaders = undefined> = (TParams extends undefined ? object : {
|
|
55
55
|
params: TParams;
|
|
56
|
-
}) & (TQuery extends
|
|
57
|
-
query
|
|
58
|
-
} : {
|
|
59
|
-
query?: TQuery;
|
|
60
|
-
}) & (TBody extends never ? {
|
|
61
|
-
body?: never;
|
|
62
|
-
} : {
|
|
56
|
+
}) & (TQuery extends undefined ? object : {
|
|
57
|
+
query: TQuery;
|
|
58
|
+
}) & (TBody extends undefined ? object : {
|
|
63
59
|
body: TBody;
|
|
64
|
-
}) & (THeaders extends
|
|
65
|
-
headers?: never;
|
|
66
|
-
} : {
|
|
60
|
+
}) & (THeaders extends undefined ? object : {
|
|
67
61
|
headers: THeaders;
|
|
68
62
|
});
|
|
69
63
|
/**
|
|
70
64
|
* Custom fetch function type that matches the standard fetch API
|
|
71
65
|
*/
|
|
72
66
|
type FetchFunction = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
73
|
-
/**
|
|
74
|
-
* API Response wrapper
|
|
75
|
-
*/
|
|
76
|
-
interface ApiResponse<T = any> {
|
|
77
|
-
data: T;
|
|
78
|
-
message?: string;
|
|
79
|
-
success: boolean;
|
|
80
|
-
}
|
|
81
67
|
/**
|
|
82
68
|
* API Error class
|
|
83
69
|
*/
|
|
@@ -86,6 +72,16 @@ declare class ApiError extends Error {
|
|
|
86
72
|
constructor(statusCode: number, message: string);
|
|
87
73
|
}
|
|
88
74
|
|
|
75
|
+
interface OpenApiOptions {
|
|
76
|
+
readonly title?: string;
|
|
77
|
+
readonly version?: string;
|
|
78
|
+
readonly description?: string;
|
|
79
|
+
readonly servers?: readonly {
|
|
80
|
+
url: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
}[];
|
|
83
|
+
readonly outputFile?: string;
|
|
84
|
+
}
|
|
89
85
|
/**
|
|
90
86
|
* Configuration options for the RPCPlugin
|
|
91
87
|
*/
|
|
@@ -94,6 +90,7 @@ interface RPCPluginOptions {
|
|
|
94
90
|
readonly tsConfigPath?: string;
|
|
95
91
|
readonly outputDir?: string;
|
|
96
92
|
readonly generateOnInit?: boolean;
|
|
93
|
+
readonly openapi?: OpenApiOptions | boolean;
|
|
97
94
|
}
|
|
98
95
|
/**
|
|
99
96
|
* Comprehensive RPC plugin that combines route analysis, schema generation, and client generation
|
|
@@ -106,10 +103,14 @@ declare class RPCPlugin implements IPlugin {
|
|
|
106
103
|
private readonly routeAnalyzer;
|
|
107
104
|
private readonly schemaGenerator;
|
|
108
105
|
private readonly clientGenerator;
|
|
106
|
+
private readonly openApiGenerator;
|
|
107
|
+
private readonly openApiOptions;
|
|
108
|
+
private project;
|
|
109
109
|
private analyzedRoutes;
|
|
110
110
|
private analyzedSchemas;
|
|
111
111
|
private generatedInfo;
|
|
112
112
|
constructor(options?: RPCPluginOptions);
|
|
113
|
+
private resolveOpenApiOptions;
|
|
113
114
|
/**
|
|
114
115
|
* Validates the plugin configuration
|
|
115
116
|
*/
|
|
@@ -123,9 +124,10 @@ declare class RPCPlugin implements IPlugin {
|
|
|
123
124
|
*/
|
|
124
125
|
private analyzeEverything;
|
|
125
126
|
/**
|
|
126
|
-
* Manually trigger analysis (useful for testing or re-generation)
|
|
127
|
+
* Manually trigger analysis (useful for testing or re-generation).
|
|
128
|
+
* Defaults to force=true to bypass cache; pass false to use caching.
|
|
127
129
|
*/
|
|
128
|
-
analyze(): Promise<void>;
|
|
130
|
+
analyze(force?: boolean): Promise<void>;
|
|
129
131
|
/**
|
|
130
132
|
* Get the analyzed routes
|
|
131
133
|
*/
|
|
@@ -138,6 +140,10 @@ declare class RPCPlugin implements IPlugin {
|
|
|
138
140
|
* Get the generation info
|
|
139
141
|
*/
|
|
140
142
|
getGenerationInfo(): GeneratedClientInfo | null;
|
|
143
|
+
/**
|
|
144
|
+
* Checks whether expected output files exist on disk
|
|
145
|
+
*/
|
|
146
|
+
private outputFilesExist;
|
|
141
147
|
/**
|
|
142
148
|
* Cleanup resources to prevent memory leaks
|
|
143
149
|
*/
|
|
@@ -192,26 +198,50 @@ declare class ClientGeneratorService {
|
|
|
192
198
|
private analyzeRouteParameters;
|
|
193
199
|
}
|
|
194
200
|
|
|
201
|
+
interface ResolvedOpenApiOptions {
|
|
202
|
+
readonly title: string;
|
|
203
|
+
readonly version: string;
|
|
204
|
+
readonly description: string;
|
|
205
|
+
readonly servers: readonly {
|
|
206
|
+
url: string;
|
|
207
|
+
description?: string;
|
|
208
|
+
}[];
|
|
209
|
+
readonly outputFile: string;
|
|
210
|
+
}
|
|
195
211
|
/**
|
|
196
|
-
* Service for
|
|
212
|
+
* Service for generating OpenAPI 3.0.3 specifications from analyzed routes and schemas
|
|
197
213
|
*/
|
|
198
|
-
declare class
|
|
199
|
-
private readonly
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
private
|
|
214
|
+
declare class OpenApiGeneratorService {
|
|
215
|
+
private readonly outputDir;
|
|
216
|
+
constructor(outputDir: string);
|
|
217
|
+
generateSpec(routes: readonly ExtendedRouteInfo[], schemas: readonly SchemaInfo[], options: ResolvedOpenApiOptions): Promise<string>;
|
|
218
|
+
private buildSpec;
|
|
219
|
+
private buildOperation;
|
|
220
|
+
private buildParameters;
|
|
221
|
+
private buildRequestBody;
|
|
222
|
+
private buildResponses;
|
|
223
|
+
private resolveResponseSchema;
|
|
224
|
+
private buildSchemaMap;
|
|
203
225
|
/**
|
|
204
|
-
*
|
|
226
|
+
* Converts Express-style `:param` path to OpenAPI `{param}` syntax
|
|
205
227
|
*/
|
|
206
|
-
|
|
228
|
+
private toOpenApiPath;
|
|
229
|
+
private tsTypeToJsonSchema;
|
|
207
230
|
/**
|
|
208
|
-
*
|
|
231
|
+
* Extracts the base type name from a TS type string, stripping
|
|
232
|
+
* wrappers like `Partial<...>`, `...[]`, `Promise<...>`.
|
|
209
233
|
*/
|
|
210
|
-
private
|
|
234
|
+
private extractBaseTypeName;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Service for analyzing controller methods and extracting type information
|
|
239
|
+
*/
|
|
240
|
+
declare class RouteAnalyzerService {
|
|
211
241
|
/**
|
|
212
|
-
*
|
|
242
|
+
* Analyzes controller methods to extract type information
|
|
213
243
|
*/
|
|
214
|
-
|
|
244
|
+
analyzeControllerMethods(project: Project): Promise<ExtendedRouteInfo[]>;
|
|
215
245
|
/**
|
|
216
246
|
* Finds controller classes in the project
|
|
217
247
|
*/
|
|
@@ -241,19 +271,10 @@ declare class SchemaGeneratorService {
|
|
|
241
271
|
private readonly controllerPattern;
|
|
242
272
|
private readonly tsConfigPath;
|
|
243
273
|
constructor(controllerPattern: string, tsConfigPath: string);
|
|
244
|
-
private projects;
|
|
245
274
|
/**
|
|
246
275
|
* Generates JSON schemas from types used in controllers
|
|
247
276
|
*/
|
|
248
|
-
generateSchemas(): Promise<SchemaInfo[]>;
|
|
249
|
-
/**
|
|
250
|
-
* Creates a new ts-morph project
|
|
251
|
-
*/
|
|
252
|
-
private createProject;
|
|
253
|
-
/**
|
|
254
|
-
* Cleanup resources to prevent memory leaks
|
|
255
|
-
*/
|
|
256
|
-
dispose(): void;
|
|
277
|
+
generateSchemas(project: Project): Promise<SchemaInfo[]>;
|
|
257
278
|
/**
|
|
258
279
|
* Collects types from controller files
|
|
259
280
|
*/
|
|
@@ -272,6 +293,26 @@ declare class SchemaGeneratorService {
|
|
|
272
293
|
private generateSchemaForType;
|
|
273
294
|
}
|
|
274
295
|
|
|
296
|
+
interface ChecksumData {
|
|
297
|
+
hash: string;
|
|
298
|
+
files: string[];
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Computes a deterministic SHA-256 hash from file contents.
|
|
302
|
+
* Sorts paths before reading to ensure consistent ordering.
|
|
303
|
+
* Includes the file count in the hash so adding/removing files changes it.
|
|
304
|
+
*/
|
|
305
|
+
declare function computeHash(filePaths: string[]): string;
|
|
306
|
+
/**
|
|
307
|
+
* Reads the stored checksum from the output directory.
|
|
308
|
+
* Returns null if the file is missing or corrupt.
|
|
309
|
+
*/
|
|
310
|
+
declare function readChecksum(outputDir: string): ChecksumData | null;
|
|
311
|
+
/**
|
|
312
|
+
* Writes the checksum data to the output directory.
|
|
313
|
+
*/
|
|
314
|
+
declare function writeChecksum(outputDir: string, data: ChecksumData): Promise<void>;
|
|
315
|
+
|
|
275
316
|
/**
|
|
276
317
|
* Builds the full path with parameter placeholders
|
|
277
318
|
*/
|
|
@@ -303,10 +344,6 @@ declare function camelCase(str: string): string;
|
|
|
303
344
|
* Extracts a named type from a TypeScript type
|
|
304
345
|
*/
|
|
305
346
|
declare function extractNamedType(type: Type): string | null;
|
|
306
|
-
/**
|
|
307
|
-
* Generates type imports for the client
|
|
308
|
-
*/
|
|
309
|
-
declare function generateTypeImports(routes: readonly any[]): string;
|
|
310
347
|
|
|
311
348
|
/**
|
|
312
349
|
* Default configuration options for the RPCPlugin
|
|
@@ -334,4 +371,4 @@ declare const BUILTIN_TYPES: Set<string>;
|
|
|
334
371
|
*/
|
|
335
372
|
declare const GENERIC_TYPES: Set<string>;
|
|
336
373
|
|
|
337
|
-
export { ApiError,
|
|
374
|
+
export { ApiError, BUILTIN_TYPES, BUILTIN_UTILITY_TYPES, type ChecksumData, ClientGeneratorService, type ControllerGroups, DEFAULT_OPTIONS, type ExtendedRouteInfo, type FetchFunction, GENERIC_TYPES, type GeneratedClientInfo, LOG_PREFIX, OpenApiGeneratorService, type OpenApiOptions, type ParameterMetadataWithType, RPCPlugin, type RPCPluginOptions, type RequestOptions, RouteAnalyzerService, type RouteParameter, SchemaGeneratorService, type SchemaInfo, buildFullApiPath, buildFullPath, camelCase, computeHash, extractNamedType, generateTypeScriptInterface, mapJsonSchemaTypeToTypeScript, readChecksum, safeToString, writeChecksum };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RouteInfo, ParameterMetadata, IPlugin, Application } from 'honestjs';
|
|
2
2
|
import { Hono } from 'hono';
|
|
3
|
-
import { Type } from 'ts-morph';
|
|
3
|
+
import { Project, Type } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Parameter metadata with enhanced type information
|
|
@@ -9,6 +9,8 @@ interface ParameterMetadataWithType extends ParameterMetadata {
|
|
|
9
9
|
readonly type: string;
|
|
10
10
|
readonly required: boolean;
|
|
11
11
|
readonly name: string;
|
|
12
|
+
/** Original decorator kind: 'body', 'param', 'query', 'header', etc. */
|
|
13
|
+
readonly decoratorType: string;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Extended route information with comprehensive type data
|
|
@@ -49,35 +51,19 @@ interface GeneratedClientInfo {
|
|
|
49
51
|
/**
|
|
50
52
|
* Clean separation of concerns for request options
|
|
51
53
|
*/
|
|
52
|
-
type RequestOptions<TParams =
|
|
53
|
-
params?: never;
|
|
54
|
-
} : {
|
|
54
|
+
type RequestOptions<TParams = undefined, TQuery = undefined, TBody = undefined, THeaders = undefined> = (TParams extends undefined ? object : {
|
|
55
55
|
params: TParams;
|
|
56
|
-
}) & (TQuery extends
|
|
57
|
-
query
|
|
58
|
-
} : {
|
|
59
|
-
query?: TQuery;
|
|
60
|
-
}) & (TBody extends never ? {
|
|
61
|
-
body?: never;
|
|
62
|
-
} : {
|
|
56
|
+
}) & (TQuery extends undefined ? object : {
|
|
57
|
+
query: TQuery;
|
|
58
|
+
}) & (TBody extends undefined ? object : {
|
|
63
59
|
body: TBody;
|
|
64
|
-
}) & (THeaders extends
|
|
65
|
-
headers?: never;
|
|
66
|
-
} : {
|
|
60
|
+
}) & (THeaders extends undefined ? object : {
|
|
67
61
|
headers: THeaders;
|
|
68
62
|
});
|
|
69
63
|
/**
|
|
70
64
|
* Custom fetch function type that matches the standard fetch API
|
|
71
65
|
*/
|
|
72
66
|
type FetchFunction = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
73
|
-
/**
|
|
74
|
-
* API Response wrapper
|
|
75
|
-
*/
|
|
76
|
-
interface ApiResponse<T = any> {
|
|
77
|
-
data: T;
|
|
78
|
-
message?: string;
|
|
79
|
-
success: boolean;
|
|
80
|
-
}
|
|
81
67
|
/**
|
|
82
68
|
* API Error class
|
|
83
69
|
*/
|
|
@@ -86,6 +72,16 @@ declare class ApiError extends Error {
|
|
|
86
72
|
constructor(statusCode: number, message: string);
|
|
87
73
|
}
|
|
88
74
|
|
|
75
|
+
interface OpenApiOptions {
|
|
76
|
+
readonly title?: string;
|
|
77
|
+
readonly version?: string;
|
|
78
|
+
readonly description?: string;
|
|
79
|
+
readonly servers?: readonly {
|
|
80
|
+
url: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
}[];
|
|
83
|
+
readonly outputFile?: string;
|
|
84
|
+
}
|
|
89
85
|
/**
|
|
90
86
|
* Configuration options for the RPCPlugin
|
|
91
87
|
*/
|
|
@@ -94,6 +90,7 @@ interface RPCPluginOptions {
|
|
|
94
90
|
readonly tsConfigPath?: string;
|
|
95
91
|
readonly outputDir?: string;
|
|
96
92
|
readonly generateOnInit?: boolean;
|
|
93
|
+
readonly openapi?: OpenApiOptions | boolean;
|
|
97
94
|
}
|
|
98
95
|
/**
|
|
99
96
|
* Comprehensive RPC plugin that combines route analysis, schema generation, and client generation
|
|
@@ -106,10 +103,14 @@ declare class RPCPlugin implements IPlugin {
|
|
|
106
103
|
private readonly routeAnalyzer;
|
|
107
104
|
private readonly schemaGenerator;
|
|
108
105
|
private readonly clientGenerator;
|
|
106
|
+
private readonly openApiGenerator;
|
|
107
|
+
private readonly openApiOptions;
|
|
108
|
+
private project;
|
|
109
109
|
private analyzedRoutes;
|
|
110
110
|
private analyzedSchemas;
|
|
111
111
|
private generatedInfo;
|
|
112
112
|
constructor(options?: RPCPluginOptions);
|
|
113
|
+
private resolveOpenApiOptions;
|
|
113
114
|
/**
|
|
114
115
|
* Validates the plugin configuration
|
|
115
116
|
*/
|
|
@@ -123,9 +124,10 @@ declare class RPCPlugin implements IPlugin {
|
|
|
123
124
|
*/
|
|
124
125
|
private analyzeEverything;
|
|
125
126
|
/**
|
|
126
|
-
* Manually trigger analysis (useful for testing or re-generation)
|
|
127
|
+
* Manually trigger analysis (useful for testing or re-generation).
|
|
128
|
+
* Defaults to force=true to bypass cache; pass false to use caching.
|
|
127
129
|
*/
|
|
128
|
-
analyze(): Promise<void>;
|
|
130
|
+
analyze(force?: boolean): Promise<void>;
|
|
129
131
|
/**
|
|
130
132
|
* Get the analyzed routes
|
|
131
133
|
*/
|
|
@@ -138,6 +140,10 @@ declare class RPCPlugin implements IPlugin {
|
|
|
138
140
|
* Get the generation info
|
|
139
141
|
*/
|
|
140
142
|
getGenerationInfo(): GeneratedClientInfo | null;
|
|
143
|
+
/**
|
|
144
|
+
* Checks whether expected output files exist on disk
|
|
145
|
+
*/
|
|
146
|
+
private outputFilesExist;
|
|
141
147
|
/**
|
|
142
148
|
* Cleanup resources to prevent memory leaks
|
|
143
149
|
*/
|
|
@@ -192,26 +198,50 @@ declare class ClientGeneratorService {
|
|
|
192
198
|
private analyzeRouteParameters;
|
|
193
199
|
}
|
|
194
200
|
|
|
201
|
+
interface ResolvedOpenApiOptions {
|
|
202
|
+
readonly title: string;
|
|
203
|
+
readonly version: string;
|
|
204
|
+
readonly description: string;
|
|
205
|
+
readonly servers: readonly {
|
|
206
|
+
url: string;
|
|
207
|
+
description?: string;
|
|
208
|
+
}[];
|
|
209
|
+
readonly outputFile: string;
|
|
210
|
+
}
|
|
195
211
|
/**
|
|
196
|
-
* Service for
|
|
212
|
+
* Service for generating OpenAPI 3.0.3 specifications from analyzed routes and schemas
|
|
197
213
|
*/
|
|
198
|
-
declare class
|
|
199
|
-
private readonly
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
private
|
|
214
|
+
declare class OpenApiGeneratorService {
|
|
215
|
+
private readonly outputDir;
|
|
216
|
+
constructor(outputDir: string);
|
|
217
|
+
generateSpec(routes: readonly ExtendedRouteInfo[], schemas: readonly SchemaInfo[], options: ResolvedOpenApiOptions): Promise<string>;
|
|
218
|
+
private buildSpec;
|
|
219
|
+
private buildOperation;
|
|
220
|
+
private buildParameters;
|
|
221
|
+
private buildRequestBody;
|
|
222
|
+
private buildResponses;
|
|
223
|
+
private resolveResponseSchema;
|
|
224
|
+
private buildSchemaMap;
|
|
203
225
|
/**
|
|
204
|
-
*
|
|
226
|
+
* Converts Express-style `:param` path to OpenAPI `{param}` syntax
|
|
205
227
|
*/
|
|
206
|
-
|
|
228
|
+
private toOpenApiPath;
|
|
229
|
+
private tsTypeToJsonSchema;
|
|
207
230
|
/**
|
|
208
|
-
*
|
|
231
|
+
* Extracts the base type name from a TS type string, stripping
|
|
232
|
+
* wrappers like `Partial<...>`, `...[]`, `Promise<...>`.
|
|
209
233
|
*/
|
|
210
|
-
private
|
|
234
|
+
private extractBaseTypeName;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Service for analyzing controller methods and extracting type information
|
|
239
|
+
*/
|
|
240
|
+
declare class RouteAnalyzerService {
|
|
211
241
|
/**
|
|
212
|
-
*
|
|
242
|
+
* Analyzes controller methods to extract type information
|
|
213
243
|
*/
|
|
214
|
-
|
|
244
|
+
analyzeControllerMethods(project: Project): Promise<ExtendedRouteInfo[]>;
|
|
215
245
|
/**
|
|
216
246
|
* Finds controller classes in the project
|
|
217
247
|
*/
|
|
@@ -241,19 +271,10 @@ declare class SchemaGeneratorService {
|
|
|
241
271
|
private readonly controllerPattern;
|
|
242
272
|
private readonly tsConfigPath;
|
|
243
273
|
constructor(controllerPattern: string, tsConfigPath: string);
|
|
244
|
-
private projects;
|
|
245
274
|
/**
|
|
246
275
|
* Generates JSON schemas from types used in controllers
|
|
247
276
|
*/
|
|
248
|
-
generateSchemas(): Promise<SchemaInfo[]>;
|
|
249
|
-
/**
|
|
250
|
-
* Creates a new ts-morph project
|
|
251
|
-
*/
|
|
252
|
-
private createProject;
|
|
253
|
-
/**
|
|
254
|
-
* Cleanup resources to prevent memory leaks
|
|
255
|
-
*/
|
|
256
|
-
dispose(): void;
|
|
277
|
+
generateSchemas(project: Project): Promise<SchemaInfo[]>;
|
|
257
278
|
/**
|
|
258
279
|
* Collects types from controller files
|
|
259
280
|
*/
|
|
@@ -272,6 +293,26 @@ declare class SchemaGeneratorService {
|
|
|
272
293
|
private generateSchemaForType;
|
|
273
294
|
}
|
|
274
295
|
|
|
296
|
+
interface ChecksumData {
|
|
297
|
+
hash: string;
|
|
298
|
+
files: string[];
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Computes a deterministic SHA-256 hash from file contents.
|
|
302
|
+
* Sorts paths before reading to ensure consistent ordering.
|
|
303
|
+
* Includes the file count in the hash so adding/removing files changes it.
|
|
304
|
+
*/
|
|
305
|
+
declare function computeHash(filePaths: string[]): string;
|
|
306
|
+
/**
|
|
307
|
+
* Reads the stored checksum from the output directory.
|
|
308
|
+
* Returns null if the file is missing or corrupt.
|
|
309
|
+
*/
|
|
310
|
+
declare function readChecksum(outputDir: string): ChecksumData | null;
|
|
311
|
+
/**
|
|
312
|
+
* Writes the checksum data to the output directory.
|
|
313
|
+
*/
|
|
314
|
+
declare function writeChecksum(outputDir: string, data: ChecksumData): Promise<void>;
|
|
315
|
+
|
|
275
316
|
/**
|
|
276
317
|
* Builds the full path with parameter placeholders
|
|
277
318
|
*/
|
|
@@ -303,10 +344,6 @@ declare function camelCase(str: string): string;
|
|
|
303
344
|
* Extracts a named type from a TypeScript type
|
|
304
345
|
*/
|
|
305
346
|
declare function extractNamedType(type: Type): string | null;
|
|
306
|
-
/**
|
|
307
|
-
* Generates type imports for the client
|
|
308
|
-
*/
|
|
309
|
-
declare function generateTypeImports(routes: readonly any[]): string;
|
|
310
347
|
|
|
311
348
|
/**
|
|
312
349
|
* Default configuration options for the RPCPlugin
|
|
@@ -334,4 +371,4 @@ declare const BUILTIN_TYPES: Set<string>;
|
|
|
334
371
|
*/
|
|
335
372
|
declare const GENERIC_TYPES: Set<string>;
|
|
336
373
|
|
|
337
|
-
export { ApiError,
|
|
374
|
+
export { ApiError, BUILTIN_TYPES, BUILTIN_UTILITY_TYPES, type ChecksumData, ClientGeneratorService, type ControllerGroups, DEFAULT_OPTIONS, type ExtendedRouteInfo, type FetchFunction, GENERIC_TYPES, type GeneratedClientInfo, LOG_PREFIX, OpenApiGeneratorService, type OpenApiOptions, type ParameterMetadataWithType, RPCPlugin, type RPCPluginOptions, type RequestOptions, RouteAnalyzerService, type RouteParameter, SchemaGeneratorService, type SchemaInfo, buildFullApiPath, buildFullPath, camelCase, computeHash, extractNamedType, generateTypeScriptInterface, mapJsonSchemaTypeToTypeScript, readChecksum, safeToString, writeChecksum };
|