@macroforge/mcp-server 0.1.17 → 0.1.21

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.
@@ -4,18 +4,9 @@
4
4
 
5
5
  ## Basic Usage
6
6
 
7
- ```typescript
8
- /** @derive(Hash) */
9
- class Point {
10
- x: number;
11
- y: number;
12
-
13
- constructor(x: number, y: number) {
14
- this.x = x;
15
- this.y = y;
16
- }
17
- }
7
+ <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
18
8
 
9
+ ```typescript
19
10
  const p1 = new Point(10, 20);
20
11
  const p2 = new Point(10, 20);
21
12
  const p3 = new Point(5, 5);
@@ -25,19 +16,6 @@ console.log(p2.hashCode()); // Same hash (equal values = equal hash)
25
16
  console.log(p3.hashCode()); // Different hash
26
17
  ```
27
18
 
28
- ## Generated Code
29
-
30
- The Hash macro generates a method that combines field hashes using the FNV-1a style algorithm:
31
-
32
- ```typescript
33
- hashCode(): number {
34
- let hash = 17;
35
- hash = (hash * 31 + (Number.isInteger(this.x) ? this.x | 0 : this.x.toString().split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) | 0;
36
- hash = (hash * 31 + (Number.isInteger(this.y) ? this.y | 0 : this.y.toString().split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) | 0;
37
- return hash;
38
- }
39
- ```
40
-
41
19
  ## Hash Algorithm
42
20
 
43
21
  The generated hash function uses the following algorithm for different types:
@@ -68,22 +46,9 @@ The generated hash function uses the following algorithm for different types:
68
46
 
69
47
  Use `@hash(skip)` to exclude a field from hash computation:
70
48
 
71
- ```typescript
72
- /** @derive(Hash) */
73
- class User {
74
- id: number;
75
- name: string;
76
-
77
- /** @hash(skip) */
78
- lastLogin: Date; // Not included in hash
79
-
80
- constructor(id: number, name: string, lastLogin: Date) {
81
- this.id = id;
82
- this.name = name;
83
- this.lastLogin = lastLogin;
84
- }
85
- }
49
+ <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
86
50
 
51
+ ```typescript
87
52
  const user1 = new User(1, "Alice", new Date("2024-01-01"));
88
53
  const user2 = new User(1, "Alice", new Date("2024-12-01"));
89
54
 
@@ -94,8 +59,7 @@ console.log(user1.hashCode() === user2.hashCode()); // true (lastLogin is skippe
94
59
 
95
60
  Hash is often used together with PartialEq. Objects that are equal should have the same hash code:
96
61
 
97
- ```typescript
98
- /** @derive(Hash, PartialEq) */
62
+ <InteractiveMacro code={`/** @derive(Hash, PartialEq) */
99
63
  class Product {
100
64
  sku: string;
101
65
  name: string;
@@ -104,8 +68,9 @@ class Product {
104
68
  this.sku = sku;
105
69
  this.name = name;
106
70
  }
107
- }
71
+ }`} />
108
72
 
73
+ ```typescript
109
74
  const p1 = new Product("ABC123", "Widget");
110
75
  const p2 = new Product("ABC123", "Widget");
111
76
 
@@ -118,23 +83,9 @@ console.log(p1.hashCode() === p2.hashCode()); // true
118
83
 
119
84
  Hash also works with interfaces. For interfaces, a namespace is generated with a `hashCode` function:
120
85
 
121
- ```typescript
122
- /** @derive(Hash) */
123
- interface Point {
124
- x: number;
125
- y: number;
126
- }
127
-
128
- // Generated:
129
- // export namespace Point {
130
- // export function hashCode(self: Point): number {
131
- // let hash = 17;
132
- // hash = (hash * 31 + (self.x | 0)) | 0;
133
- // hash = (hash * 31 + (self.y | 0)) | 0;
134
- // return hash;
135
- // }
136
- // }
86
+ <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
137
87
 
88
+ ```typescript
138
89
  const p: Point = { x: 10, y: 20 };
139
90
  console.log(Point.hashCode(p)); // numeric hash value
140
91
  ```
@@ -143,28 +94,9 @@ console.log(Point.hashCode(p)); // numeric hash value
143
94
 
144
95
  Hash works with enums. For string enums, it hashes the string value; for numeric enums, it uses the numeric value directly:
145
96
 
146
- ```typescript
147
- /** @derive(Hash) */
148
- enum Status {
149
- Active = "active",
150
- Inactive = "inactive",
151
- Pending = "pending",
152
- }
153
-
154
- // Generated:
155
- // export namespace Status {
156
- // export function hashCode(value: Status): number {
157
- // if (typeof value === "string") {
158
- // let hash = 0;
159
- // for (let i = 0; i < value.length; i++) {
160
- // hash = (hash * 31 + value.charCodeAt(i)) | 0;
161
- // }
162
- // return hash;
163
- // }
164
- // return value | 0;
165
- // }
166
- // }
97
+ <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
167
98
 
99
+ ```typescript
168
100
  console.log(Status.hashCode(Status.Active)); // consistent hash
169
101
  console.log(Status.hashCode(Status.Inactive)); // different hash
170
102
  ```
@@ -173,33 +105,19 @@ console.log(Status.hashCode(Status.Inactive)); // different hash
173
105
 
174
106
  Hash works with type aliases. For object types, it hashes each field:
175
107
 
176
- ```typescript
177
- /** @derive(Hash) */
178
- type Coordinates = {
179
- lat: number;
180
- lng: number;
181
- };
182
-
183
- // Generated:
184
- // export namespace Coordinates {
185
- // export function hashCode(value: Coordinates): number {
186
- // let hash = 17;
187
- // hash = (hash * 31 + (value.lat | 0)) | 0;
188
- // hash = (hash * 31 + (value.lng | 0)) | 0;
189
- // return hash;
190
- // }
191
- // }
108
+ <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
192
109
 
110
+ ```typescript
193
111
  const loc: Coordinates = { lat: 40.7128, lng: -74.0060 };
194
112
  console.log(Coordinates.hashCode(loc));
195
113
  ```
196
114
 
197
115
  For union types, it uses JSON stringification as a fallback:
198
116
 
199
- ```typescript
200
- /** @derive(Hash) */
201
- type Result = "success" | "error" | "pending";
117
+ <InteractiveMacro code={`/** @derive(Hash) */
118
+ type Result = "success" | "error" | "pending";`} />
202
119
 
120
+ ```typescript
203
121
  console.log(Result.hashCode("success")); // hash of "success" string
204
122
  console.log(Result.hashCode("error")); // hash of "error" string
205
123
  ```
@@ -1,27 +1,43 @@
1
1
  # Built-in Macros
2
2
 
3
- *Macroforge comes with five built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.*
3
+ *Macroforge comes with built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.*
4
4
 
5
5
  ## Overview
6
6
 
7
- | `Debug`
7
+ | [`Debug`]({base}/docs/builtin-macros/debug)
8
8
  | `toString(): string`
9
9
  | Human-readable string representation
10
10
 
11
- | `Clone`
11
+ | [`Clone`]({base}/docs/builtin-macros/clone)
12
12
  | `clone(): T`
13
- | Creates a copy of the object
13
+ | Creates a deep copy of the object
14
14
 
15
- | `PartialEq`
15
+ | [`Default`]({base}/docs/builtin-macros/default)
16
+ | `static default(): T`
17
+ | Creates an instance with default values
18
+
19
+ | [`Hash`]({base}/docs/builtin-macros/hash)
20
+ | `hashCode(): number`
21
+ | Generates a hash code for the object
22
+
23
+ | [`PartialEq`]({base}/docs/builtin-macros/partial-eq)
16
24
  | `equals(other: T): boolean`
17
25
  | Value equality comparison
18
26
 
19
- | `Serialize`
27
+ | [`Ord`]({base}/docs/builtin-macros/ord)
28
+ | `compare(other: T): number`
29
+ | Total ordering comparison (-1, 0, 1)
30
+
31
+ | [`PartialOrd`]({base}/docs/builtin-macros/partial-ord)
32
+ | `partialCompare(other: T): number | null`
33
+ | Partial ordering comparison
34
+
35
+ | [`Serialize`]({base}/docs/builtin-macros/serialize)
20
36
  | `toJSON(): Record<string, unknown>`
21
37
  | JSON serialization with type handling
22
38
 
23
- | `Deserialize`
24
- | `fromJSON(data: unknown): T`
39
+ | [`Deserialize`]({base}/docs/builtin-macros/deserialize)
40
+ | `static fromJSON(data: unknown): T`
25
41
  | JSON deserialization with validation
26
42
 
27
43
  ## Using Built-in Macros
@@ -160,10 +176,18 @@ Each macro has its own options and behaviors:
160
176
 
161
177
  - [**Debug**]({base}/docs/builtin-macros/debug) - Customizable field renaming and skipping
162
178
 
163
- - [**Clone**]({base}/docs/builtin-macros/clone) - Shallow copying for all field types
179
+ - [**Clone**]({base}/docs/builtin-macros/clone) - Deep copying for all field types
180
+
181
+ - [**Default**]({base}/docs/builtin-macros/default) - Default value generation with field attributes
182
+
183
+ - [**Hash**]({base}/docs/builtin-macros/hash) - Hash code generation for use in maps and sets
164
184
 
165
185
  - [**PartialEq**]({base}/docs/builtin-macros/partial-eq) - Value-based equality comparison
166
186
 
187
+ - [**Ord**]({base}/docs/builtin-macros/ord) - Total ordering for sorting
188
+
189
+ - [**PartialOrd**]({base}/docs/builtin-macros/partial-ord) - Partial ordering comparison
190
+
167
191
  - [**Serialize**]({base}/docs/builtin-macros/serialize) - JSON serialization with serde-style options
168
192
 
169
193
  - [**Deserialize**]({base}/docs/builtin-macros/deserialize) - JSON deserialization with validation
@@ -4,20 +4,9 @@
4
4
 
5
5
  ## Basic Usage
6
6
 
7
- ```typescript
8
- /** @derive(Ord) */
9
- class Version {
10
- major: number;
11
- minor: number;
12
- patch: number;
13
-
14
- constructor(major: number, minor: number, patch: number) {
15
- this.major = major;
16
- this.minor = minor;
17
- this.patch = patch;
18
- }
19
- }
7
+ <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
20
8
 
9
+ ```typescript
21
10
  const v1 = new Version(1, 0, 0);
22
11
  const v2 = new Version(1, 2, 0);
23
12
  const v3 = new Version(1, 2, 0);
@@ -27,24 +16,6 @@ console.log(v2.compareTo(v1)); // 1 (v2 > v1)
27
16
  console.log(v2.compareTo(v3)); // 0 (v2 == v3)
28
17
  ```
29
18
 
30
- ## Generated Code
31
-
32
- The Ord macro generates a compareTo method using lexicographic field comparison:
33
-
34
- ```typescript
35
- compareTo(other: Version): number {
36
- if (this === other) return 0;
37
- const typedOther = other;
38
- const cmp0 = (this.major < typedOther.major ? -1 : this.major > typedOther.major ? 1 : 0);
39
- if (cmp0 !== 0) return cmp0;
40
- const cmp1 = (this.minor < typedOther.minor ? -1 : this.minor > typedOther.minor ? 1 : 0);
41
- if (cmp1 !== 0) return cmp1;
42
- const cmp2 = (this.patch < typedOther.patch ? -1 : this.patch > typedOther.patch ? 1 : 0);
43
- if (cmp2 !== 0) return cmp2;
44
- return 0;
45
- }
46
- ```
47
-
48
19
  ## Comparison Logic
49
20
 
50
21
  The Ord macro compares fields in declaration order (lexicographic ordering). For each type:
@@ -83,22 +54,9 @@ Unlike `PartialOrd`, the `Ord` macro never returns `null` - it provides total or
83
54
 
84
55
  Use `@ord(skip)` to exclude a field from ordering comparison:
85
56
 
86
- ```typescript
87
- /** @derive(Ord) */
88
- class Task {
89
- priority: number;
90
- name: string;
91
-
92
- /** @ord(skip) */
93
- createdAt: Date; // Not used for ordering
94
-
95
- constructor(priority: number, name: string, createdAt: Date) {
96
- this.priority = priority;
97
- this.name = name;
98
- this.createdAt = createdAt;
99
- }
100
- }
57
+ <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
101
58
 
59
+ ```typescript
102
60
  const t1 = new Task(1, "Bug fix", new Date("2024-01-01"));
103
61
  const t2 = new Task(1, "Bug fix", new Date("2024-12-01"));
104
62
 
@@ -109,8 +67,7 @@ console.log(t1.compareTo(t2)); // 0 (createdAt is skipped)
109
67
 
110
68
  The generated `compareTo()` method works directly with `Array.sort()`:
111
69
 
112
- ```typescript
113
- /** @derive(Ord) */
70
+ <InteractiveMacro code={`/** @derive(Ord) */
114
71
  class Score {
115
72
  points: number;
116
73
  name: string;
@@ -119,8 +76,9 @@ class Score {
119
76
  this.points = points;
120
77
  this.name = name;
121
78
  }
122
- }
79
+ }`} />
123
80
 
81
+ ```typescript
124
82
  const scores = [
125
83
  new Score(100, "Alice"),
126
84
  new Score(50, "Bob"),
@@ -141,25 +99,9 @@ scores.sort((a, b) => b.compareTo(a));
141
99
 
142
100
  Ord works with interfaces. For interfaces, a namespace is generated with a `compareTo` function:
143
101
 
144
- ```typescript
145
- /** @derive(Ord) */
146
- interface Point {
147
- x: number;
148
- y: number;
149
- }
150
-
151
- // Generated:
152
- // export namespace Point {
153
- // export function compareTo(self: Point, other: Point): number {
154
- // if (self === other) return 0;
155
- // const cmp0 = (self.x < other.x ? -1 : self.x > other.x ? 1 : 0);
156
- // if (cmp0 !== 0) return cmp0;
157
- // const cmp1 = (self.y < other.y ? -1 : self.y > other.y ? 1 : 0);
158
- // if (cmp1 !== 0) return cmp1;
159
- // return 0;
160
- // }
161
- // }
102
+ <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
162
103
 
104
+ ```typescript
163
105
  const points: Point[] = [
164
106
  { x: 5, y: 10 },
165
107
  { x: 1, y: 20 },
@@ -174,22 +116,9 @@ points.sort((a, b) => Point.compareTo(a, b));
174
116
 
175
117
  Ord works with enums. For numeric enums, it compares the numeric values; for string enums, it uses string comparison:
176
118
 
177
- ```typescript
178
- /** @derive(Ord) */
179
- enum Priority {
180
- Low = 0,
181
- Medium = 1,
182
- High = 2,
183
- Critical = 3
184
- }
185
-
186
- // Generated:
187
- // export namespace Priority {
188
- // export function compareTo(a: Priority, b: Priority): number {
189
- // return a < b ? -1 : a > b ? 1 : 0;
190
- // }
191
- // }
119
+ <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
192
120
 
121
+ ```typescript
193
122
  console.log(Priority.compareTo(Priority.Low, Priority.High)); // -1
194
123
  console.log(Priority.compareTo(Priority.Critical, Priority.Low)); // 1
195
124
  console.log(Priority.compareTo(Priority.Medium, Priority.Medium)); // 0
@@ -199,25 +128,9 @@ console.log(Priority.compareTo(Priority.Medium, Priority.Medium)); // 0
199
128
 
200
129
  Ord works with type aliases. For object types, it uses lexicographic field comparison:
201
130
 
202
- ```typescript
203
- /** @derive(Ord) */
204
- type Coordinate = {
205
- x: number;
206
- y: number;
207
- };
208
-
209
- // Generated:
210
- // export namespace Coordinate {
211
- // export function compareTo(a: Coordinate, b: Coordinate): number {
212
- // if (a === b) return 0;
213
- // const cmp0 = (a.x < b.x ? -1 : a.x > b.x ? 1 : 0);
214
- // if (cmp0 !== 0) return cmp0;
215
- // const cmp1 = (a.y < b.y ? -1 : a.y > b.y ? 1 : 0);
216
- // if (cmp1 !== 0) return cmp1;
217
- // return 0;
218
- // }
219
- // }
131
+ <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
220
132
 
133
+ ```typescript
221
134
  const c1: Coordinate = { x: 10, y: 20 };
222
135
  const c2: Coordinate = { x: 10, y: 30 };
223
136
 
@@ -228,8 +141,7 @@ console.log(Coordinate.compareTo(c1, c2)); // -1 (c1 < c2)
228
141
 
229
142
  Use `Ord` when all values of a type are comparable. Use `PartialOrd` when some values might be incomparable (e.g., different types at runtime).
230
143
 
231
- ```typescript
232
- // Ord: Total ordering - never returns null
144
+ <InteractiveMacro code={`// Ord: Total ordering - never returns null
233
145
  /** @derive(Ord) */
234
146
  class Version {
235
147
  major: number;
@@ -238,21 +150,10 @@ class Version {
238
150
  this.major = major;
239
151
  this.minor = minor;
240
152
  }
241
- }
153
+ }`} />
242
154
 
155
+ ```typescript
243
156
  const v1 = new Version(1, 0);
244
157
  const v2 = new Version(2, 0);
245
158
  console.log(v1.compareTo(v2)); // Always -1, 0, or 1
246
-
247
- // PartialOrd: Partial ordering - can return null
248
- /** @derive(PartialOrd) */
249
- class Value {
250
- data: number;
251
- constructor(data: number) {
252
- this.data = data;
253
- }
254
- }
255
-
256
- const val = new Value(10);
257
- console.log(val.compareTo("not a Value")); // null (incomparable)
258
159
  ```