openapi-sync 2.1.9 → 2.1.11

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
@@ -35,7 +35,11 @@
35
35
  ### 🔧 **Highly Configurable**
36
36
 
37
37
  - Customizable naming conventions for types and endpoints
38
- - Flexible output directory structure
38
+ - Exclude/include endpoints by exact path or regex patterns
39
+ - Tag-based filtering, method-specific filtering, and pattern matching
40
+ - Folder splitting configuration for organized code generation
41
+ - OperationId-based naming for better type and endpoint names
42
+ - Flexible output directory structure with custom folder organization
39
43
  - URL transformation and text replacement rules
40
44
  - Configurable documentation generation
41
45
  - Support for multiple API specifications
@@ -151,6 +155,18 @@ const config: IConfig = {
151
155
  },
152
156
  server: "https://api.example.com", // Override server URL
153
157
 
158
+ // NEW: Folder splitting configuration
159
+ folderSplit: {
160
+ byTags: true, // Create folders based on endpoint tags
161
+ customFolder: ({ method, path, tags, operationId }) => {
162
+ // Custom logic to determine folder structure
163
+ if (tags?.includes("admin")) return "admin";
164
+ if (tags?.includes("public")) return "public";
165
+ if (path.startsWith("/api/v1/")) return "v1";
166
+ return null; // Use default folder structure
167
+ },
168
+ },
169
+
154
170
  // Type generation configuration
155
171
  types: {
156
172
  name: {
@@ -201,6 +217,34 @@ const config: IConfig = {
201
217
  disable: false,
202
218
  showCurl: true, // Include cURL examples in documentation
203
219
  },
220
+ exclude: {
221
+ // Exclude endpoints by tags
222
+ tags: ["deprecated", "internal"],
223
+ // Exclude individual endpoints by path and method
224
+ endpoints: [
225
+ // Exact path match
226
+ { path: "/admin/users", method: "DELETE" },
227
+ // Regex pattern match
228
+ { regex: "^/internal/.*", method: "GET" },
229
+ { regex: ".*/debug$", method: "GET" },
230
+ // Don't specify method to exclude all methods
231
+ { path: "/debug/logs" },
232
+ ],
233
+ },
234
+ include: {
235
+ // Include endpoints by tags
236
+ tags: ["public"],
237
+ // Include individual endpoints by path and method
238
+ endpoints: [
239
+ // Exact path match
240
+ { path: "/public/users", method: "GET" },
241
+ // Regex pattern match
242
+ { regex: "^/public/.*", method: "GET" },
243
+ { regex: ".*/logs$", method: "GET" },
244
+ // Don't specify method to include all methods
245
+ { path: "/public/logs" },
246
+ ],
247
+ },
204
248
  },
205
249
  };
206
250
 
@@ -217,27 +261,81 @@ export default config;
217
261
  | `folder` | `string` | Output directory for generated files | `""` |
218
262
  | `api` | `Record<string, string>` | Map of API names to OpenAPI spec URLs | Required |
219
263
  | `server` | `number \| string` | Server index or custom server URL | `0` |
264
+ | `folderSplit` | `IConfigFolderSplit` | Configuration for folder splitting | - |
220
265
 
221
266
  #### Type Configuration (`types`)
222
267
 
223
- | Property | Type | Description |
224
- | ------------- | ---------- | ---------------------------------- |
225
- | `name.prefix` | `string` | Prefix for generated type names |
226
- | `name.format` | `function` | Custom naming function for types |
227
- | `doc.disable` | `boolean` | Disable JSDoc generation for types |
268
+ | Property | Type | Description |
269
+ | --------------------- | ---------- | ------------------------------------------------------- |
270
+ | `name.prefix` | `string` | Prefix for generated type names |
271
+ | `name.useOperationId` | `boolean` | Use OpenAPI operationId for type naming when available |
272
+ | `name.format` | `function` | Custom naming function with source context and metadata |
273
+ | `doc.disable` | `boolean` | Disable JSDoc generation for types |
274
+
275
+ **OperationId-based Type Naming:**
276
+
277
+ When `useOperationId` is set to `true`, the system will use the OpenAPI `operationId` for type naming:
278
+
279
+ - **Query Types**: `{operationId}Query` (e.g., `getUserByIdQuery`)
280
+ - **DTO Types**: `{operationId}DTO` (e.g., `createUserDTO`)
281
+ - **Response Types**: `{operationId}{code}Response` (e.g., `getUserById200Response`)
282
+
283
+ If `operationId` is not available, the system falls back to the default path-based naming convention.
228
284
 
229
285
  #### Endpoint Configuration (`endpoints`)
230
286
 
