@type-crafter/mcp 0.5.0 → 1.0.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/src/SPEC_RULES.md DELETED
@@ -1,1527 +0,0 @@
1
- # Type Crafter YAML Specification Rules
2
-
3
- Complete guide for writing Type Crafter YAML specifications and understanding TypeScript generation.
4
-
5
- ---
6
-
7
- ## Table of Contents
8
-
9
- - [🚨 Common Mistakes (Read This First)](#-common-mistakes-read-this-first)
10
- - [Multi-File Specifications](#multi-file-specifications)
11
- - [Root Structure](#root-structure)
12
- - [Data Types & Type Mapping](#data-types--type-mapping)
13
- - [Constraints & Limitations](#constraints--limitations)
14
- - [Nullable Types (Critical)](#nullable-types-critical)
15
- - [Type Definitions](#type-definitions)
16
- - [References](#references)
17
- - [Composition](#composition)
18
- - [TypeScript Generation Examples](#typescript-generation-examples)
19
- - [Best Practices](#best-practices)
20
- - [Common Patterns](#common-patterns)
21
- - [Rules Checklist](#rules-checklist)
22
-
23
- ---
24
-
25
- ## 🚨 Common Mistakes (Read This First)
26
-
27
- ### ❌ NEVER Do These
28
-
29
- ```yaml
30
- # ❌ WRONG: Adding 'nullable: true' property
31
- User:
32
- type: object
33
- properties:
34
- name:
35
- type: string
36
- nullable: true # ❌ INVALID! This property does NOT exist
37
-
38
- # ❌ WRONG: Using 'optional: true' property
39
- User:
40
- type: object
41
- properties:
42
- name:
43
- type: string
44
- optional: true # ❌ INVALID! This property does NOT exist
45
-
46
- # ❌ WRONG: Using '?' suffix for optional
47
- User:
48
- type: object
49
- properties:
50
- name?: # ❌ INVALID! Don't use ? suffix
51
- type: string
52
-
53
- # ❌ WRONG: Creating top-level array types
54
- Tags:
55
- type: array # ❌ INVALID! Arrays cannot be top-level types
56
- items:
57
- type: string
58
-
59
- # ❌ WRONG: Using relative paths from current file
60
- # File: src/api/users.yaml
61
- User:
62
- type: object
63
- properties:
64
- profile:
65
- $ref: './profile.yaml#/Profile' # ❌ WRONG! Not relative to current file
66
- ```
67
-
68
- ### ✅ CORRECT Ways
69
-
70
- ```yaml
71
- # ✅ CORRECT: Use 'required' array to control nullable
72
- User:
73
- type: object
74
- required:
75
- - id # id is required (NOT nullable)
76
- # name is NOT in required, so it's nullable
77
- properties:
78
- id:
79
- type: string # Generates: string
80
- name:
81
- type: string # Generates: string | null (because not in required)
82
-
83
- # ✅ CORRECT: Arrays must be properties within objects
84
- Post:
85
- type: object
86
- properties:
87
- tags:
88
- type: array
89
- items:
90
- type: string
91
-
92
- # ✅ CORRECT: Use paths from project root
93
- # File: src/api/users.yaml (running type-crafter from project root)
94
- User:
95
- type: object
96
- properties:
97
- profile:
98
- $ref: './src/api/profile.yaml#/Profile' # ✅ From project root
99
- ```
100
-
101
- ### 🔑 Key Rules to Remember
102
-
103
- 1. **Nullable is controlled by `required` array ONLY**
104
- - In `required` → generates `Type`
105
- - NOT in `required` → generates `Type | null`
106
- - No properties like `nullable`, `optional`, `?` exist
107
-
108
- 2. **Arrays cannot be top-level types**
109
- - Arrays MUST be properties within objects
110
- - Use `type: array` with `items` specification
111
-
112
- 3. **File paths are from project root**
113
- - NOT relative to current YAML file
114
- - Always use `./path/from/root/file.yaml#/Type`
115
-
116
- 4. **Every spec file needs `info` section**
117
- - Even sub-files need `info: { version, title }`
118
- - Top-level file and all referenced files must have `info`
119
-
120
- ---
121
-
122
- ## Multi-File Specifications
123
-
124
- ### File Organization Patterns
125
-
126
- #### Pattern 1: Single Top-Level File
127
-
128
- **Best for:** Small to medium projects
129
-
130
- ```
131
- project/
132
- ├── types.yaml # Single file with all types
133
- └── src/
134
- └── index.ts
135
- ```
136
-
137
- **types.yaml:**
138
- ```yaml
139
- info:
140
- version: '1.0.0'
141
- title: 'Project Types'
142
-
143
- types:
144
- User:
145
- type: object
146
- properties:
147
- id: { type: string }
148
-
149
- Post:
150
- type: object
151
- properties:
152
- author: { $ref: '#/types/User' }
153
- ```
154
-
155
- #### Pattern 2: Multiple Files with Main Entry Point
156
-
157
- **Best for:** Large projects with logical domain separation
158
-
159
- ```
160
- project/
161
- ├── types/
162
- │ ├── index.yaml # Main entry point (top-level file)
163
- │ ├── user.yaml # User-related types (sub-file)
164
- │ ├── post.yaml # Post-related types (sub-file)
165
- │ └── comment.yaml # Comment-related types (sub-file)
166
- └── src/
167
- └── index.ts
168
- ```
169
-
170
- **types/index.yaml (Top-level file):**
171
- ```yaml
172
- info:
173
- version: '1.0.0'
174
- title: 'Main API Types'
175
-
176
- # Import types from other files
177
- types:
178
- # Reference to external file (from project root)
179
- User:
180
- $ref: './types/user.yaml#/User'
181
-
182
- Post:
183
- $ref: './types/post.yaml#/Post'
184
-
185
- Comment:
186
- $ref: './types/comment.yaml#/Comment'
187
- ```
188
-
189
- **types/user.yaml (Sub-file):**
190
- ```yaml
191
- info:
192
- version: '1.0.0'
193
- title: 'User Types'
194
-
195
- types:
196
- User:
197
- type: object
198
- required:
199
- - id
200
- - email
201
- properties:
202
- id:
203
- type: string
204
- email:
205
- type: string
206
- name:
207
- type: string # nullable (not in required)
208
- ```
209
-
210
- **types/post.yaml (Sub-file):**
211
- ```yaml
212
- info:
213
- version: '1.0.0'
214
- title: 'Post Types'
215
-
216
- types:
217
- Post:
218
- type: object
219
- required:
220
- - id
221
- - title
222
- - author
223
- properties:
224
- id:
225
- type: string
226
- title:
227
- type: string
228
- author:
229
- # Reference to user.yaml from project root
230
- $ref: './types/user.yaml#/User'
231
- ```
232
-
233
- #### Pattern 3: Grouped Types with External References
234
-
235
- **Best for:** Complex domains with many related types
236
-
237
- ```
238
- project/
239
- ├── specs/
240
- │ ├── api.yaml # Main entry point
241
- │ ├── auth/
242
- │ │ └── types.yaml # Auth domain types
243
- │ └── shop/
244
- │ ├── cart.yaml # Shopping cart types
245
- │ └── product.yaml # Product types
246
- └── src/
247
- ```
248
-
249
- **specs/api.yaml (Top-level file):**
250
- ```yaml
251
- info:
252
- version: '1.0.0'
253
- title: 'API Specification'
254
-
255
- groupedTypes:
256
- # Import entire groups from external files
257
- Auth:
258
- $ref: './specs/auth/types.yaml#/AuthTypes'
259
-
260
- Shop:
261
- Cart:
262
- $ref: './specs/shop/cart.yaml#/ShopTypes/Cart'
263
- Product:
264
- $ref: './specs/shop/product.yaml#/ShopTypes/Product'
265
- ```
266
-
267
- **specs/auth/types.yaml:**
268
- ```yaml
269
- info:
270
- version: '1.0.0'
271
- title: 'Authentication Types'
272
-
273
- groupedTypes:
274
- AuthTypes:
275
- LoginRequest:
276
- type: object
277
- required:
278
- - email
279
- - password
280
- properties:
281
- email: { type: string }
282
- password: { type: string }
283
-
284
- LoginResponse:
285
- type: object
286
- required:
287
- - token
288
- - user
289
- properties:
290
- token: { type: string }
291
- user:
292
- $ref: './specs/user.yaml#/User' # Cross-file reference
293
- ```
294
-
295
- ### Multi-File Reference Rules
296
-
297
- #### 1. Every File Needs `info` Section
298
-
299
- ```yaml
300
- # ✅ CORRECT: All files need info section
301
- info:
302
- version: '1.0.0'
303
- title: 'File Title'
304
-
305
- types:
306
- # ... your types
307
- ```
308
-
309
- #### 2. Reference Format
310
-
311
- ```yaml
312
- # Local reference (same file)
313
- $ref: '#/types/TypeName'
314
- $ref: '#/groupedTypes/GroupName/TypeName'
315
-
316
- # External reference (from project root)
317
- $ref: './path/from/root/file.yaml#/TypeName'
318
- $ref: './path/from/root/file.yaml#/GroupName/TypeName'
319
- ```
320
-
321
- #### 3. Path Resolution
322
-
323
- **CRITICAL:** All paths are from **project root** (where you run `type-crafter` command)
324
-
325
- ```bash
326
- # If you run this command from /project
327
- cd /project
328
- type-crafter generate typescript ./specs/api.yaml ./output
329
-
330
- # Then all $ref paths in ANY file are relative to /project
331
- ```
332
-
333
- **Example:**
334
- ```
335
- /project/
336
- ├── specs/
337
- │ ├── api.yaml # File A
338
- │ └── user/
339
- │ └── types.yaml # File B
340
- ```
341
-
342
- **In specs/api.yaml:**
343
- ```yaml
344
- # ✅ CORRECT: Path from project root
345
- User:
346
- $ref: './specs/user/types.yaml#/User'
347
-
348
- # ❌ WRONG: Don't use relative path from current file
349
- User:
350
- $ref: './user/types.yaml#/User'
351
- ```
352
-
353
- **In specs/user/types.yaml:**
354
- ```yaml
355
- # ✅ CORRECT: Path from project root
356
- Profile:
357
- $ref: './specs/api.yaml#/ApiTypes/Profile'
358
-
359
- # ❌ WRONG: Don't use relative path
360
- Profile:
361
- $ref: '../api.yaml#/ApiTypes/Profile'
362
- ```
363
-
364
- ### Generating Types from Multi-File Specs
365
-
366
- ```bash
367
- # Generate from top-level file (references will be resolved automatically)
368
- type-crafter generate typescript ./types/index.yaml ./output
369
-
370
- # Or from any entry point
371
- type-crafter generate typescript ./specs/api.yaml ./src/types
372
- ```
373
-
374
- All referenced files will be automatically processed and types generated.
375
-
376
- ---
377
-
378
- ## Root Structure
379
-
380
- ### Required Fields
381
-
382
- ```yaml
383
- info:
384
- version: '0.0.0' # Semver format (required)
385
- title: 'My API Types' # Specification title (required)
386
- ```
387
-
388
- ### Type Organization
389
-
390
- **At least ONE is required:**
391
-
392
- ```yaml
393
- types: {} # Flat/top-level types
394
- groupedTypes: {} # Grouped/organized types
395
- ```
396
-
397
- **Can have both:**
398
-
399
- ```yaml
400
- types:
401
- User: {}
402
- Post: {}
403
-
404
- groupedTypes:
405
- Auth:
406
- LoginRequest: {}
407
- LoginResponse: {}
408
- ```
409
-
410
- ---
411
-
412
- ## Data Types & Type Mapping
413
-
414
- ### Primitive Types → TypeScript Mapping
415
-
416
- | YAML Type | TypeScript Output | Notes |
417
- | ----------------------- | ----------------- | ------------------------------ |
418
- | `string` | `string` | Default string |
419
- | `string` (format: date) | `Date` | With format specified |
420
- | `number` | `number` | Floating point |
421
- | `integer` | `number` | TypeScript has no integer type |
422
- | `boolean` | `boolean` | |
423
- | `array` | `Type[]` | Requires `items` specification |
424
- | `object` | `{ ... }` | Custom object type |
425
- | `unknown` | `unknown` | For dynamic/any type |
426
-
427
- ### Format Modifiers
428
-
429
- ```yaml
430
- # String with format
431
- dateField:
432
- type: string
433
- format: date # Generates: Date (not string)
434
- ```
435
-
436
- ---
437
-
438
- ## Constraints & Limitations
439
-
440
- ### ❌ Arrays Cannot Be Top-Level Types
441
-
442
- Arrays can **ONLY** be used as properties within object types, never as standalone top-level types.
443
-
444
- ```yaml
445
- # ❌ INVALID - This will NOT work
446
- Tags:
447
- type: array
448
- items:
449
- type: string
450
-
451
- # ✅ VALID - Arrays must be properties
452
- Post:
453
- type: object
454
- properties:
455
- tags:
456
- type: array
457
- items:
458
- type: string
459
- ```
460
-
461
- **Why:** Type Crafter generates named types. An array alone has no semantic meaning - it must be a property that describes what the array contains.
462
-
463
- ### ✅ Valid Type Categories
464
-
465
- Only these can be top-level types:
466
-
467
- - **Objects** (`type: object` with properties)
468
- - **Enums** (`type: string/number` with enum array)
469
- - **Primitives** (string, number, boolean, unknown)
470
- - **Unions** (oneOf)
471
- - **Intersections** (allOf)
472
- - **References** ($ref)
473
-
474
- ---
475
-
476
- ## Nullable Types (Critical)
477
-
478
- ### ⚠️ IMPORTANT: Required vs Optional Properties
479
-
480
- **Properties NOT in `required` array become nullable (`Type | null`)**
481
-
482
- This is controlled EXCLUSIVELY by the `required` array. There are NO other properties or syntax for controlling nullability.
483
-
484
- ### ❌ WRONG: What NOT to Do
485
-
486
- ```yaml
487
- # ❌ WRONG: Do NOT use 'nullable' property
488
- User:
489
- type: object
490
- properties:
491
- name:
492
- type: string
493
- nullable: true # ❌ INVALID! This property does NOT exist in Type Crafter
494
-
495
- # ❌ WRONG: Do NOT use 'optional' property
496
- User:
497
- type: object
498
- properties:
499
- name:
500
- type: string
501
- optional: true # ❌ INVALID! This property does NOT exist
502
-
503
- # ❌ WRONG: Do NOT use '?' suffix
504
- User:
505
- type: object
506
- properties:
507
- name?: # ❌ INVALID! Don't use ? in property names
508
- type: string
509
-
510
- # ❌ WRONG: Do NOT use null in type
511
- User:
512
- type: object
513
- properties:
514
- name:
515
- type: [string, null] # ❌ INVALID! Don't use array of types here
516
- ```
517
-
518
- ### ✅ CORRECT: Use `required` Array Only
519
-
520
- ```yaml
521
- # ✅ CORRECT: Control nullability with 'required' array
522
- User:
523
- type: object
524
- required:
525
- - id # id is required → generates: string
526
- - email # email is required → generates: string
527
- # name is NOT in required → generates: string | null
528
- # age is NOT in required → generates: number | null
529
- properties:
530
- id:
531
- type: string
532
- email:
533
- type: string
534
- name:
535
- type: string
536
- age:
537
- type: number
538
- ```
539
-
540
- **TypeScript Output:**
541
-
542
- ```typescript
543
- export type User = {
544
- id: string; // Required (in required array)
545
- email: string; // Required (in required array)
546
- name: string | null; // Nullable (NOT in required array)
547
- age: number | null; // Nullable (NOT in required array)
548
- };
549
- ```
550
-
551
- ### Detailed Rules
552
-
553
- 1. ✅ **Property in `required` array** → Generates `Type` (NOT nullable)
554
-
555
- ```yaml
556
- User:
557
- type: object
558
- required:
559
- - name
560
- properties:
561
- name: { type: string }
562
- # Generates: name: string
563
- ```
564
-
565
- 2. ✅ **Property NOT in `required` array** → Generates `Type | null` (nullable)
566
-
567
- ```yaml
568
- User:
569
- type: object
570
- required:
571
- - id
572
- properties:
573
- id: { type: string }
574
- name: { type: string } # NOT in required
575
- # Generates: name: string | null
576
- ```
577
-
578
- 3. ✅ **No `required` array at all** → All properties are `Type | null`
579
-
580
- ```yaml
581
- User:
582
- type: object
583
- # No required array
584
- properties:
585
- id: { type: string }
586
- name: { type: string }
587
- # Generates: id: string | null, name: string | null
588
- ```
589
-
590
- 4. ✅ **Empty `required: []`** → All properties are `Type | null`
591
- ```yaml
592
- User:
593
- type: object
594
- required: [] # Empty array
595
- properties:
596
- id: { type: string }
597
- # Generates: id: string | null
598
- ```
599
-
600
- ### Complete Examples
601
-
602
- #### Example 1: All Properties Required
603
-
604
- ```yaml
605
- User:
606
- type: object
607
- required:
608
- - id
609
- - email
610
- - name
611
- - age
612
- properties:
613
- id: { type: string }
614
- email: { type: string }
615
- name: { type: string }
616
- age: { type: number }
617
- ```
618
-
619
- ```typescript
620
- // Generated TypeScript
621
- export type User = {
622
- id: string;
623
- email: string;
624
- name: string;
625
- age: number;
626
- };
627
- ```
628
-
629
- #### Example 2: Some Properties Required
630
-
631
- ```yaml
632
- User:
633
- type: object
634
- required:
635
- - id
636
- - email
637
- properties:
638
- id: { type: string }
639
- email: { type: string }
640
- name: { type: string }
641
- age: { type: number }
642
- ```
643
-
644
- ```typescript
645
- // Generated TypeScript
646
- export type User = {
647
- id: string;
648
- email: string;
649
- name: string | null;
650
- age: number | null;
651
- };
652
- ```
653
-
654
- #### Example 3: No Properties Required
655
-
656
- ```yaml
657
- User:
658
- type: object
659
- properties:
660
- id: { type: string }
661
- email: { type: string }
662
- name: { type: string }
663
- age: { type: number }
664
- ```
665
-
666
- ```typescript
667
- // Generated TypeScript - All nullable
668
- export type User = {
669
- id: string | null;
670
- email: string | null;
671
- name: string | null;
672
- age: number | null;
673
- };
674
- ```
675
-
676
- ### Nested Objects and Arrays
677
-
678
- ```yaml
679
- User:
680
- type: object
681
- required:
682
- - profile
683
- - posts
684
- properties:
685
- profile:
686
- type: object
687
- required:
688
- - name
689
- properties:
690
- name: { type: string }
691
- bio: { type: string } # NOT in profile.required
692
- posts:
693
- type: array
694
- items:
695
- type: object
696
- required:
697
- - title
698
- properties:
699
- title: { type: string }
700
- content: { type: string } # NOT in items.required
701
- ```
702
-
703
- ```typescript
704
- // Generated TypeScript
705
- export type User = {
706
- profile: {
707
- // profile is required (in User.required)
708
- name: string; // required in profile
709
- bio: string | null; // NOT required in profile
710
- };
711
- posts: Array<{
712
- // posts array is required
713
- title: string; // required in post item
714
- content: string | null; // NOT required in post item
715
- }>;
716
- };
717
- ```
718
-
719
- ---
720
-
721
- ## Type Definitions
722
-
723
- ### Object Type
724
-
725
- ```yaml
726
- User:
727
- type: object
728
- description: 'User account type' # Optional metadata
729
- example: "{ id: '123', name: 'John' }" # Optional example
730
- required:
731
- - id
732
- - email
733
- properties:
734
- id:
735
- type: string
736
- description: 'Unique identifier'
737
- example: 'user-123'
738
- email:
739
- type: string
740
- name:
741
- type: string
742
- age:
743
- type: number
744
- ```
745
-
746
- **TypeScript:**
747
-
748
- ```typescript
749
- /**
750
- * @type { User }
751
- * @description User account type
752
- * @example { id: '123', name: 'John' }
753
- */
754
- export type User = {
755
- /**
756
- * @description Unique identifier
757
- * @type { string }
758
- * @memberof User
759
- * @example user-123
760
- */
761
- id: string;
762
- email: string;
763
- name: string | null;
764
- age: number | null;
765
- };
766
- ```
767
-
768
- ### Enum Type (Top-Level)
769
-
770
- ```yaml
771
- Status:
772
- type: string
773
- description: 'User status enum'
774
- example: 'active'
775
- enum:
776
- - active
777
- - inactive
778
- - pending
779
-
780
- Priority:
781
- type: number
782
- enum:
783
- - 1
784
- - 2
785
- - 3
786
- ```
787
-
788
- **TypeScript:**
789
-
790
- ```typescript
791
- // String enum
792
- export type Status = 'active' | 'inactive' | 'pending';
793
-
794
- // Number enum
795
- export type Priority = 1 | 2 | 3;
796
- ```
797
-
798
- ### Inline Enum (Property)
799
-
800
- ```yaml
801
- User:
802
- type: object
803
- properties:
804
- role:
805
- type: string
806
- enum:
807
- - admin
808
- - user
809
- - guest
810
- ```
811
-
812
- **TypeScript:**
813
-
814
- ```typescript
815
- export type User = {
816
- role: ('admin' | 'user' | 'guest') | null;
817
- };
818
- ```
819
-
820
- ### Array Types (Property-Level Only)
821
-
822
- **⚠️ IMPORTANT: Arrays cannot be top-level types. They must be properties within an object type.**
823
-
824
- ```yaml
825
- # ❌ INVALID - Cannot create standalone array types
826
- Tags:
827
- type: array
828
- items:
829
- type: string
830
-
831
- # ✅ VALID - Arrays as properties within objects
832
- Post:
833
- type: object
834
- required:
835
- - id
836
- - tags
837
- properties:
838
- id:
839
- type: string
840
- tags:
841
- type: array
842
- items:
843
- type: string
844
- comments:
845
- type: array
846
- items:
847
- type: object
848
- properties:
849
- text:
850
- type: string
851
- relatedPosts:
852
- type: array
853
- items:
854
- $ref: '#/types/Post'
855
- ```
856
-
857
- **TypeScript:**
858
-
859
- ```typescript
860
- // Arrays only appear as properties, never as top-level types
861
- export type Post = {
862
- id: string;
863
- tags: string[];
864
- comments: { text: string | null }[] | null;
865
- relatedPosts: Post[] | null;
866
- };
867
- ```
868
-
869
- ### Nested Objects
870
-
871
- ```yaml
872
- Company:
873
- type: object
874
- required:
875
- - id
876
- - address
877
- properties:
878
- id:
879
- type: string
880
- address:
881
- type: object
882
- required:
883
- - street
884
- properties:
885
- street:
886
- type: string
887
- city:
888
- type: string
889
- zipCode:
890
- type: string
891
- ```
892
-
893
- **TypeScript:**
894
-
895
- ```typescript
896
- export type Company = {
897
- id: string;
898
- address: {
899
- street: string;
900
- city: string | null;
901
- zipCode: string | null;
902
- };
903
- };
904
- ```
905
-
906
- ### Additional Properties (Hashmap/Dictionary)
907
-
908
- ```yaml
909
- # Simple hashmap (any keys → any values)
910
- SimpleMap:
911
- type: object
912
- additionalProperties: true
913
-
914
- # Typed hashmap (string keys → string values)
915
- StringMap:
916
- type: object
917
- additionalProperties:
918
- keyType: string
919
- valueType:
920
- type: string
921
-
922
- # Number keys → Object values
923
- IdMap:
924
- type: object
925
- additionalProperties:
926
- keyType: number
927
- valueType:
928
- $ref: '#/types/User'
929
-
930
- # Properties + additional (mixed)
931
- UserWithMeta:
932
- type: object
933
- required:
934
- - id
935
- properties:
936
- id:
937
- type: string
938
- additionalProperties:
939
- keyType: string
940
- valueType:
941
- type: string
942
- ```
943
-
944
- **TypeScript:**
945
-
946
- ```typescript
947
- export type SimpleMap = {
948
- [keys: string]: unknown;
949
- };
950
-
951
- export type StringMap = {
952
- [keys: string]: string;
953
- };
954
-
955
- export type IdMap = {
956
- [keys: number]: User;
957
- };
958
-
959
- export type UserWithMeta = {
960
- id: string;
961
- [keys: string]: string; // Additional dynamic properties
962
- };
963
- ```
964
-
965
- ---
966
-
967
- ## References
968
-
969
- ### Local References (Same File)
970
-
971
- ```yaml
972
- # Reference to top-level type
973
- Post:
974
- type: object
975
- properties:
976
- author:
977
- $ref: '#/types/User'
978
-
979
- # Reference to grouped type
980
- Comment:
981
- type: object
982
- properties:
983
- author:
984
- $ref: '#/groupedTypes/Auth/UserProfile'
985
- ```
986
-
987
- **Reference Format:**
988
-
989
- - Top-level: `#/types/TypeName`
990
- - Grouped: `#/groupedTypes/GroupName/TypeName`
991
-
992
- ### External File References
993
-
994
- **⚠️ IMPORTANT: Paths are from project root, not relative to current file**
995
-
996
- ```yaml
997
- # Reference to type in another file (path from project root)
998
- Post:
999
- type: object
1000
- properties:
1001
- author:
1002
- $ref: './src/types/users.yaml#/User'
1003
-
1004
- # Reference to grouped type in another file
1005
- Comment:
1006
- type: object
1007
- properties:
1008
- metadata:
1009
- $ref: './docs/specs/common.yaml#/SharedTypes/Metadata'
1010
-
1011
- # Real-world example: Shopify cart referencing cart item
1012
- SCart:
1013
- type: object
1014
- properties:
1015
- items:
1016
- type: array
1017
- items:
1018
- $ref: './docs/specs/Cart.yaml#/Cart/SCartItem'
1019
- ```
1020
-
1021
- **Reference Format:**
1022
-
1023
- - **Path from project root:** `./path/from/root/file.yaml#/TypeName`
1024
- - External type: `./path/from/root/file.yaml#/TypeName`
1025
- - External grouped: `./path/from/root/file.yaml#/GroupName/TypeName`
1026
-
1027
- **Path Rules:**
1028
-
1029
- - Paths start with `./` and are relative to **project root** (where you run the command)
1030
- - NOT relative to the current YAML file location
1031
- - Example: If your spec is at `./src/api.yaml` and references `./src/types/user.yaml`, the path is `./src/types/user.yaml`, not `./types/user.yaml`
1032
-
1033
- ### Group References (Entire Group)
1034
-
1035
- ```yaml
1036
- groupedTypes:
1037
- # Import entire group from external file
1038
- SharedModels:
1039
- $ref: './shared.yaml#/Models'
1040
- ```
1041
-
1042
- ### Cyclic References (Self-Referencing)
1043
-
1044
- ```yaml
1045
- TreeNode:
1046
- type: object
1047
- properties:
1048
- value:
1049
- type: string
1050
- children:
1051
- type: array
1052
- items:
1053
- $ref: '#/types/TreeNode' # Self-reference allowed
1054
-
1055
- LinkedList:
1056
- type: object
1057
- properties:
1058
- value:
1059
- type: number
1060
- next:
1061
- $ref: '#/types/LinkedList' # Self-reference allowed
1062
- ```
1063
-
1064
- **TypeScript:**
1065
-
1066
- ```typescript
1067
- export type TreeNode = {
1068
- value: string | null;
1069
- children: TreeNode[] | null;
1070
- };
1071
-
1072
- export type LinkedList = {
1073
- value: number | null;
1074
- next: LinkedList | null;
1075
- };
1076
- ```
1077
-
1078
- ---
1079
-
1080
- ## Composition
1081
-
1082
- ### oneOf (Union Types)
1083
-
1084
- Creates TypeScript union: `TypeA | TypeB | TypeC`
1085
-
1086
- ```yaml
1087
- Response:
1088
- oneOf:
1089
- # Reference types
1090
- - $ref: '#/types/SuccessResponse'
1091
- - $ref: '#/types/ErrorResponse'
1092
- # Primitive types
1093
- - type: string
1094
- - type: number
1095
- # Inline enum
1096
- - type: string
1097
- enum:
1098
- - pending
1099
- - loading
1100
- # Inline object
1101
- - type: object
1102
- properties:
1103
- status:
1104
- type: string
1105
- # Array type
1106
- - type: array
1107
- items:
1108
- type: string
1109
- ```
1110
-
1111
- **TypeScript:**
1112
-
1113
- ```typescript
1114
- export type Response =
1115
- | SuccessResponse
1116
- | ErrorResponse
1117
- | string
1118
- | number
1119
- | ('pending' | 'loading')
1120
- | { status: string | null }
1121
- | string[];
1122
- ```
1123
-
1124
- ### allOf (Intersection/Merge Types)
1125
-
1126
- Creates TypeScript intersection: `TypeA & TypeB & TypeC`
1127
-
1128
- ```yaml
1129
- AdminUser:
1130
- allOf:
1131
- - $ref: '#/types/BaseUser'
1132
- - $ref: '#/types/AdminPermissions'
1133
- - type: object
1134
- properties:
1135
- adminLevel:
1136
- type: number
1137
-
1138
- # Output merges all types together
1139
- ```
1140
-
1141
- **TypeScript:**
1142
-
1143
- ```typescript
1144
- export type AdminUser = BaseUser &
1145
- AdminPermissions & {
1146
- adminLevel: number | null;
1147
- };
1148
- ```
1149
-
1150
- ---
1151
-
1152
- ## TypeScript Generation Examples
1153
-
1154
- ### Complete Example
1155
-
1156
- **YAML:**
1157
-
1158
- ```yaml
1159
- info:
1160
- version: '1.0.0'
1161
- title: 'Blog API Types'
1162
-
1163
- types:
1164
- User:
1165
- type: object
1166
- description: 'Blog user account'
1167
- required:
1168
- - id
1169
- - email
1170
- - role
1171
- properties:
1172
- id:
1173
- type: string
1174
- description: 'Unique user ID'
1175
- email:
1176
- type: string
1177
- role:
1178
- $ref: '#/types/UserRole'
1179
- profile:
1180
- type: object
1181
- properties:
1182
- name:
1183
- type: string
1184
- avatar:
1185
- type: string
1186
-
1187
- UserRole:
1188
- type: string
1189
- enum:
1190
- - admin
1191
- - editor
1192
- - viewer
1193
-
1194
- Post:
1195
- type: object
1196
- required:
1197
- - id
1198
- - title
1199
- - author
1200
- properties:
1201
- id:
1202
- type: string
1203
- title:
1204
- type: string
1205
- content:
1206
- type: string
1207
- author:
1208
- $ref: '#/types/User'
1209
- tags:
1210
- type: array
1211
- items:
1212
- type: string
1213
- metadata:
1214
- type: object
1215
- additionalProperties:
1216
- keyType: string
1217
- valueType:
1218
- type: string
1219
- ```
1220
-
1221
- **TypeScript Output:**
1222
-
1223
- ```typescript
1224
- /**
1225
- * @type { User }
1226
- * @description Blog user account
1227
- */
1228
- export type User = {
1229
- /**
1230
- * @description Unique user ID
1231
- * @type { string }
1232
- * @memberof User
1233
- */
1234
- id: string;
1235
- email: string;
1236
- role: UserRole;
1237
- profile: {
1238
- name: string | null;
1239
- avatar: string | null;
1240
- } | null;
1241
- };
1242
-
1243
- export type UserRole = 'admin' | 'editor' | 'viewer';
1244
-
1245
- export type Post = {
1246
- id: string;
1247
- title: string;
1248
- content: string | null;
1249
- author: User;
1250
- tags: string[] | null;
1251
- metadata: {
1252
- [keys: string]: string;
1253
- } | null;
1254
- };
1255
- ```
1256
-
1257
- ---
1258
-
1259
- ## Best Practices
1260
-
1261
- ### 1. Always Use `required` Array
1262
-
1263
- ```yaml
1264
- # ❌ BAD - All properties become nullable
1265
- User:
1266
- type: object
1267
- properties:
1268
- id: { type: string }
1269
- email: { type: string }
1270
-
1271
- # ✅ GOOD - Explicit required fields
1272
- User:
1273
- type: object
1274
- required:
1275
- - id
1276
- - email
1277
- properties:
1278
- id: { type: string }
1279
- email: { type: string }
1280
- ```
1281
-
1282
- ### 2. Use PascalCase for Type Names
1283
-
1284
- ```yaml
1285
- # ✅ GOOD
1286
- types:
1287
- UserProfile: {}
1288
- BlogPost: {}
1289
- APIResponse: {}
1290
-
1291
- # ❌ AVOID
1292
- types:
1293
- userProfile: {}
1294
- blog_post: {}
1295
- api-response: {}
1296
- ```
1297
-
1298
- ### 3. Group Related Types
1299
-
1300
- ```yaml
1301
- # ✅ GOOD
1302
- groupedTypes:
1303
- Auth:
1304
- LoginRequest: {}
1305
- LoginResponse: {}
1306
- RefreshToken: {}
1307
-
1308
- Users:
1309
- UserProfile: {}
1310
- UserSettings: {}
1311
- UserPreferences: {}
1312
- ```
1313
-
1314
- ### 4. Use Descriptions for Complex Types
1315
-
1316
- ```yaml
1317
- # ✅ GOOD
1318
- User:
1319
- type: object
1320
- description: 'Represents a registered user account with authentication details'
1321
- properties:
1322
- passwordHash:
1323
- type: string
1324
- description: 'Bcrypt hashed password (never expose in responses)'
1325
- ```
1326
-
1327
- ### 5. Reference External Types for Reusability
1328
-
1329
- ```yaml
1330
- # ✅ GOOD - Reuse common types (paths from project root)
1331
- Post:
1332
- type: object
1333
- properties:
1334
- author:
1335
- $ref: './src/types/common.yaml#/User'
1336
- metadata:
1337
- $ref: './src/types/common.yaml#/Metadata'
1338
-
1339
- # Real example: Shopify cart referencing item types
1340
- SCart:
1341
- type: object
1342
- properties:
1343
- items:
1344
- type: array
1345
- items:
1346
- $ref: './docs/specs/Cart.yaml#/Cart/SCartItem'
1347
- ```
1348
-
1349
- **Remember:** Paths are from project root, not relative to current file location.
1350
-
1351
- ---
1352
-
1353
- ## Common Patterns
1354
-
1355
- ### Pattern 1: Paginated Response
1356
-
1357
- ```yaml
1358
- PaginatedUsers:
1359
- type: object
1360
- required:
1361
- - data
1362
- - total
1363
- - page
1364
- properties:
1365
- data:
1366
- type: array
1367
- items:
1368
- $ref: '#/types/User'
1369
- total:
1370
- type: number
1371
- page:
1372
- type: number
1373
- perPage:
1374
- type: number
1375
- ```
1376
-
1377
- ### Pattern 2: API Response Wrapper
1378
-
1379
- ```yaml
1380
- ApiResponse:
1381
- oneOf:
1382
- - type: object
1383
- required:
1384
- - success
1385
- - data
1386
- properties:
1387
- success:
1388
- type: boolean
1389
- data:
1390
- type: unknown
1391
- - type: object
1392
- required:
1393
- - success
1394
- - error
1395
- properties:
1396
- success:
1397
- type: boolean
1398
- error:
1399
- type: string
1400
- ```
1401
-
1402
- ### Pattern 3: Timestamps Mixin
1403
-
1404
- ```yaml
1405
- Timestamped:
1406
- type: object
1407
- required:
1408
- - createdAt
1409
- - updatedAt
1410
- properties:
1411
- createdAt:
1412
- type: string
1413
- format: date
1414
- updatedAt:
1415
- type: string
1416
- format: date
1417
-
1418
- # Use with allOf
1419
- User:
1420
- allOf:
1421
- - $ref: '#/types/Timestamped'
1422
- - type: object
1423
- required:
1424
- - id
1425
- properties:
1426
- id: { type: string }
1427
- ```
1428
-
1429
- ### Pattern 4: Enum + Metadata
1430
-
1431
- ```yaml
1432
- StatusType:
1433
- type: string
1434
- enum:
1435
- - draft
1436
- - published
1437
- - archived
1438
-
1439
- Post:
1440
- type: object
1441
- required:
1442
- - status
1443
- properties:
1444
- status:
1445
- $ref: '#/types/StatusType'
1446
- statusChangedAt:
1447
- type: string
1448
- format: date
1449
- ```
1450
-
1451
- ---
1452
-
1453
- ## Rules Checklist
1454
-
1455
- ### Required ✅
1456
-
1457
- - [ ] Has `info.version` (string)
1458
- - [ ] Has `info.title` (string)
1459
- - [ ] Has `types` OR `groupedTypes` (or both)
1460
-
1461
- ### Constraints ✅
1462
-
1463
- - [ ] **Arrays CANNOT be top-level types** - must be properties within objects
1464
- - [ ] Only objects, enums, primitives, unions, intersections, and references can be top-level types
1465
- - [ ] Arrays require `items` specification
1466
-
1467
- ### Type Definitions ✅
1468
-
1469
- - [ ] Objects have `type: object`
1470
- - [ ] Arrays are only used as properties (never top-level)
1471
- - [ ] Enums have `type` (string/number) with `enum` array
1472
- - [ ] Use `required` array for non-nullable properties
1473
- - [ ] Properties not in `required` become `Type | null`
1474
-
1475
- ### References ✅
1476
-
1477
- - [ ] Local references: `#/types/Name` or `#/groupedTypes/Group/Name`
1478
- - [ ] External references: `./path/from/root/file.yaml#/Name`
1479
- - [ ] **External paths are from project root, NOT relative to current file**
1480
- - [ ] Cyclic references are allowed
1481
-
1482
- ### Composition ✅
1483
-
1484
- - [ ] `oneOf` creates unions (`A | B | C`)
1485
- - [ ] `allOf` creates intersections (`A & B & C`)
1486
- - [ ] Can mix inline types and references
1487
-
1488
- ### TypeScript Generation ✅
1489
-
1490
- - [ ] `string` → `string`
1491
- - [ ] `string` (format: date) → `Date`
1492
- - [ ] `number`/`integer` → `number`
1493
- - [ ] `boolean` → `boolean`
1494
- - [ ] `array` → `Type[]`
1495
- - [ ] `object` → `{ ... }`
1496
- - [ ] `unknown` → `unknown`
1497
- - [ ] NOT in `required` → `Type | null`
1498
-
1499
- ### Best Practices ✅
1500
-
1501
- - [ ] Use PascalCase for type names
1502
- - [ ] Always specify `required` array for objects
1503
- - [ ] Group related types in `groupedTypes`
1504
- - [ ] Add descriptions for complex types
1505
- - [ ] Use references for reusability
1506
- - [ ] Prefer explicit over implicit nullability
1507
-
1508
- ---
1509
-
1510
- ## Summary
1511
-
1512
- | Concept | YAML | TypeScript |
1513
- | ----------------- | ----------------------------- | -------------------- |
1514
- | Required property | In `required` array | `prop: Type` |
1515
- | Optional property | NOT in `required` array | `prop: Type \| null` |
1516
- | String enum | `type: string, enum: [...]` | `'a' \| 'b' \| 'c'` |
1517
- | Number enum | `type: number, enum: [...]` | `1 \| 2 \| 3` |
1518
- | Union | `oneOf: [...]` | `A \| B \| C` |
1519
- | Intersection | `allOf: [...]` | `A & B & C` |
1520
- | Array | `type: array, items: {...}` | `Type[]` |
1521
- | Hashmap | `additionalProperties: {...}` | `[key: Type]: Type` |
1522
- | Reference | `$ref: '#/...'` | Type name |
1523
- | Nested object | Inline `type: object` | `{ ... }` |
1524
-
1525
- ---
1526
-
1527
- **Remember:** Properties NOT in the `required` array automatically become `Type | null` in TypeScript!