@honestjs/rpc-plugin 1.2.0 → 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 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:
@@ -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
@@ -237,12 +328,15 @@ export type RequestOptions<
237
328
 
238
329
  ## Plugin Lifecycle
239
330
 
240
- The plugin automatically generates files when your HonestJS application starts up (if `generateOnInit` is true). You can
241
- also manually trigger generation:
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:
242
335
 
243
336
  ```typescript
244
337
  const rpcPlugin = new RPCPlugin()
245
- await rpcPlugin.analyze() // Manually trigger analysis and generation
338
+ await rpcPlugin.analyze() // Force regeneration (bypasses cache)
339
+ await rpcPlugin.analyze(false) // Respect cache
246
340
  ```
247
341
 
248
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,21 +51,13 @@ interface GeneratedClientInfo {
49
51
  /**
50
52
  * Clean separation of concerns for request options
51
53
  */
52
- type RequestOptions<TParams = never, TQuery = never, TBody = never, THeaders = never> = (TParams extends never ? {
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 never ? {
57
- query?: never;
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 never ? {
65
- headers?: never;
66
- } : {
60
+ }) & (THeaders extends undefined ? object : {
67
61
  headers: THeaders;
68
62
  });
69
63
  /**
@@ -78,6 +72,16 @@ declare class ApiError extends Error {
78
72
  constructor(statusCode: number, message: string);
79
73
  }
80
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
+ }
81
85
  /**
82
86
  * Configuration options for the RPCPlugin
83
87
  */
@@ -86,6 +90,7 @@ interface RPCPluginOptions {
86
90
  readonly tsConfigPath?: string;
87
91
  readonly outputDir?: string;
88
92
  readonly generateOnInit?: boolean;
93
+ readonly openapi?: OpenApiOptions | boolean;
89
94
  }
90
95
  /**
91
96
  * Comprehensive RPC plugin that combines route analysis, schema generation, and client generation
@@ -98,10 +103,14 @@ declare class RPCPlugin implements IPlugin {
98
103
  private readonly routeAnalyzer;
99
104
  private readonly schemaGenerator;
100
105
  private readonly clientGenerator;
106
+ private readonly openApiGenerator;
107
+ private readonly openApiOptions;
108
+ private project;
101
109
  private analyzedRoutes;
102
110
  private analyzedSchemas;
103
111
  private generatedInfo;
104
112
  constructor(options?: RPCPluginOptions);
113
+ private resolveOpenApiOptions;
105
114
  /**
106
115
  * Validates the plugin configuration
107
116
  */
@@ -115,9 +124,10 @@ declare class RPCPlugin implements IPlugin {
115
124
  */
116
125
  private analyzeEverything;
117
126
  /**
118
- * 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.
119
129
  */
120
- analyze(): Promise<void>;
130
+ analyze(force?: boolean): Promise<void>;
121
131
  /**
122
132
  * Get the analyzed routes
123
133
  */
@@ -130,6 +140,10 @@ declare class RPCPlugin implements IPlugin {
130
140
  * Get the generation info
131
141
  */
132
142
  getGenerationInfo(): GeneratedClientInfo | null;
143
+ /**
144
+ * Checks whether expected output files exist on disk
145
+ */
146
+ private outputFilesExist;
133
147
  /**
134
148
  * Cleanup resources to prevent memory leaks
135
149
  */
@@ -184,26 +198,50 @@ declare class ClientGeneratorService {
184
198
  private analyzeRouteParameters;
185
199
  }
186
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
+ }
187
211
  /**
188
- * Service for analyzing controller methods and extracting type information
212
+ * Service for generating OpenAPI 3.0.3 specifications from analyzed routes and schemas
189
213
  */
190
- declare class RouteAnalyzerService {
191
- private readonly controllerPattern;
192
- private readonly tsConfigPath;
193
- constructor(controllerPattern: string, tsConfigPath: string);
194
- private projects;
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;
195
225
  /**
196
- * Analyzes controller methods to extract type information
226
+ * Converts Express-style `:param` path to OpenAPI `{param}` syntax
197
227
  */
198
- analyzeControllerMethods(): Promise<ExtendedRouteInfo[]>;
228
+ private toOpenApiPath;
229
+ private tsTypeToJsonSchema;
199
230
  /**
200
- * Creates a new ts-morph project
231
+ * Extracts the base type name from a TS type string, stripping
232
+ * wrappers like `Partial<...>`, `...[]`, `Promise<...>`.
201
233
  */
202
- private createProject;
234
+ private extractBaseTypeName;
235
+ }
236
+
237
+ /**
238
+ * Service for analyzing controller methods and extracting type information
239
+ */
240
+ declare class RouteAnalyzerService {
203
241
  /**
204
- * Cleanup resources to prevent memory leaks
242
+ * Analyzes controller methods to extract type information
205
243
  */
206
- dispose(): void;
244
+ analyzeControllerMethods(project: Project): Promise<ExtendedRouteInfo[]>;
207
245
  /**
208
246
  * Finds controller classes in the project
209
247
  */
@@ -233,19 +271,10 @@ declare class SchemaGeneratorService {
233
271
  private readonly controllerPattern;
234
272
  private readonly tsConfigPath;
235
273
  constructor(controllerPattern: string, tsConfigPath: string);
236
- private projects;
237
274
  /**
238
275
  * Generates JSON schemas from types used in controllers
239
276
  */
240
- generateSchemas(): Promise<SchemaInfo[]>;
241
- /**
242
- * Creates a new ts-morph project
243
- */
244
- private createProject;
245
- /**
246
- * Cleanup resources to prevent memory leaks
247
- */
248
- dispose(): void;
277
+ generateSchemas(project: Project): Promise<SchemaInfo[]>;
249
278
  /**
250
279
  * Collects types from controller files
251
280
  */
@@ -264,6 +293,26 @@ declare class SchemaGeneratorService {
264
293
  private generateSchemaForType;
265
294
  }
266
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
+
267
316
  /**
268
317
  * Builds the full path with parameter placeholders
269
318
  */
@@ -295,10 +344,6 @@ declare function camelCase(str: string): string;
295
344
  * Extracts a named type from a TypeScript type
296
345
  */
297
346
  declare function extractNamedType(type: Type): string | null;
298
- /**
299
- * Generates type imports for the client
300
- */
301
- declare function generateTypeImports(routes: readonly any[]): string;
302
347
 
303
348
  /**
304
349
  * Default configuration options for the RPCPlugin
@@ -326,4 +371,4 @@ declare const BUILTIN_TYPES: Set<string>;
326
371
  */
327
372
  declare const GENERIC_TYPES: Set<string>;
328
373
 
329
- export { ApiError, BUILTIN_TYPES, BUILTIN_UTILITY_TYPES, ClientGeneratorService, type ControllerGroups, DEFAULT_OPTIONS, type ExtendedRouteInfo, type FetchFunction, GENERIC_TYPES, type GeneratedClientInfo, LOG_PREFIX, type ParameterMetadataWithType, RPCPlugin, type RPCPluginOptions, type RequestOptions, RouteAnalyzerService, type RouteParameter, SchemaGeneratorService, type SchemaInfo, buildFullApiPath, buildFullPath, camelCase, extractNamedType, generateTypeImports, generateTypeScriptInterface, mapJsonSchemaTypeToTypeScript, safeToString };
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,21 +51,13 @@ interface GeneratedClientInfo {
49
51
  /**
50
52
  * Clean separation of concerns for request options
51
53
  */
52
- type RequestOptions<TParams = never, TQuery = never, TBody = never, THeaders = never> = (TParams extends never ? {
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 never ? {
57
- query?: never;
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 never ? {
65
- headers?: never;
66
- } : {
60
+ }) & (THeaders extends undefined ? object : {
67
61
  headers: THeaders;
68
62
  });
69
63
  /**
@@ -78,6 +72,16 @@ declare class ApiError extends Error {
78
72
  constructor(statusCode: number, message: string);
79
73
  }
80
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
+ }
81
85
  /**
82
86
  * Configuration options for the RPCPlugin
83
87
  */
@@ -86,6 +90,7 @@ interface RPCPluginOptions {
86
90
  readonly tsConfigPath?: string;
87
91
  readonly outputDir?: string;
88
92
  readonly generateOnInit?: boolean;
93
+ readonly openapi?: OpenApiOptions | boolean;
89
94
  }
90
95
  /**
91
96
  * Comprehensive RPC plugin that combines route analysis, schema generation, and client generation
@@ -98,10 +103,14 @@ declare class RPCPlugin implements IPlugin {
98
103
  private readonly routeAnalyzer;
99
104
  private readonly schemaGenerator;
100
105
  private readonly clientGenerator;
106
+ private readonly openApiGenerator;
107
+ private readonly openApiOptions;
108
+ private project;
101
109
  private analyzedRoutes;
102
110
  private analyzedSchemas;
103
111
  private generatedInfo;
104
112
  constructor(options?: RPCPluginOptions);
113
+ private resolveOpenApiOptions;
105
114
  /**
106
115
  * Validates the plugin configuration
107
116
  */
@@ -115,9 +124,10 @@ declare class RPCPlugin implements IPlugin {
115
124
  */
116
125
  private analyzeEverything;
117
126
  /**
118
- * 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.
119
129
  */
120
- analyze(): Promise<void>;
130
+ analyze(force?: boolean): Promise<void>;
121
131
  /**
122
132
  * Get the analyzed routes
123
133
  */
@@ -130,6 +140,10 @@ declare class RPCPlugin implements IPlugin {
130
140
  * Get the generation info
131
141
  */
132
142
  getGenerationInfo(): GeneratedClientInfo | null;
143
+ /**
144
+ * Checks whether expected output files exist on disk
145
+ */
146
+ private outputFilesExist;
133
147
  /**
134
148
  * Cleanup resources to prevent memory leaks
135
149
  */
@@ -184,26 +198,50 @@ declare class ClientGeneratorService {
184
198
  private analyzeRouteParameters;
185
199
  }
186
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
+ }
187
211
  /**
188
- * Service for analyzing controller methods and extracting type information
212
+ * Service for generating OpenAPI 3.0.3 specifications from analyzed routes and schemas
189
213
  */
190
- declare class RouteAnalyzerService {
191
- private readonly controllerPattern;
192
- private readonly tsConfigPath;
193
- constructor(controllerPattern: string, tsConfigPath: string);
194
- private projects;
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;
195
225
  /**
196
- * Analyzes controller methods to extract type information
226
+ * Converts Express-style `:param` path to OpenAPI `{param}` syntax
197
227
  */
198
- analyzeControllerMethods(): Promise<ExtendedRouteInfo[]>;
228
+ private toOpenApiPath;
229
+ private tsTypeToJsonSchema;
199
230
  /**
200
- * Creates a new ts-morph project
231
+ * Extracts the base type name from a TS type string, stripping
232
+ * wrappers like `Partial<...>`, `...[]`, `Promise<...>`.
201
233
  */
202
- private createProject;
234
+ private extractBaseTypeName;
235
+ }
236
+
237
+ /**
238
+ * Service for analyzing controller methods and extracting type information
239
+ */
240
+ declare class RouteAnalyzerService {
203
241
  /**
204
- * Cleanup resources to prevent memory leaks
242
+ * Analyzes controller methods to extract type information
205
243
  */
206
- dispose(): void;
244
+ analyzeControllerMethods(project: Project): Promise<ExtendedRouteInfo[]>;
207
245
  /**
208
246
  * Finds controller classes in the project
209
247
  */
@@ -233,19 +271,10 @@ declare class SchemaGeneratorService {
233
271
  private readonly controllerPattern;
234
272
  private readonly tsConfigPath;
235
273
  constructor(controllerPattern: string, tsConfigPath: string);
236
- private projects;
237
274
  /**
238
275
  * Generates JSON schemas from types used in controllers
239
276
  */
240
- generateSchemas(): Promise<SchemaInfo[]>;
241
- /**
242
- * Creates a new ts-morph project
243
- */
244
- private createProject;
245
- /**
246
- * Cleanup resources to prevent memory leaks
247
- */
248
- dispose(): void;
277
+ generateSchemas(project: Project): Promise<SchemaInfo[]>;
249
278
  /**
250
279
  * Collects types from controller files
251
280
  */
@@ -264,6 +293,26 @@ declare class SchemaGeneratorService {
264
293
  private generateSchemaForType;
265
294
  }
266
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
+
267
316
  /**
268
317
  * Builds the full path with parameter placeholders
269
318
  */
@@ -295,10 +344,6 @@ declare function camelCase(str: string): string;
295
344
  * Extracts a named type from a TypeScript type
296
345
  */
297
346
  declare function extractNamedType(type: Type): string | null;
298
- /**
299
- * Generates type imports for the client
300
- */
301
- declare function generateTypeImports(routes: readonly any[]): string;
302
347
 
303
348
  /**
304
349
  * Default configuration options for the RPCPlugin
@@ -326,4 +371,4 @@ declare const BUILTIN_TYPES: Set<string>;
326
371
  */
327
372
  declare const GENERIC_TYPES: Set<string>;
328
373
 
329
- export { ApiError, BUILTIN_TYPES, BUILTIN_UTILITY_TYPES, ClientGeneratorService, type ControllerGroups, DEFAULT_OPTIONS, type ExtendedRouteInfo, type FetchFunction, GENERIC_TYPES, type GeneratedClientInfo, LOG_PREFIX, type ParameterMetadataWithType, RPCPlugin, type RPCPluginOptions, type RequestOptions, RouteAnalyzerService, type RouteParameter, SchemaGeneratorService, type SchemaInfo, buildFullApiPath, buildFullPath, camelCase, extractNamedType, generateTypeImports, generateTypeScriptInterface, mapJsonSchemaTypeToTypeScript, safeToString };
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 };