231
- | Property | Type | Description |
232
- | --------------------- | ---------------------- | -------------------------------------- |
233
- | `value.replaceWords` | `IConfigReplaceWord[]` | URL transformation rules |
234
- | `value.includeServer` | `boolean` | Include server URL in endpoints |
235
- | `value.type` | `"string" \| "object"` | Output format for endpoints |
236
- | `name.prefix` | `string` | Prefix for endpoint names |
237
- | `name.useOperationId` | `boolean` | Use OpenAPI operationId for naming |
238
- | `name.format` | `function` | Custom naming function for endpoints |
239
- | `doc.disable` | `boolean` | Disable JSDoc generation for endpoints |
240
- | `doc.showCurl` | `boolean` | Include cURL examples in documentation |
287
+ | Property | Type | Description |
288
+ | --------------------- | --------------------------------------------------------- | --------------------------------------------------------- |
289
+ | `value.replaceWords` | `IConfigReplaceWord[]` | URL transformation rules |
290
+ | `value.includeServer` | `boolean` | Include server URL in endpoints |
291
+ | `value.type` | `"string" \| "object"` | Output format for endpoints |
292
+ | `name.prefix` | `string` | Prefix for endpoint names |
293
+ | `name.useOperationId` | `boolean` | Use OpenAPI operationId for naming |
294
+ | `name.format` | `function` | Custom naming function for endpoints |
295
+ | `doc.disable` | `boolean` | Disable JSDoc generation for endpoints |
296
+ | `doc.showCurl` | `boolean` | Include cURL examples in documentation |
297
+ | `exclude.tags` | `string[]` | Exclude endpoints by tags |
298
+ | `exclude.endpoints` | `Array<{path?: string, regex?: string, method?: Method}>` | Exclude specific endpoints by exact path or regex pattern |
299
+ | `include.tags` | `string[]` | Include endpoints by tags |
300
+ | `include.endpoints` | `Array<{path?: string, regex?: string, method?: Method}>` | Include specific endpoints by exact path or regex pattern |
301
+
302
+ #### Folder Splitting Configuration (`folderSplit`)
303
+
304
+ | Property | Type | Description |
305
+ | -------------- | ---------- | --------------------------------------------- |
306
+ | `byTags` | `boolean` | Create folders based on endpoint tags |
307
+ | `customFolder` | `function` | Custom function to determine folder structure |
308
+
309
+ **Folder Splitting Examples:**
310
+
311
+ ```typescript
312
+ // Split by tags - creates folders like "admin/", "public/", "user/"
313
+ folderSplit: {
314
+ byTags: true,
315
+ }
316
+
317
+ // Custom folder logic
318
+ folderSplit: {
319
+ customFolder: ({ method, path, tags, operationId }) => {
320
+ // Admin endpoints go to admin folder
321
+ if (tags?.includes("admin")) return "admin";
322
+
323
+ // Public endpoints go to public folder
324
+ if (tags?.includes("public")) return "public";
325
+
326
+ // API versioning
327
+ if (path.startsWith("/api/v1/")) return "v1";
328
+ if (path.startsWith("/api/v2/")) return "v2";
329
+
330
+ // Method-based organization
331
+ const method = data.method.toLowerCase();
332
+ if (method === "get") return "read";
333
+ if (method === "post" || method === "PUT") return "write";
334
+
335
+ return null; // Use default structure
336
+ },
337
+ }
338
+ ```
241
339
 
242
340
  ## Usage
243
341
 
