@macroforge/mcp-server 0.1.34 → 0.1.35

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.
@@ -1,281 +1,102 @@
1
1
  # Default
2
- *The `Default` macro generates a static `defaultValue()` factory method that creates instances with default values. This is analogous to Rust's `Default` trait, providing a standard way to create "zero" or "empty" instances of types.*
3
- ## Basic Usage
4
- **Before:**
5
- ```
6
- /** @derive(Default) */
7
- class Config {
8
- host: string;
9
- port: number;
10
- enabled: boolean;
11
2
 
12
- constructor(host: string, port: number, enabled: boolean) {
13
- this.host = host;
14
- this.port = port;
15
- this.enabled = enabled;
16
- }
17
- }
18
- ```
19
- **After:**
20
- ```
21
- class Config {
22
- host: string;
23
- port: number;
24
- enabled: boolean;
3
+ The `Default` macro generates a static `defaultValue()` factory method that creates
4
+ instances with default values. This is analogous to Rust's `Default` trait, providing
5
+ a standard way to create "zero" or "empty" instances of types.
25
6
 
26
- constructor(host: string, port: number, enabled: boolean) {
27
- this.host = host;
28
- this.port = port;
29
- this.enabled = enabled;
30
- }
31
-
32
- static defaultValue(): Config {
33
- const instance = new Config();
34
- instance.host = '';
35
- instance.port = 0;
36
- instance.enabled = false;
37
- return instance;
38
- }
39
- }
40
- ``` ```
41
- const config = Config.defaultValue();
42
- console.log(config.host); // ""
43
- console.log(config.port); // 0
44
- console.log(config.enabled); // false
45
- ``` ## Automatic Default Values
46
- Like Rust's `Default` trait, the macro automatically determines default values for primitive types and common collections:
47
- | TypeScript Type | Default Value | Rust Equivalent |
48
- | --- | --- | --- |
49
- | `string` | `""` | `String::default()` |
50
- | `number` | `0` | `i32::default()` |
51
- | `boolean` | `false` | `bool::default()` |
52
- | `bigint` | `0n` | `i64::default()` |
53
- | `T[]` / `Array<T>` | `[]` | `Vec::default()` |
54
- | `Map<K, V>` | `new Map()` | `HashMap::default()` |
55
- | `Set<T>` | `new Set()` | `HashSet::default()` |
56
- | `Date` | `new Date()` | — |
57
- | `T | null` / `T | undefined` | `null` | `Option::default()` |
58
- | Custom types | **Error** | **Error** (needs `impl Default`) |
59
- ## Nullable Types (like Rust's Option)
60
- Just like Rust's `Option<T>` defaults to `None`, nullable TypeScript types automatically default to `null`:
61
- **Before:**
62
- ```
63
- /** @derive(Default) */
64
- interface User {
65
- name: string;
66
- email: string | null;
67
- age: number;
68
- metadata: Record<string, unknown> | null;
69
- }
70
- ```
71
- **After:**
72
- ```
73
- interface User {
74
- name: string;
75
- email: string | null;
76
- age: number;
77
- metadata: Record<string, unknown> | null;
78
- }
7
+ ## Generated Output
79
8
 
80
- export namespace User {
81
- export function defaultValue(): User {
82
- return { name: '', email: null, age: 0, metadata: null } as User;
83
- }
84
- }
85
- ``` ```
86
- const user = User.defaultValue();
87
- console.log(user.name); // ""
88
- console.log(user.email); // null (nullable type)
89
- console.log(user.age); // 0
90
- console.log(user.metadata); // null (nullable type)
91
- ``` ## Custom Types Require @default
92
- Just like Rust requires `impl Default` for custom types, Macroforge requires the `@default()` decorator on fields with non-primitive types:
93
- **Before:**
94
- ```
95
- /** @derive(Default) */
96
- interface AppConfig {
97
- name: string;
98
- port: number;
99
- /** @default(Settings.defaultValue()) */
100
- settings: Settings;
101
- /** @default(Permissions.defaultValue()) */
102
- permissions: Permissions;
103
- }
104
- ```
105
- **After:**
106
- ```
107
- interface AppConfig {
108
- name: string;
109
- port: number;
9
+ | Type | Generated Code | Description |
10
+ |------|----------------|-------------|
11
+ | Class | `static defaultValue(): ClassName` | Static factory method |
12
+ | Enum | `defaultValueEnumName(): EnumName` | Standalone function returning marked variant |
13
+ | Interface | `defaultValueInterfaceName(): InterfaceName` | Standalone function returning object literal |
14
+ | Type Alias | `defaultValueTypeName(): TypeName` | Standalone function with type-appropriate default |
110
15
 
111
- settings: Settings;
16
+ ## Configuration
112
17
 
113
- permissions: Permissions;
114
- }
18
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
19
+ - `"suffix"` (default): Suffixes with type name (e.g., `defaultValueMyType`)
20
+ - `"prefix"`: Prefixes with type name (e.g., `myTypeDefaultValue`)
21
+ - `"generic"`: Uses TypeScript generics (e.g., `defaultValue<T extends MyType>`)
22
+ - `"namespace"`: Legacy namespace wrapping
115
23
 
116
- export namespace AppConfig {
117
- export function defaultValue(): AppConfig {
118
- return {
119
- name: '',
120
- port: 0,
121
- settings: Settings.defaultValue(),
122
- permissions: Permissions.defaultValue()
123
- } as AppConfig;
124
- }
125
- }
126
- ``` <p class="text-red-500 text-sm mt-2">Without `@default` on custom type fields, the macro will emit an error: ```
127
- // Error: @derive(Default) cannot determine default for non-primitive fields.
128
- // Add @default(value) to: settings, permissions
129
- ``` ## Custom Default Values
130
- Use the `@default()` decorator to specify custom default values for any field:
131
- **Before:**
132
- ```
133
- /** @derive(Default) */
134
- class ServerConfig {
135
- /** @default("localhost") */
136
- host: string;
24
+ ## Default Values by Type
137
25
 
138
- /** @default(8080) */
139
- port: number;
26
+ The macro uses Rust-like default semantics:
140
27
 
141
- /** @default(true) */
142
- enabled: boolean;
28
+ | Type | Default Value |
29
+ |------|---------------|
30
+ | `string` | `""` (empty string) |
31
+ | `number` | `0` |
32
+ | `boolean` | `false` |
33
+ | `bigint` | `0n` |
34
+ | `T[]` | `[]` (empty array) |
35
+ | `Array<T>` | `[]` (empty array) |
36
+ | `Map<K,V>` | `new Map()` |
37
+ | `Set<T>` | `new Set()` |
38
+ | `Date` | `new Date()` (current time) |
39
+ | `T \| null` | `null` |
40
+ | `CustomType` | `CustomType.defaultValue()` (recursive) |
143
41
 
144
- /** @default(["info", "error"]) */
145
- logLevels: string[];
42
+ ## Field-Level Options
146
43
 
147
- constructor(host: string, port: number, enabled: boolean, logLevels: string[]) {
148
- this.host = host;
149
- this.port = port;
150
- this.enabled = enabled;
151
- this.logLevels = logLevels;
152
- }
153
- }
154
- ```
155
- **After:**
156
- ```
157
- class ServerConfig {
158
- host: string;
44
+ The `@default` decorator allows specifying explicit default values:
159
45
 
160
- port: number;
46
+ - `@default(42)` - Use 42 as the default
47
+ - `@default("hello")` - Use "hello" as the default
48
+ - `@default([])` - Use empty array as the default
49
+ - `@default({ value: "test" })` - Named form for complex values
161
50
 
162
- enabled: boolean;
51
+ ## Example
163
52
 
164
- logLevels: string[];
53
+ ```typescript
54
+ @derive(Default)
55
+ class UserSettings {
56
+ @default("light")
57
+ theme: string;
165
58
 
166
- constructor(host: string, port: number, enabled: boolean, logLevels: string[]) {
167
- this.host = host;
168
- this.port = port;
169
- this.enabled = enabled;
170
- this.logLevels = logLevels;
171
- }
59
+ @default(10)
60
+ pageSize: number;
172
61
 
173
- static defaultValue(): ServerConfig {
174
- const instance = new ServerConfig();
175
- instance.host = 'localhost';
176
- instance.port = 8080;
177
- instance.enabled = true;
178
- instance.logLevels = ['info', 'error'];
179
- return instance;
180
- }
181
- }
182
- ``` ```
183
- const config = ServerConfig.defaultValue();
184
- console.log(config.host); // "localhost"
185
- console.log(config.port); // 8080
186
- console.log(config.enabled); // true
187
- console.log(config.logLevels); // ["info", "error"]
188
- ``` ## Interface Support
189
- Default also works with interfaces. For interfaces, a namespace is generated with a `defaultValue()` function:
190
- **Before:**
191
- ```
192
- /** @derive(Default) */
193
- interface Point {
194
- x: number;
195
- y: number;
196
- }
197
- ```
198
- **After:**
199
- ```
200
- interface Point {
201
- x: number;
202
- y: number;
62
+ notifications: boolean; // Uses type default: false
203
63
  }
