@claudetools/tools 0.3.9 → 0.5.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 +60 -4
- package/dist/cli.js +0 -0
- package/dist/codedna/generators/base.d.ts +41 -0
- package/dist/codedna/generators/base.js +102 -0
- package/dist/codedna/generators/express-api.d.ts +12 -0
- package/dist/codedna/generators/express-api.js +61 -0
- package/dist/codedna/index.d.ts +4 -0
- package/dist/codedna/index.js +7 -0
- package/dist/codedna/parser.d.ts +117 -0
- package/dist/codedna/parser.js +233 -0
- package/dist/codedna/registry.d.ts +60 -0
- package/dist/codedna/registry.js +217 -0
- package/dist/codedna/template-engine.d.ts +17 -0
- package/dist/codedna/template-engine.js +183 -0
- package/dist/codedna/types.d.ts +64 -0
- package/dist/codedna/types.js +4 -0
- package/dist/handlers/codedna-handlers.d.ts +122 -0
- package/dist/handlers/codedna-handlers.js +194 -0
- package/dist/handlers/tool-handlers.js +593 -14
- package/dist/helpers/api-client.d.ts +37 -0
- package/dist/helpers/api-client.js +70 -0
- package/dist/helpers/codedna-monitoring.d.ts +34 -0
- package/dist/helpers/codedna-monitoring.js +159 -0
- package/dist/helpers/error-tracking.d.ts +73 -0
- package/dist/helpers/error-tracking.js +164 -0
- package/dist/helpers/library-detection.d.ts +26 -0
- package/dist/helpers/library-detection.js +145 -0
- package/dist/helpers/tasks-retry.d.ts +49 -0
- package/dist/helpers/tasks-retry.js +168 -0
- package/dist/helpers/tasks.d.ts +24 -1
- package/dist/helpers/tasks.js +146 -50
- package/dist/helpers/usage-analytics.d.ts +91 -0
- package/dist/helpers/usage-analytics.js +256 -0
- package/dist/helpers/workers.d.ts +25 -0
- package/dist/helpers/workers.js +80 -0
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.js +16 -5
- package/dist/tools.js +314 -0
- package/docs/AUTO-REGISTRATION.md +353 -0
- package/docs/CLAUDE4_PROMPT_ANALYSIS.md +589 -0
- package/docs/ENTITY_DSL_REFERENCE.md +685 -0
- package/docs/MODERN_STACK_COMPLETE_GUIDE.md +706 -0
- package/docs/PROMPT_STANDARDIZATION_RESULTS.md +324 -0
- package/docs/PROMPT_TIER_TEMPLATES.md +787 -0
- package/docs/RESEARCH_METHODOLOGY_EXTRACTION.md +336 -0
- package/package.json +14 -3
- package/scripts/verify-prompt-compliance.sh +197 -0
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
# Entity DSL Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for CodeDNA's Entity DSL (Domain-Specific Language) for defining data models.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Syntax Overview](#syntax-overview)
|
|
8
|
+
2. [Field Types](#field-types)
|
|
9
|
+
3. [Constraints](#constraints)
|
|
10
|
+
4. [Relations](#relations)
|
|
11
|
+
5. [Advanced Features](#advanced-features)
|
|
12
|
+
6. [Examples](#examples)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Syntax Overview
|
|
17
|
+
|
|
18
|
+
### Basic Format
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
EntityName(field1:type:constraint, field2:type:constraint, ...)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Rules
|
|
25
|
+
|
|
26
|
+
- **Entity names** MUST start with uppercase letter (PascalCase)
|
|
27
|
+
- **Field names** MUST start with lowercase letter or underscore (camelCase)
|
|
28
|
+
- **Fields** are separated by commas
|
|
29
|
+
- **Type** and **constraints** are separated by colons
|
|
30
|
+
- Empty entities are allowed: `Entity()`
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Field Types
|
|
35
|
+
|
|
36
|
+
### Primitive Types
|
|
37
|
+
|
|
38
|
+
| Type | SQL Type | TypeScript Type | Description |
|
|
39
|
+
|------|----------|-----------------|-------------|
|
|
40
|
+
| `string` | VARCHAR(255) | string | Text string |
|
|
41
|
+
| `integer` | INTEGER | number | Whole number |
|
|
42
|
+
| `decimal` | DECIMAL(10,2) | number | Decimal number |
|
|
43
|
+
| `boolean` | BOOLEAN | boolean | True/false |
|
|
44
|
+
| `datetime` | TIMESTAMP | Date | Date and time |
|
|
45
|
+
| `email` | VARCHAR(255) | string | Email address (validation built-in) |
|
|
46
|
+
| `url` | VARCHAR(512) | string | URL (validation built-in) |
|
|
47
|
+
| `json` | JSONB | any | JSON object |
|
|
48
|
+
|
|
49
|
+
**Examples:**
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
User(name:string, age:integer, verified:boolean)
|
|
53
|
+
Product(price:decimal, createdAt:datetime)
|
|
54
|
+
Contact(email:email, website:url)
|
|
55
|
+
Config(settings:json)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Array Types
|
|
59
|
+
|
|
60
|
+
Syntax: `array(itemType)`
|
|
61
|
+
|
|
62
|
+
Supported item types: `string`, `integer`, `decimal`, `boolean`
|
|
63
|
+
|
|
64
|
+
**Examples:**
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Post(tags:array(string))
|
|
68
|
+
Stats(scores:array(integer))
|
|
69
|
+
Chart(values:array(decimal))
|
|
70
|
+
Flags(options:array(boolean))
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Generated as:**
|
|
74
|
+
- SQL: `TEXT[]`, `INTEGER[]`, etc. (PostgreSQL arrays)
|
|
75
|
+
- TypeScript: `string[]`, `number[]`, etc.
|
|
76
|
+
|
|
77
|
+
### Reference Types
|
|
78
|
+
|
|
79
|
+
#### Simple Reference
|
|
80
|
+
Syntax: `ref(EntityName)`
|
|
81
|
+
|
|
82
|
+
Foreign key to another entity.
|
|
83
|
+
|
|
84
|
+
**Example:**
|
|
85
|
+
```
|
|
86
|
+
Post(author:ref(User))
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### One-to-Many Reference
|
|
90
|
+
Syntax: `refOne(EntityName)`
|
|
91
|
+
|
|
92
|
+
Entity has one parent of this type (e.g., Post has one Author).
|
|
93
|
+
|
|
94
|
+
**Example:**
|
|
95
|
+
```
|
|
96
|
+
Post(author:refOne(User))
|
|
97
|
+
Comment(post:refOne(Post))
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Many-to-Many Reference
|
|
101
|
+
Syntax: `refMany(EntityName)`
|
|
102
|
+
|
|
103
|
+
Entity can have many of this type and vice versa (e.g., Post has many Tags, Tag has many Posts).
|
|
104
|
+
|
|
105
|
+
**Example:**
|
|
106
|
+
```
|
|
107
|
+
Post(tags:refMany(Tag))
|
|
108
|
+
Student(courses:refMany(Course))
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Generated as:**
|
|
112
|
+
- Simple/OneToMany: Foreign key column + index
|
|
113
|
+
- ManyToMany: Junction table with composite primary key
|
|
114
|
+
|
|
115
|
+
### Enum Types
|
|
116
|
+
|
|
117
|
+
Syntax: `enum(value1,value2,value3)`
|
|
118
|
+
|
|
119
|
+
Restricted set of allowed values.
|
|
120
|
+
|
|
121
|
+
**Examples:**
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
Order(status:enum(pending,paid,shipped,cancelled))
|
|
125
|
+
User(role:enum(admin,user,guest))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Generated as:**
|
|
129
|
+
- SQL: ENUM type
|
|
130
|
+
- TypeScript: Union type (`'pending' | 'paid' | 'shipped' | 'cancelled'`)
|
|
131
|
+
|
|
132
|
+
### Computed Fields
|
|
133
|
+
|
|
134
|
+
Syntax: `computed(expression)`
|
|
135
|
+
|
|
136
|
+
Virtual field calculated from other fields.
|
|
137
|
+
|
|
138
|
+
**Examples:**
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
User(fullName:computed(firstName + lastName))
|
|
142
|
+
Order(total:computed(price * quantity))
|
|
143
|
+
Product(discountedPrice:computed(price * (1 - discount)))
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Generated as:**
|
|
147
|
+
- SQL: GENERATED column or database trigger
|
|
148
|
+
- TypeScript: Getter function
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Constraints
|
|
153
|
+
|
|
154
|
+
### Simple Constraints
|
|
155
|
+
|
|
156
|
+
No parameters, just add to field definition.
|
|
157
|
+
|
|
158
|
+
| Constraint | Description | Example |
|
|
159
|
+
|------------|-------------|---------|
|
|
160
|
+
| `required` | NOT NULL | `email:string:required` |
|
|
161
|
+
| `unique` | UNIQUE constraint | `email:string:unique` |
|
|
162
|
+
| `index` | Database index | `username:string:index` |
|
|
163
|
+
| `hashed` | Bcrypt hash before save | `password:string:hashed` |
|
|
164
|
+
| `nullable` | Allows NULL | `middleName:string:nullable` |
|
|
165
|
+
| `immutable` | Cannot be updated after creation | `id:integer:immutable` |
|
|
166
|
+
| `email` | Email format validation | `contact:string:email` |
|
|
167
|
+
| `url` | URL format validation | `homepage:string:url` |
|
|
168
|
+
|
|
169
|
+
**Examples:**
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
User(email:email:unique:required, password:string:hashed:required)
|
|
173
|
+
Post(slug:string:unique:index, deletedAt:datetime:nullable)
|
|
174
|
+
Account(accountNumber:string:immutable:unique)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Parameterized Constraints
|
|
178
|
+
|
|
179
|
+
Constraints that take values.
|
|
180
|
+
|
|
181
|
+
#### min(value)
|
|
182
|
+
Minimum value for numbers, minimum length for strings.
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
User(age:integer:min(18))
|
|
186
|
+
Product(price:decimal:min(0))
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### max(value)
|
|
190
|
+
Maximum value for numbers, maximum length for strings.
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
Product(price:decimal:max(9999))
|
|
194
|
+
Rating(stars:integer:max(5))
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### default(value)
|
|
198
|
+
Default value for field.
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
User(role:enum(admin,user):default(user))
|
|
202
|
+
Post(views:integer:default(0))
|
|
203
|
+
Product(inStock:boolean:default(true))
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### length(max) or length(min,max)
|
|
207
|
+
String length constraints.
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
User(username:string:length(20))
|
|
211
|
+
User(password:string:length(8,100))
|
|
212
|
+
Bio(text:string:length(10,500))
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Generates:**
|
|
216
|
+
- SQL: CHECK constraint
|
|
217
|
+
- TypeScript: Runtime validation
|
|
218
|
+
- Frontend: Input maxLength/minLength
|
|
219
|
+
|
|
220
|
+
#### pattern(regex)
|
|
221
|
+
Regular expression validation.
|
|
222
|
+
|
|
223
|
+
Regex can be provided with or without slashes.
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
User(zipCode:string:pattern(/^\d{5}$/))
|
|
227
|
+
Product(sku:string:pattern(^[A-Z]{3}-\d{4}$))
|
|
228
|
+
User(phone:string:pattern(/^\+1\d{10}$/))
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Generates:**
|
|
232
|
+
- SQL: CHECK constraint (where supported)
|
|
233
|
+
- TypeScript: RegExp test
|
|
234
|
+
- Frontend: Input pattern attribute
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Relations
|
|
239
|
+
|
|
240
|
+
### Simple Foreign Key
|
|
241
|
+
|
|
242
|
+
Use `ref(Entity)` for a basic foreign key relationship.
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
Post(author:ref(User))
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Generates:**
|
|
249
|
+
- SQL: `author_id INTEGER REFERENCES users(id)`
|
|
250
|
+
- TypeScript: `author: User` or `authorId: number`
|
|
251
|
+
|
|
252
|
+
### One-to-Many
|
|
253
|
+
|
|
254
|
+
Use `refOne(Entity)` when entity has ONE parent.
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
Comment(post:refOne(Post), author:refOne(User))
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Real-world meaning:**
|
|
261
|
+
- Each Comment belongs to ONE Post
|
|
262
|
+
- Each Comment belongs to ONE User (author)
|
|
263
|
+
- But Post can have MANY Comments
|
|
264
|
+
- User can have MANY Comments
|
|
265
|
+
|
|
266
|
+
**Generates:**
|
|
267
|
+
- Foreign key with index
|
|
268
|
+
- Cascade delete options
|
|
269
|
+
- TypeScript navigation properties
|
|
270
|
+
|
|
271
|
+
### Many-to-Many
|
|
272
|
+
|
|
273
|
+
Use `refMany(Entity)` for many-to-many relationships.
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
Post(tags:refMany(Tag))
|
|
277
|
+
Student(courses:refMany(Course))
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Real-world meaning:**
|
|
281
|
+
- Each Post can have MANY Tags
|
|
282
|
+
- Each Tag can belong to MANY Posts
|
|
283
|
+
- Each Student can have MANY Courses
|
|
284
|
+
- Each Course can have MANY Students
|
|
285
|
+
|
|
286
|
+
**Generates:**
|
|
287
|
+
- Junction table (e.g., `post_tags`)
|
|
288
|
+
- Composite primary key
|
|
289
|
+
- Foreign keys to both entities
|
|
290
|
+
- TypeScript: `tags: Tag[]`
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Advanced Features
|
|
295
|
+
|
|
296
|
+
### Self-Referencing Entities
|
|
297
|
+
|
|
298
|
+
Entity can reference itself for hierarchical data.
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
Category(parent:ref(Category))
|
|
302
|
+
Comment(replyTo:ref(Comment))
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Generates:**
|
|
306
|
+
- Self-referential foreign key
|
|
307
|
+
- Allows NULL for root items
|
|
308
|
+
- Query methods for hierarchy traversal
|
|
309
|
+
|
|
310
|
+
### Multiple Constraints
|
|
311
|
+
|
|
312
|
+
Chain multiple constraints for complex validation.
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
User(
|
|
316
|
+
email:email:unique:required:email,
|
|
317
|
+
password:string:hashed:required:length(8,100):pattern(/^(?=.*[A-Z])(?=.*[0-9])/),
|
|
318
|
+
age:integer:required:min(18):max(120)
|
|
319
|
+
)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Complex Field Example
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
Product(
|
|
326
|
+
name:string:required:length(3,100),
|
|
327
|
+
slug:string:unique:index:pattern(/^[a-z0-9-]+$/),
|
|
328
|
+
price:decimal:required:min(0):max(999999),
|
|
329
|
+
category:refOne(Category),
|
|
330
|
+
tags:refMany(Tag),
|
|
331
|
+
inStock:boolean:default(true),
|
|
332
|
+
metadata:json:nullable
|
|
333
|
+
)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Examples
|
|
339
|
+
|
|
340
|
+
### Blog Platform
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
User(
|
|
344
|
+
email:email:unique:required,
|
|
345
|
+
username:string:unique:required:length(3,20):pattern(/^[a-zA-Z0-9_]+$/),
|
|
346
|
+
password:string:hashed:required:length(8,100),
|
|
347
|
+
bio:string:length(10,500):nullable,
|
|
348
|
+
website:url:url:nullable,
|
|
349
|
+
role:enum(admin,editor,author,reader):default(reader),
|
|
350
|
+
createdAt:datetime:required
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
Post(
|
|
354
|
+
title:string:required:length(3,200),
|
|
355
|
+
slug:string:unique:required:index:pattern(/^[a-z0-9-]+$/),
|
|
356
|
+
content:string:required,
|
|
357
|
+
excerpt:string:length(10,500):nullable,
|
|
358
|
+
author:refOne(User),
|
|
359
|
+
category:refOne(Category),
|
|
360
|
+
tags:refMany(Tag),
|
|
361
|
+
status:enum(draft,published,archived):default(draft),
|
|
362
|
+
publishedAt:datetime:nullable,
|
|
363
|
+
viewCount:integer:default(0),
|
|
364
|
+
createdAt:datetime:required,
|
|
365
|
+
updatedAt:datetime:required
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
Category(
|
|
369
|
+
name:string:unique:required:length(2,50),
|
|
370
|
+
slug:string:unique:required:index,
|
|
371
|
+
description:string:nullable,
|
|
372
|
+
parent:ref(Category)
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
Tag(
|
|
376
|
+
name:string:unique:required:length(2,30),
|
|
377
|
+
slug:string:unique:required:index
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
Comment(
|
|
381
|
+
content:string:required:length(1,1000),
|
|
382
|
+
author:refOne(User),
|
|
383
|
+
post:refOne(Post),
|
|
384
|
+
replyTo:ref(Comment),
|
|
385
|
+
status:enum(pending,approved,spam):default(pending),
|
|
386
|
+
createdAt:datetime:required
|
|
387
|
+
)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### E-Commerce Store
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
Product(
|
|
394
|
+
name:string:required:length(3,200),
|
|
395
|
+
sku:string:unique:required:index:pattern(/^[A-Z]{3}-\d{6}$/),
|
|
396
|
+
description:string:required,
|
|
397
|
+
price:decimal:required:min(0):max(999999.99),
|
|
398
|
+
compareAtPrice:decimal:min(0):nullable,
|
|
399
|
+
cost:decimal:min(0):nullable,
|
|
400
|
+
stock:integer:min(0):default(0),
|
|
401
|
+
category:refOne(Category),
|
|
402
|
+
tags:refMany(Tag),
|
|
403
|
+
images:array(string),
|
|
404
|
+
metadata:json:nullable,
|
|
405
|
+
status:enum(active,inactive,discontinued):default(active),
|
|
406
|
+
createdAt:datetime:required,
|
|
407
|
+
updatedAt:datetime:required
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
Order(
|
|
411
|
+
orderNumber:string:unique:required:immutable:pattern(/^ORD-\d{8}$/),
|
|
412
|
+
customer:refOne(User),
|
|
413
|
+
items:refMany(Product),
|
|
414
|
+
subtotal:decimal:required:min(0),
|
|
415
|
+
tax:decimal:required:min(0),
|
|
416
|
+
shipping:decimal:required:min(0),
|
|
417
|
+
total:computed(subtotal + tax + shipping),
|
|
418
|
+
status:enum(pending,paid,processing,shipped,delivered,cancelled):default(pending),
|
|
419
|
+
shippingAddress:json:required,
|
|
420
|
+
billingAddress:json:required,
|
|
421
|
+
createdAt:datetime:required,
|
|
422
|
+
updatedAt:datetime:required
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
Customer(
|
|
426
|
+
email:email:unique:required,
|
|
427
|
+
firstName:string:required:length(2,50),
|
|
428
|
+
lastName:string:required:length(2,50),
|
|
429
|
+
fullName:computed(firstName + lastName),
|
|
430
|
+
phone:string:pattern(/^\+1\d{10}$/):nullable,
|
|
431
|
+
addresses:json:nullable,
|
|
432
|
+
createdAt:datetime:required
|
|
433
|
+
)
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### SaaS Application
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
Organization(
|
|
440
|
+
name:string:required:unique:length(2,100),
|
|
441
|
+
slug:string:unique:required:index:pattern(/^[a-z0-9-]+$/),
|
|
442
|
+
plan:enum(free,starter,pro,enterprise):default(free),
|
|
443
|
+
settings:json:nullable,
|
|
444
|
+
createdAt:datetime:required
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
User(
|
|
448
|
+
email:email:unique:required,
|
|
449
|
+
password:string:hashed:required:length(8,100),
|
|
450
|
+
firstName:string:required:length(2,50),
|
|
451
|
+
lastName:string:required:length(2,50),
|
|
452
|
+
organization:refOne(Organization),
|
|
453
|
+
role:enum(owner,admin,member,guest):default(member),
|
|
454
|
+
permissions:array(string),
|
|
455
|
+
avatar:url:url:nullable,
|
|
456
|
+
lastLoginAt:datetime:nullable,
|
|
457
|
+
createdAt:datetime:required
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
Project(
|
|
461
|
+
name:string:required:length(2,100),
|
|
462
|
+
description:string:nullable,
|
|
463
|
+
organization:refOne(Organization),
|
|
464
|
+
owner:refOne(User),
|
|
465
|
+
members:refMany(User),
|
|
466
|
+
status:enum(active,archived,deleted):default(active),
|
|
467
|
+
settings:json:nullable,
|
|
468
|
+
createdAt:datetime:required
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
Task(
|
|
472
|
+
title:string:required:length(3,200),
|
|
473
|
+
description:string:nullable,
|
|
474
|
+
project:refOne(Project),
|
|
475
|
+
assignee:refOne(User),
|
|
476
|
+
status:enum(todo,in_progress,review,done):default(todo),
|
|
477
|
+
priority:enum(low,medium,high,critical):default(medium),
|
|
478
|
+
dueDate:datetime:nullable,
|
|
479
|
+
completedAt:datetime:nullable,
|
|
480
|
+
createdAt:datetime:required
|
|
481
|
+
)
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## TypeScript Type Generation
|
|
487
|
+
|
|
488
|
+
The DSL generates TypeScript types automatically:
|
|
489
|
+
|
|
490
|
+
### Input DSL:
|
|
491
|
+
|
|
492
|
+
```
|
|
493
|
+
User(
|
|
494
|
+
email:email:unique:required,
|
|
495
|
+
age:integer:min(18):nullable,
|
|
496
|
+
roles:array(string),
|
|
497
|
+
organization:refOne(Organization),
|
|
498
|
+
tags:refMany(Tag)
|
|
499
|
+
)
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Generated TypeScript:
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
interface User {
|
|
506
|
+
id: number;
|
|
507
|
+
email: string;
|
|
508
|
+
age: number | null;
|
|
509
|
+
roles: string[];
|
|
510
|
+
organizationId: number;
|
|
511
|
+
organization?: Organization;
|
|
512
|
+
tags?: Tag[];
|
|
513
|
+
createdAt: Date;
|
|
514
|
+
updatedAt: Date;
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## SQL Schema Generation
|
|
521
|
+
|
|
522
|
+
### Input DSL:
|
|
523
|
+
|
|
524
|
+
```
|
|
525
|
+
Product(
|
|
526
|
+
name:string:required:length(3,200),
|
|
527
|
+
price:decimal:required:min(0),
|
|
528
|
+
stock:integer:min(0):default(0),
|
|
529
|
+
status:enum(active,inactive):default(active)
|
|
530
|
+
)
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Generated SQL (PostgreSQL):
|
|
534
|
+
|
|
535
|
+
```sql
|
|
536
|
+
CREATE TYPE product_status AS ENUM ('active', 'inactive');
|
|
537
|
+
|
|
538
|
+
CREATE TABLE products (
|
|
539
|
+
id SERIAL PRIMARY KEY,
|
|
540
|
+
name VARCHAR(200) NOT NULL CHECK (LENGTH(name) >= 3),
|
|
541
|
+
price DECIMAL(10,2) NOT NULL CHECK (price >= 0),
|
|
542
|
+
stock INTEGER DEFAULT 0 CHECK (stock >= 0),
|
|
543
|
+
status product_status DEFAULT 'active',
|
|
544
|
+
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
545
|
+
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
546
|
+
);
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
|
|
551
|
+
## Best Practices
|
|
552
|
+
|
|
553
|
+
### 1. Use Semantic Field Types
|
|
554
|
+
|
|
555
|
+
Prefer `email` and `url` types over generic `string` when applicable.
|
|
556
|
+
|
|
557
|
+
❌ BAD:
|
|
558
|
+
```
|
|
559
|
+
User(email:string:required)
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
✅ GOOD:
|
|
563
|
+
```
|
|
564
|
+
User(email:email:required)
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### 2. Add Validation Constraints
|
|
568
|
+
|
|
569
|
+
Use `length`, `pattern`, `min`, `max` for data integrity.
|
|
570
|
+
|
|
571
|
+
❌ BAD:
|
|
572
|
+
```
|
|
573
|
+
User(username:string)
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
✅ GOOD:
|
|
577
|
+
```
|
|
578
|
+
User(username:string:required:length(3,20):pattern(/^[a-zA-Z0-9_]+$/))
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### 3. Use Appropriate Relation Types
|
|
582
|
+
|
|
583
|
+
Choose `ref`, `refOne`, or `refMany` based on cardinality.
|
|
584
|
+
|
|
585
|
+
❌ BAD (ambiguous):
|
|
586
|
+
```
|
|
587
|
+
Post(author:ref(User), tags:ref(Tag))
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
✅ GOOD (explicit):
|
|
591
|
+
```
|
|
592
|
+
Post(author:refOne(User), tags:refMany(Tag))
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### 4. Add Indexes for Lookups
|
|
596
|
+
|
|
597
|
+
Use `:index` on fields used in WHERE clauses.
|
|
598
|
+
|
|
599
|
+
```
|
|
600
|
+
User(email:email:unique:index, username:string:unique:index)
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### 5. Use Computed Fields for Derived Data
|
|
604
|
+
|
|
605
|
+
Don't store data that can be calculated.
|
|
606
|
+
|
|
607
|
+
❌ BAD:
|
|
608
|
+
```
|
|
609
|
+
Order(subtotal:decimal, tax:decimal, shipping:decimal, total:decimal)
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
✅ GOOD:
|
|
613
|
+
```
|
|
614
|
+
Order(subtotal:decimal, tax:decimal, shipping:decimal, total:computed(subtotal + tax + shipping))
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## Migration from v0.3.x
|
|
620
|
+
|
|
621
|
+
If you're upgrading from CodeDNA v0.3.x:
|
|
622
|
+
|
|
623
|
+
### Breaking Changes
|
|
624
|
+
|
|
625
|
+
None! All v0.3.x syntax remains valid.
|
|
626
|
+
|
|
627
|
+
### New Features Available
|
|
628
|
+
|
|
629
|
+
| Feature | Old Syntax | New Syntax |
|
|
630
|
+
|---------|-----------|-----------|
|
|
631
|
+
| Email | `email:string` | `email:email` |
|
|
632
|
+
| URL | `website:string` | `website:url` |
|
|
633
|
+
| JSON | N/A | `settings:json` |
|
|
634
|
+
| Arrays | N/A | `tags:array(string)` |
|
|
635
|
+
| One-to-Many | `author:ref(User)` | `author:refOne(User)` (more explicit) |
|
|
636
|
+
| Many-to-Many | N/A | `tags:refMany(Tag)` |
|
|
637
|
+
| Computed | N/A | `total:computed(price * qty)` |
|
|
638
|
+
| Length | N/A | `name:string:length(3,100)` |
|
|
639
|
+
| Pattern | N/A | `code:string:pattern(/^[A-Z]+$/)` |
|
|
640
|
+
| Nullable | N/A | `middleName:string:nullable` |
|
|
641
|
+
| Immutable | N/A | `id:integer:immutable` |
|
|
642
|
+
|
|
643
|
+
---
|
|
644
|
+
|
|
645
|
+
## Cheat Sheet
|
|
646
|
+
|
|
647
|
+
### Quick Reference
|
|
648
|
+
|
|
649
|
+
```
|
|
650
|
+
# Primitive Types
|
|
651
|
+
string, integer, decimal, boolean, datetime, email, url, json
|
|
652
|
+
|
|
653
|
+
# Array Types
|
|
654
|
+
array(string), array(integer), array(decimal), array(boolean)
|
|
655
|
+
|
|
656
|
+
# Reference Types
|
|
657
|
+
ref(Entity) # Simple foreign key
|
|
658
|
+
refOne(Entity) # One-to-many (this entity has one parent)
|
|
659
|
+
refMany(Entity) # Many-to-many (bidirectional)
|
|
660
|
+
|
|
661
|
+
# Enum
|
|
662
|
+
enum(val1,val2,val3)
|
|
663
|
+
|
|
664
|
+
# Computed
|
|
665
|
+
computed(expression)
|
|
666
|
+
|
|
667
|
+
# Simple Constraints
|
|
668
|
+
required, unique, index, hashed, nullable, immutable, email, url
|
|
669
|
+
|
|
670
|
+
# Parameterized Constraints
|
|
671
|
+
min(value) # Minimum value/length
|
|
672
|
+
max(value) # Maximum value/length
|
|
673
|
+
default(value) # Default value
|
|
674
|
+
length(max) # Max length
|
|
675
|
+
length(min,max) # Min and max length
|
|
676
|
+
pattern(regex) # Regex validation
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
---
|
|
680
|
+
|
|
681
|
+
## Support
|
|
682
|
+
|
|
683
|
+
For questions, issues, or feature requests:
|
|
684
|
+
- GitHub: [claudetools/tools](https://github.com/claudetools/tools)
|
|
685
|
+
- Documentation: [CodeDNA Docs](https://docs.claudetools.dev/codedna)
|