@type-crafter/mcp 0.6.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/README.md +114 -208
- package/dist/docs/RULES_COMPOSITION.md +343 -0
- package/dist/docs/RULES_NULLABLE.md +293 -0
- package/dist/docs/RULES_PATTERNS.md +516 -0
- package/dist/docs/RULES_REFERENCES.md +302 -0
- package/dist/docs/RULES_STRUCTURE.md +248 -0
- package/dist/docs/RULES_TYPES.md +291 -0
- package/dist/docs/WRITING_GUIDE.md +179 -0
- package/dist/index.js +321 -345
- package/package.json +3 -5
- package/src/GUIDE.md +0 -459
- package/src/SPEC_RULES.md +0 -1755
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# References Rules
|
|
2
|
+
|
|
3
|
+
## Reference Syntax
|
|
4
|
+
|
|
5
|
+
References use `$ref` to point to other types:
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
$ref: '#/types/TypeName' # Same file, top-level type
|
|
9
|
+
$ref: '#/groupedTypes/Group/Type' # Same file, grouped type
|
|
10
|
+
$ref: './path/file.yaml#/TypeName' # External file
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Top File vs Non-Top File (CRITICAL)
|
|
16
|
+
|
|
17
|
+
### Identifying File Type
|
|
18
|
+
|
|
19
|
+
**Top File** = Has `info` section at root:
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
info:
|
|
23
|
+
version: '1.0.0'
|
|
24
|
+
title: 'My Types'
|
|
25
|
+
types:
|
|
26
|
+
User: { ... }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Non-Top File** = No `info` section:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
# No info section here
|
|
33
|
+
UserTypes:
|
|
34
|
+
User: { ... }
|
|
35
|
+
Profile: { ... }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Reference Rules by File Type
|
|
39
|
+
|
|
40
|
+
| File Type | Same-File Reference | External Reference |
|
|
41
|
+
| ------------ | ---------------------------------- | -------------------------- |
|
|
42
|
+
| Top File | `#/types/Name` | `'./path/file.yaml#/Name'` |
|
|
43
|
+
| Non-Top File | `'./path/to/this-file.yaml#/Name'` | `'./path/file.yaml#/Name'` |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Top File References
|
|
48
|
+
|
|
49
|
+
In a file WITH `info` section:
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
# types.yaml (TOP FILE)
|
|
53
|
+
info:
|
|
54
|
+
version: '1.0.0'
|
|
55
|
+
title: 'API Types'
|
|
56
|
+
|
|
57
|
+
types:
|
|
58
|
+
User:
|
|
59
|
+
type: object
|
|
60
|
+
properties:
|
|
61
|
+
profile:
|
|
62
|
+
$ref: '#/types/Profile' # Same-file reference
|
|
63
|
+
|
|
64
|
+
Profile:
|
|
65
|
+
type: object
|
|
66
|
+
properties:
|
|
67
|
+
bio: { type: string }
|
|
68
|
+
|
|
69
|
+
groupedTypes:
|
|
70
|
+
Auth:
|
|
71
|
+
LoginResponse:
|
|
72
|
+
type: object
|
|
73
|
+
properties:
|
|
74
|
+
user:
|
|
75
|
+
$ref: '#/types/User' # Reference to types section
|
|
76
|
+
session:
|
|
77
|
+
$ref: '#/groupedTypes/Auth/Session' # Same group
|
|
78
|
+
|
|
79
|
+
Session:
|
|
80
|
+
type: object
|
|
81
|
+
properties:
|
|
82
|
+
token: { type: string }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Non-Top File References
|
|
88
|
+
|
|
89
|
+
In a file WITHOUT `info` section, you MUST use full paths for EVERYTHING:
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
# shared/cart.yaml (NON-TOP FILE - no info section)
|
|
93
|
+
Cart:
|
|
94
|
+
CartItem:
|
|
95
|
+
type: object
|
|
96
|
+
required:
|
|
97
|
+
- product
|
|
98
|
+
properties:
|
|
99
|
+
product:
|
|
100
|
+
# MUST use full path even for same-file reference
|
|
101
|
+
$ref: './shared/cart.yaml#/Cart/Product'
|
|
102
|
+
quantity:
|
|
103
|
+
type: number
|
|
104
|
+
|
|
105
|
+
Product:
|
|
106
|
+
type: object
|
|
107
|
+
properties:
|
|
108
|
+
name: { type: string }
|
|
109
|
+
price: { type: number }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Why?** Non-top files have no root context. The parser needs the full path to resolve references.
|
|
113
|
+
|
|
114
|
+
### Common Mistake in Non-Top Files
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
# shared/cart.yaml (NON-TOP FILE)
|
|
118
|
+
Cart:
|
|
119
|
+
CartItem:
|
|
120
|
+
type: object
|
|
121
|
+
properties:
|
|
122
|
+
product:
|
|
123
|
+
$ref: '#/Cart/Product' # WRONG! Missing file path
|
|
124
|
+
|
|
125
|
+
product:
|
|
126
|
+
$ref: './shared/cart.yaml#/Cart/Product' # CORRECT
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## External File References
|
|
132
|
+
|
|
133
|
+
### Path Rules
|
|
134
|
+
|
|
135
|
+
1. **Paths are from project root** (where you run `type-crafter` CLI)
|
|
136
|
+
2. **Always start with `./`**
|
|
137
|
+
3. **Never use `../`** for relative navigation
|
|
138
|
+
|
|
139
|
+
### Project Structure Example
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
my-project/ # <- Run CLI from here
|
|
143
|
+
specs/
|
|
144
|
+
api.yaml # Top file
|
|
145
|
+
auth/
|
|
146
|
+
types.yaml # Non-top file
|
|
147
|
+
shop/
|
|
148
|
+
cart.yaml # Non-top file
|
|
149
|
+
product.yaml # Non-top file
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### References in api.yaml (top file)
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
# specs/api.yaml
|
|
156
|
+
info:
|
|
157
|
+
version: '1.0.0'
|
|
158
|
+
title: 'API'
|
|
159
|
+
|
|
160
|
+
groupedTypes:
|
|
161
|
+
Auth:
|
|
162
|
+
$ref: './specs/auth/types.yaml#/AuthTypes'
|
|
163
|
+
|
|
164
|
+
Shop:
|
|
165
|
+
Cart:
|
|
166
|
+
$ref: './specs/shop/cart.yaml#/Cart'
|
|
167
|
+
Product:
|
|
168
|
+
$ref: './specs/shop/product.yaml#/Product'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### References in cart.yaml (non-top file)
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
# specs/shop/cart.yaml (NON-TOP FILE)
|
|
175
|
+
Cart:
|
|
176
|
+
CartItem:
|
|
177
|
+
type: object
|
|
178
|
+
properties:
|
|
179
|
+
product:
|
|
180
|
+
# Reference to another non-top file
|
|
181
|
+
$ref: './specs/shop/product.yaml#/Product/ProductInfo'
|
|
182
|
+
|
|
183
|
+
# Same-file reference - still needs full path!
|
|
184
|
+
discount:
|
|
185
|
+
$ref: './specs/shop/cart.yaml#/Cart/Discount'
|
|
186
|
+
|
|
187
|
+
Discount:
|
|
188
|
+
type: object
|
|
189
|
+
properties:
|
|
190
|
+
amount: { type: number }
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### WRONG: Using Relative Paths
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
# specs/shop/cart.yaml
|
|
197
|
+
Cart:
|
|
198
|
+
CartItem:
|
|
199
|
+
type: object
|
|
200
|
+
properties:
|
|
201
|
+
product:
|
|
202
|
+
# WRONG - Don't use ../
|
|
203
|
+
$ref: '../product.yaml#/Product'
|
|
204
|
+
|
|
205
|
+
# CORRECT - From project root
|
|
206
|
+
$ref: './specs/shop/product.yaml#/Product'
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Referencing Entire Groups
|
|
212
|
+
|
|
213
|
+
You can reference an entire group, not just individual types:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
# api.yaml (top file)
|
|
217
|
+
info:
|
|
218
|
+
version: '1.0.0'
|
|
219
|
+
title: 'API'
|
|
220
|
+
|
|
221
|
+
groupedTypes:
|
|
222
|
+
# Import entire Auth group from external file
|
|
223
|
+
Auth:
|
|
224
|
+
$ref: './specs/auth/types.yaml#/AuthTypes'
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
```yaml
|
|
228
|
+
# specs/auth/types.yaml (can be top or non-top)
|
|
229
|
+
AuthTypes:
|
|
230
|
+
LoginRequest:
|
|
231
|
+
type: object
|
|
232
|
+
properties:
|
|
233
|
+
email: { type: string }
|
|
234
|
+
|
|
235
|
+
LoginResponse:
|
|
236
|
+
type: object
|
|
237
|
+
properties:
|
|
238
|
+
token: { type: string }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Cyclic/Self References
|
|
244
|
+
|
|
245
|
+
Types can reference themselves (useful for trees, linked lists):
|
|
246
|
+
|
|
247
|
+
```yaml
|
|
248
|
+
TreeNode:
|
|
249
|
+
type: object
|
|
250
|
+
required:
|
|
251
|
+
- value
|
|
252
|
+
properties:
|
|
253
|
+
value:
|
|
254
|
+
type: string
|
|
255
|
+
children:
|
|
256
|
+
type: array
|
|
257
|
+
items:
|
|
258
|
+
$ref: '#/types/TreeNode' # Self-reference
|
|
259
|
+
|
|
260
|
+
LinkedList:
|
|
261
|
+
type: object
|
|
262
|
+
properties:
|
|
263
|
+
value:
|
|
264
|
+
type: number
|
|
265
|
+
next:
|
|
266
|
+
$ref: '#/types/LinkedList' # Self-reference
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**TypeScript:**
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
export type TreeNode = {
|
|
273
|
+
value: string;
|
|
274
|
+
children: TreeNode[] | null;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export type LinkedList = {
|
|
278
|
+
value: number | null;
|
|
279
|
+
next: LinkedList | null;
|
|
280
|
+
};
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Reference Path Formats
|
|
286
|
+
|
|
287
|
+
| Context | Format | Example |
|
|
288
|
+
| ---------------------------- | --------------------------- | -------------------------------------- |
|
|
289
|
+
| Top file, same file, types | `#/types/Name` | `$ref: '#/types/User'` |
|
|
290
|
+
| Top file, same file, grouped | `#/groupedTypes/Group/Name` | `$ref: '#/groupedTypes/Auth/Token'` |
|
|
291
|
+
| Top file, external | `'./path/file.yaml#/...'` | `$ref: './shared/types.yaml#/User'` |
|
|
292
|
+
| Non-top file, ANY reference | `'./path/file.yaml#/...'` | `$ref: './this/file.yaml#/Group/Type'` |
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Checklist
|
|
297
|
+
|
|
298
|
+
- [ ] Is this a top file or non-top file?
|
|
299
|
+
- [ ] If non-top: Am I using full paths for ALL references?
|
|
300
|
+
- [ ] Are paths from project root (not relative to current file)?
|
|
301
|
+
- [ ] Do paths start with `./`?
|
|
302
|
+
- [ ] No `../` in any path?
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Structure Rules
|
|
2
|
+
|
|
3
|
+
## Root Structure
|
|
4
|
+
|
|
5
|
+
Every Type Crafter spec file has this structure:
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
info:
|
|
9
|
+
version: '1.0.0' # Required - semver format
|
|
10
|
+
title: 'My Types' # Required - descriptive title
|
|
11
|
+
|
|
12
|
+
types: # Optional - flat/top-level types
|
|
13
|
+
TypeName: { ... }
|
|
14
|
+
|
|
15
|
+
groupedTypes: # Optional - organized into namespaces
|
|
16
|
+
GroupName:
|
|
17
|
+
TypeName: { ... }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Rule:** At least ONE of `types` or `groupedTypes` is required.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## The `info` Section
|
|
25
|
+
|
|
26
|
+
```yaml
|
|
27
|
+
info:
|
|
28
|
+
version: '1.0.0' # String, semver format
|
|
29
|
+
title: 'API Types' # String, describes the spec
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Both fields are **required**. Without them, the file is a "non-top file" with different reference rules.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Top File vs Non-Top File
|
|
37
|
+
|
|
38
|
+
### Top File (has `info` section)
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
# top-file.yaml
|
|
42
|
+
info:
|
|
43
|
+
version: '1.0.0'
|
|
44
|
+
title: 'Main Types'
|
|
45
|
+
|
|
46
|
+
types:
|
|
47
|
+
User:
|
|
48
|
+
type: object
|
|
49
|
+
properties:
|
|
50
|
+
profile:
|
|
51
|
+
$ref: '#/types/Profile' # Can use #/ for same-file refs
|
|
52
|
+
Profile:
|
|
53
|
+
type: object
|
|
54
|
+
properties:
|
|
55
|
+
bio: { type: string }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Rules for top files:**
|
|
59
|
+
|
|
60
|
+
- Can use `#/types/TypeName` for same-file references
|
|
61
|
+
- Can use `#/groupedTypes/Group/TypeName` for grouped types
|
|
62
|
+
- Can be used directly with `type-crafter generate` CLI
|
|
63
|
+
|
|
64
|
+
### Non-Top File (no `info` section)
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
# shared/cart.yaml - NO info section
|
|
68
|
+
Cart:
|
|
69
|
+
CartItem:
|
|
70
|
+
type: object
|
|
71
|
+
properties:
|
|
72
|
+
product:
|
|
73
|
+
# MUST use full path, even for same-file refs
|
|
74
|
+
$ref: './shared/cart.yaml#/Cart/Product'
|
|
75
|
+
Product:
|
|
76
|
+
type: object
|
|
77
|
+
properties:
|
|
78
|
+
name: { type: string }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Rules for non-top files:**
|
|
82
|
+
|
|
83
|
+
- MUST use full file paths for ALL references
|
|
84
|
+
- Cannot use `#/` alone - always include file path
|
|
85
|
+
- Cannot be used directly with CLI - must be referenced from a top file
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## `types` Section (Flat Types)
|
|
90
|
+
|
|
91
|
+
For standalone, top-level types:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
types:
|
|
95
|
+
User:
|
|
96
|
+
type: object
|
|
97
|
+
required: [id]
|
|
98
|
+
properties:
|
|
99
|
+
id: { type: string }
|
|
100
|
+
|
|
101
|
+
Status:
|
|
102
|
+
type: string
|
|
103
|
+
enum: [active, inactive]
|
|
104
|
+
|
|
105
|
+
ApiResponse:
|
|
106
|
+
oneOf:
|
|
107
|
+
- $ref: '#/types/User'
|
|
108
|
+
- type: string
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Generated TypeScript:**
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
export type User = { id: string };
|
|
115
|
+
export type Status = 'active' | 'inactive';
|
|
116
|
+
export type ApiResponse = User | string;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## `groupedTypes` Section (Namespaced Types)
|
|
122
|
+
|
|
123
|
+
For organizing related types:
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
groupedTypes:
|
|
127
|
+
Auth:
|
|
128
|
+
LoginRequest:
|
|
129
|
+
type: object
|
|
130
|
+
required: [email, password]
|
|
131
|
+
properties:
|
|
132
|
+
email: { type: string }
|
|
133
|
+
password: { type: string }
|
|
134
|
+
|
|
135
|
+
LoginResponse:
|
|
136
|
+
type: object
|
|
137
|
+
required: [token]
|
|
138
|
+
properties:
|
|
139
|
+
token: { type: string }
|
|
140
|
+
user:
|
|
141
|
+
$ref: '#/groupedTypes/Auth/User'
|
|
142
|
+
|
|
143
|
+
User:
|
|
144
|
+
type: object
|
|
145
|
+
properties:
|
|
146
|
+
id: { type: string }
|
|
147
|
+
|
|
148
|
+
Shop:
|
|
149
|
+
Product:
|
|
150
|
+
type: object
|
|
151
|
+
properties:
|
|
152
|
+
name: { type: string }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Generated TypeScript (with FolderWithFiles mode):**
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
output/
|
|
159
|
+
Auth/
|
|
160
|
+
LoginRequest.ts
|
|
161
|
+
LoginResponse.ts
|
|
162
|
+
User.ts
|
|
163
|
+
Shop/
|
|
164
|
+
Product.ts
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Combining `types` and `groupedTypes`
|
|
170
|
+
|
|
171
|
+
You can have both:
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
info:
|
|
175
|
+
version: '1.0.0'
|
|
176
|
+
title: 'Full API'
|
|
177
|
+
|
|
178
|
+
types:
|
|
179
|
+
# Shared/common types
|
|
180
|
+
Timestamp:
|
|
181
|
+
type: object
|
|
182
|
+
required: [createdAt]
|
|
183
|
+
properties:
|
|
184
|
+
createdAt: { type: string, format: date }
|
|
185
|
+
|
|
186
|
+
groupedTypes:
|
|
187
|
+
# Domain-specific types
|
|
188
|
+
Users:
|
|
189
|
+
User:
|
|
190
|
+
allOf:
|
|
191
|
+
- $ref: '#/types/Timestamp'
|
|
192
|
+
- type: object
|
|
193
|
+
properties:
|
|
194
|
+
name: { type: string }
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## File Organization Patterns
|
|
200
|
+
|
|
201
|
+
### Pattern 1: Single File (Small Projects)
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
project/
|
|
205
|
+
types.yaml # Everything in one file
|
|
206
|
+
src/
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Pattern 2: Main + Shared (Medium Projects)
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
project/
|
|
213
|
+
types/
|
|
214
|
+
index.yaml # Top file with info
|
|
215
|
+
shared.yaml # Non-top file, referenced from index
|
|
216
|
+
src/
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Pattern 3: Domain Separation (Large Projects)
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
project/
|
|
223
|
+
specs/
|
|
224
|
+
api.yaml # Top file - main entry
|
|
225
|
+
auth/
|
|
226
|
+
types.yaml # Non-top file
|
|
227
|
+
shop/
|
|
228
|
+
cart.yaml # Non-top file
|
|
229
|
+
product.yaml
|
|
230
|
+
src/
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**api.yaml (top file):**
|
|
234
|
+
|
|
235
|
+
```yaml
|
|
236
|
+
info:
|
|
237
|
+
version: '1.0.0'
|
|
238
|
+
title: 'E-Commerce API'
|
|
239
|
+
|
|
240
|
+
groupedTypes:
|
|
241
|
+
Auth:
|
|
242
|
+
$ref: './specs/auth/types.yaml#/AuthTypes'
|
|
243
|
+
Shop:
|
|
244
|
+
Cart:
|
|
245
|
+
$ref: './specs/shop/cart.yaml#/Cart'
|
|
246
|
+
Product:
|
|
247
|
+
$ref: './specs/shop/product.yaml#/Product'
|
|
248
|
+
```
|