@@ -333,6 +431,8 @@ export default (): IConfig => {
333
431
 
334
432
  OpenAPI Sync generates a structured output in your specified folder:
335
433
 
434
+ ### Default Structure
435
+
336
436
  ```
337
437
  src/api/
338
438
  ├── petstore/
@@ -347,6 +447,37 @@ src/api/
347
447
  └── shared.ts
348
448
  ```
349
449
 
450
+ ### Folder Splitting Structure
451
+
452
+ When `folderSplit.byTags` is enabled or custom folder logic is used:
453
+
454
+ ```
455
+ src/api/
456
+ ├── petstore/
457
+ │ ├── admin/ # Endpoints with "admin" tag
458
+ │ │ ├── endpoints.ts
459
+ │ │ └── types/
460
+ │ │ ├── index.ts
461
+ │ │ └── shared.ts
462
+ │ ├── public/ # Endpoints with "public" tag
463
+ │ │ ├── endpoints.ts
464
+ │ │ └── types/
465
+ │ │ ├── index.ts
466
+ │ │ └── shared.ts
467
+ │ └── user/ # Endpoints with "user" tag
468
+ │ ├── endpoints.ts
469
+ │ └── types/
470
+ │ ├── index.ts
471
+ │ └── shared.ts
472
+ └── auth-api/
473
+ ├── v1/ # Custom folder logic
474
+ │ ├── endpoints.ts
475
+ │ └── types/
476
+ └── v2/
477
+ ├── endpoints.ts
478
+ └── types/
479
+ ```
480
+
350
481
  ### Generated Endpoints
351
482
 
352
483
  When `endpoints.value.type` is set to `"string"`
@@ -512,11 +643,101 @@ import {
512
643
  IOpenApiSpec,
513
644
  IOpenApSchemaSpec,
514
645
  IConfigReplaceWord,
646
+ IConfigExclude,
647
+ IConfigInclude,
648
+ IConfigDoc,
515
649
  } from "openapi-sync/types";
516
650
  ```
517
651
 
518
652
  ## Advanced Examples
519
653
 
654
+ ### Advanced Folder Splitting Configuration
655
+
656
+ ```typescript
657
+ // openapi.sync.ts
658
+ import { IConfig } from "openapi-sync/types";
659
+
660
+ const config: IConfig = {
661
+ refetchInterval: 5000,
662
+ folder: "./src/api",
663
+ api: {
664
+ "main-api": "https://api.example.com/openapi.json",
665
+ },
666
+
667
+ // Advanced folder splitting with multiple strategies
668
+ folderSplit: {
669
+ byTags: true, // Enable tag-based splitting
670
+ customFolder: ({ method, path, tags, operationId }) => {
671
+ // Priority-based folder assignment
672
+
673
+ // 1. Admin endpoints always go to admin folder
674
+ if (tags?.includes("admin")) return "admin";
675
+
676
+ // 2. Public API endpoints
677
+ if (tags?.includes("public")) return "public";
678
+
679
+ // 3. Version-based splitting
680
+ if (path.startsWith("/api/v1/")) return "v1";
681
+ if (path.startsWith("/api/v2/")) return "v2";
682
+
683
+ // 4. Method-based organization for remaining endpoints
684
+ if (method === "GET") return "read";
685
+ if (method === "POST" || method === "PUT" || method === "PATCH")
686
+ return "write";
687
+ if (method === "DELETE") return "delete";
688
+
689
+ // 5. OperationId-based splitting for specific operations
690
+ if (operationId?.includes("Auth")) return "auth";
691
+ if (operationId?.includes("User")) return "user";
692
+
693
+ return null; // Use default structure
694
+ },
695
+ },
696
+
697
+ // Enhanced type naming with operationId support
698
+ types: {
699
+ name: {
700
+ prefix: "I",
701
+ useOperationId: true, // Use operationId when available
702
+ format: (source, data, defaultName) => {
703
+ if (source === "endpoint" && data.operationId) {
704
+ // Use operationId for better naming
705
+ switch (data.type) {
706
+ case "query":
707
+ return `${data.operationId}Query`;
708
+ case "dto":
709
+ return `${data.operationId}DTO`;
710
+ case "response":
711
+ return `${data.operationId}${data.code}Response`;
712
+ }
713
+ }
714
+ return defaultName;
715
+ },
716
+ },
717
+ },
718
+
719
+ // Enhanced endpoint configuration
720
+ endpoints: {
721
+ name: {
722
+ useOperationId: true, // Use operationId for endpoint names
723
+ format: ({ operationId, method, path }, defaultName) => {
724
+ if (operationId) return operationId;
725
+ return defaultName;
726
+ },
727
+ },
728
+ exclude: {
729
+ tags: ["deprecated", "internal"],
730
+ endpoints: [
731
+ { regex: "^/internal/.*" },
732
+ { path: "/debug", method: "GET" },
733
+ ],
734
+ },
735
+ },
736
+ };
737
+
738
+ export default config;
739
+ ```
740
+
520
741
  ### Multi-Environment Configuration
521
742
 
522
743
  ```typescript
@@ -570,17 +791,33 @@ export default getConfig;
570
791
  ### Custom Type Formatting
571
792
 
572
793
  ```typescript
573
- // Advanced type name formatting
794
+ // Advanced type name formatting with operationId support
574
795
  const config: IConfig = {
575
796
  // ... other config
576
797
  types: {
577
798
  name: {
578
799
  prefix: "",
800
+ useOperationId: true, // Use operationId when available
579
801
  format: (source, data, defaultName) => {
580
802
  if (source === "shared") {
581
803
  // Shared types: UserProfile, OrderStatus, etc.
582
804
  return `${data.name}`;
583
805
  } else if (source === "endpoint") {
806
+ // Use operationId if available and configured
807
+ if (data.operationId) {
808
+ switch (data.type) {
809
+ case "query":
810
+ return `${data.operationId}Query`;
811
+ case "dto":
812
+ return `${data.operationId}DTO`;
813
+ case "response":
814
+ return `${data.operationId}${data.code}Response`;
815
+ default:
816
+ return defaultName;
817
+ }
818
+ }
819
+
820
+ // Fallback to path-based naming
584
821
  const method = data.method?.toUpperCase();
585
822
  const cleanPath = data.path
586
823
  ?.replace(/[{}\/]/g, "_")
@@ -604,6 +841,72 @@ const config: IConfig = {
604
841
  };
605
842
  ```
606
843
 
844
+ ### Endpoint Filtering and Selection
845
+
846
+ ```typescript
847
+ // Advanced endpoint filtering configuration
848
+ const config: IConfig = {
849
+ // ... other config
850
+ endpoints: {
851
+ // ... other endpoint config
852
+ exclude: {
853
+ // Exclude endpoints by tags
854
+ tags: ["deprecated", "internal", "admin"],
855
+ // Exclude specific endpoints by exact path or regex pattern
856
+ endpoints: [
857
+ // Exact path matches
858
+ { path: "/admin/users", method: "DELETE" },
859
+ { path: "/admin/settings", method: "PUT" },
860
+ // Regex pattern matches
861
+ { regex: "^/internal/.*", method: "GET" },
862
+ { regex: ".*/debug$", method: "POST" },
863
+ // Exclude all methods for a specific path
864
+ { path: "/debug/logs" },
865
+ ],
866
+ },
867
+ include: {
868
+ // Include only public endpoints
869
+ tags: ["public", "user"],
870
+ // Include specific endpoints by exact path or regex pattern
871
+ endpoints: [
872
+ // Exact path matches
873
+ { path: "/public/users", method: "GET" },
874
+ { path: "/public/profile", method: "PUT" },
875
+ // Regex pattern matches
876
+ { regex: "^/public/.*", method: "GET" },
877
+ { regex: ".*/health$", method: "GET" },
878
+ ],
879
+ },
880
+ },
881
+ };
882
+ ```
883
+
884
+ ### Path vs Regex Filtering
885
+
886
+ ```typescript
887
+ // Demonstrating the difference between path and regex filtering
888
+ const config: IConfig = {
889
+ // ... other config
890
+ endpoints: {
891
+ exclude: {
892
+ endpoints: [
893
+ // Exact path match - only excludes exactly "/api/users"
894
+ { path: "/api/users", method: "GET" },
895
+
896
+ // Regex match - excludes all paths starting with "/api/users"
897
+ { regex: "^/api/users.*", method: "GET" },
898
+
899
+ // Regex match - excludes all paths ending with "/debug"
900
+ { regex: ".*/debug$", method: "GET" },
901
+
902
+ // Regex match - excludes paths with specific pattern
903
+ { regex: "^/internal/.*/admin$", method: "POST" },
904
+ ],
905
+ },
906
+ },
907
+ };
908
+ ```
909
+
607
910
  ### URL Transformation Rules
608
911
 
609
912
  ```typescript
@@ -859,6 +1162,34 @@ The tool maintains state in `db.json` to track changes:
859
1162
 
860
1163
  ---
861
1164
 
1165
+ ## Changelog
1166
+
1167
+ ### v2.1.11 (Latest)
1168
+
1169
+ - **NEW**: Folder splitting configuration for organized code generation
1170
+ - `folderSplit.byTags` - Create folders based on endpoint tags
1171
+ - `folderSplit.customFolder` - Custom function for folder structure logic
1172
+ - Enhanced folder organization with priority-based assignment
1173
+ - Improved code organization for large APIs
1174
+
1175
+ ### v2.1.10
1176
+
1177
+ - OperationId-based naming for types and endpoints
1178
+ - `types.name.useOperationId` - Use OpenAPI operationId for type naming
1179
+ - `endpoints.name.useOperationId` - Use operationId for endpoint naming
1180
+ - Enhanced endpoint filtering capabilities
1181
+ - Improved tag-based filtering
1182
+ - Better regex pattern matching
1183
+ - More flexible include/exclude rules
1184
+ - Enhanced JSONStringify function with array serialization support
1185
+ - Improved endpoint tags support in generated documentation
1186
+
1187
+ ### Previous Versions
1188
+
1189
+ - v2.1.9: Enhanced JSONStringify function improvements
1190
+ - v2.1.8: File extension corrections and path handling
1191
+ - v2.1.7: Endpoint tags support in API documentation
1192
+
862
1193
  ## License
863
1194
 
864
1195
  This project is licensed under the ISC License - see the [LICENSE](LICENSE) file for details.