204
64
 
205
- export namespace Point {
206
- export function defaultValue(): Point {
207
- return { x: 0, y: 0 } as Point;
208
- }
209
- }
210
- ``` ```
211
- const origin = Point.defaultValue();
212
- console.log(origin); // { x: 0, y: 0 }
213
- ``` ## Enum Support
214
- Default works with enums. For enums, it returns the first variant as the default value:
215
- **Before:**
65
+ // Generated:
66
+ // static defaultValue(): UserSettings {
67
+ // const instance = new UserSettings();
68
+ // instance.theme = "light";
69
+ // instance.pageSize = 10;
70
+ // instance.notifications = false;
71
+ // return instance;
72
+ // }
216
73
  ```
217
- /** @derive(Default) */
218
- enum Status {
219
- Pending = 'pending',
220
- Active = 'active',
221
- Completed = 'completed'
222
- }
223
- ```
224
- **After:**
225
- ```
226
- enum Status {
227
- Pending = 'pending',
228
- Active = 'active',
229
- Completed = 'completed'
230
- }
231
- ``` ```
232
- const defaultStatus = Status.defaultValue();
233
- console.log(defaultStatus); // "pending"
234
- ``` ## Type Alias Support
235
- Default works with type aliases. For object types, it creates an object with default field values:
236
- **Before:**
237
- ```
238
- /** @derive(Default) */
239
- type Dimensions = {
240
- width: number;
241
- height: number;
242
- };
243
- ```
244
- **After:**
245
- ```
246
- type Dimensions = {
247
- width: number;
248
- height: number;
249
- };
250
74
 
251
- export namespace Dimensions {
252
- export function defaultValue(): Dimensions {
253
- return { width: 0, height: 0 } as Dimensions;
254
- }
255
- }
256
- ``` ```
257
- const dims = Dimensions.defaultValue();
258
- console.log(dims); // { width: 0, height: 0 }
259
- ``` ## Combining with Other Macros
260
- **Source:**
75
+ ## Enum Defaults
76
+
77
+ For enums, mark one variant with `@default`:
78
+
79
+ ```typescript
80
+ @derive(Default)
81
+ enum Status {
82
+ @default
83
+ Pending,
84
+ Active,
85
+ Completed
86
+ }
87
+
88
+ // Generated:
89
+ // export namespace Status {
90
+ // export function defaultValue(): Status {
91
+ // return Status.Pending;
92
+ // }
93
+ // }
261
94
  ```
262
- /** @derive(Default, Debug, Clone, PartialEq) */
263
- class User {
264
- /** @default("Anonymous") */
265
- name: string;
266
95
 
267
- /** @default(0) */
268
- age: number;
96
+ ## Error Handling
269
97
 
270
- constructor(name: string, age: number) {
271
- this.name = name;
272
- this.age = age;
273
- }
274
- }
275
- ``` ```
276
- const user1 = User.defaultValue();
277
- const user2 = user1.clone();
98
+ The macro will return an error if:
278
99
 
279
- console.log(user1.toString()); // User { name: "Anonymous", age: 0 }
280
- console.log(user1.equals(user2)); // true
281
- ```
100
+ - A non-primitive field lacks `@default` and has no known default
101
+ - An enum has no variant marked with `@default`
102
+ - A union type has no `@default` on a variant