@macroforge/mcp-server 0.1.33 → 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.
Files changed (50) hide show
  1. package/README.md +68 -0
  2. package/dist/index.d.ts +32 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +46 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/tools/docs-loader.d.ts +133 -5
  7. package/dist/tools/docs-loader.d.ts.map +1 -1
  8. package/dist/tools/docs-loader.js +131 -15
  9. package/dist/tools/docs-loader.js.map +1 -1
  10. package/dist/tools/index.d.ts +48 -1
  11. package/dist/tools/index.d.ts.map +1 -1
  12. package/dist/tools/index.js +163 -14
  13. package/dist/tools/index.js.map +1 -1
  14. package/docs/api/api-overview.md +24 -46
  15. package/docs/api/expand-sync.md +24 -51
  16. package/docs/api/native-plugin.md +24 -56
  17. package/docs/api/position-mapper.md +34 -76
  18. package/docs/api/transform-sync.md +27 -59
  19. package/docs/builtin-macros/clone.md +45 -104
  20. package/docs/builtin-macros/debug.md +33 -104
  21. package/docs/builtin-macros/default.md +78 -114
  22. package/docs/builtin-macros/deserialize.md +93 -273
  23. package/docs/builtin-macros/hash.md +58 -100
  24. package/docs/builtin-macros/macros-overview.md +42 -103
  25. package/docs/builtin-macros/ord.md +65 -133
  26. package/docs/builtin-macros/partial-eq.md +53 -179
  27. package/docs/builtin-macros/partial-ord.md +67 -159
  28. package/docs/builtin-macros/serialize.md +64 -194
  29. package/docs/concepts/architecture.md +40 -99
  30. package/docs/concepts/derive-system.md +129 -125
  31. package/docs/concepts/how-macros-work.md +52 -84
  32. package/docs/custom-macros/custom-overview.md +17 -39
  33. package/docs/custom-macros/rust-setup.md +22 -55
  34. package/docs/custom-macros/ts-macro-derive.md +43 -107
  35. package/docs/custom-macros/ts-quote.md +177 -507
  36. package/docs/getting-started/first-macro.md +108 -33
  37. package/docs/getting-started/installation.md +32 -73
  38. package/docs/integration/cli.md +70 -156
  39. package/docs/integration/configuration.md +32 -75
  40. package/docs/integration/integration-overview.md +16 -55
  41. package/docs/integration/mcp-server.md +30 -69
  42. package/docs/integration/svelte-preprocessor.md +60 -83
  43. package/docs/integration/typescript-plugin.md +32 -74
  44. package/docs/integration/vite-plugin.md +30 -79
  45. package/docs/language-servers/ls-overview.md +22 -46
  46. package/docs/language-servers/svelte.md +30 -69
  47. package/docs/language-servers/zed.md +34 -72
  48. package/docs/roadmap/roadmap.md +54 -130
  49. package/docs/sections.json +3 -262
  50. package/package.json +2 -2
@@ -1,204 +1,78 @@
1
1
  # PartialEq
2
2
 
3
- *The `PartialEq` macro generates an `equals()` method for value-based equality comparison between objects.*
3
+ The `PartialEq` macro generates an `equals()` method for field-by-field
4
+ structural equality comparison. This is analogous to Rust's `PartialEq` trait,
5
+ enabling value-based equality semantics instead of reference equality.
4
6
 
5
- ## Basic Usage
7
+ ## Generated Output
6
8
 
7
- <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
9
+ | Type | Generated Code | Description |
10
+ |------|----------------|-------------|
11
+ | Class | `equals(other: unknown): boolean` | Instance method with instanceof check |
12
+ | Enum | `equalsEnumName(a: EnumName, b: EnumName): boolean` | Standalone function using strict equality |
13
+ | Interface | `equalsInterfaceName(a: InterfaceName, b: InterfaceName): boolean` | Standalone function comparing fields |
14
+ | Type Alias | `equalsTypeName(a: TypeName, b: TypeName): boolean` | Standalone function with type-appropriate comparison |
8
15
 
9
- ```typescript
10
- const p1 = new Point(10, 20);
11
- const p2 = new Point(10, 20);
12
- const p3 = new Point(5, 5);
13
-
14
- console.log(p1.equals(p2)); // true (same values)
15
- console.log(p1.equals(p3)); // false (different values)
16
- console.log(p1 === p2); // false (different references)
17
- ```
18
-
19
- ## How It Works
16
+ ## Configuration
20
17
 
21
- The PartialEq macro performs field-by-field comparison using these strategies:
18
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
19
+ - `"suffix"` (default): Suffixes with type name (e.g., `equalsMyType`)
20
+ - `"prefix"`: Prefixes with type name (e.g., `myTypeEquals`)
21
+ - `"generic"`: Uses TypeScript generics (e.g., `equals<T extends MyType>`)
22
+ - `"namespace"`: Legacy namespace wrapping
22
23
 
23
- - **Primitives** (string, number, boolean, null, undefined) → Strict equality (`===`)
24
+ ## Comparison Strategy
24
25
 
25
- - **Date** Compares timestamps via `getTime()`
26
+ The generated equality check:
26
27
 
27
- - **Array** Length check + element-by-element comparison
28
+ 1. **Identity check**: `this === other` returns true immediately
29
+ 2. **Type check**: For classes, uses `instanceof`; returns false if wrong type
30
+ 3. **Field comparison**: Compares each non-skipped field
28
31
 
29
- - **Map** → Size check + entry comparison
32
+ ## Type-Specific Comparisons
30
33
 
31
- - **Set** Size check + membership verification
34
+ | Type | Comparison Method |
35
+ |------|-------------------|
36
+ | Primitives | Strict equality (`===`) |
37
+ | Arrays | Length + element-by-element (recursive) |
38
+ | `Date` | `getTime()` comparison |
39
+ | `Map` | Size + entry-by-entry comparison |
40
+ | `Set` | Size + membership check |
41
+ | Objects | Calls `equals()` if available, else `===` |
32
42
 
33
- - **Objects** → Calls `equals()` if available, otherwise `===`
43
+ ## Field-Level Options
34
44
 
35
- ## Field Options
45
+ The `@partialEq` decorator supports:
36
46
 
37
- ### @partialEq(skip)
47
+ - `skip` - Exclude the field from equality comparison
38
48
 
39
- Use `@partialEq(skip)` to exclude a field from equality comparison:
40
-
41
- <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
49
+ ## Example
42
50
 
43
51
  ```typescript
44
- const user1 = new User(1, "Alice", new Date("2024-01-01"));
45
- const user2 = new User(1, "Alice", new Date("2024-12-01"));
46
-
47
- console.log(user1.equals(user2)); // true (createdAt is skipped)
48
- ```
49
-
50
- ## Type Safety
51
-
52
- The generated `equals()` method accepts `unknown` and performs runtime type checking:
53
-
54
- <InteractiveMacro code={`/** @derive(PartialEq) */
52
+ @derive(PartialEq, Hash)
55
53
  class User {
56
- name: string;
57
- constructor(name: string) {
58
- this.name = name;
59
- }
60
- }`} />
61
-
62
- ```typescript
63
- const user = new User("Alice");
64
-
65
- console.log(user.equals(new User("Alice"))); // true
66
- console.log(user.equals("Alice")); // false (not a User instance)
67
- ```
68
-
69
- ## With Nested Objects
54
+ id: number;
55
+ name: string;
70
56
 
71
- For objects with nested fields, PartialEq recursively calls `equals()` if available:
72
-
73
- <InteractiveMacro code={`/** @derive(PartialEq) */
74
- class Address {
75
- city: string;
76
- zip: string;
77
-
78
- constructor(city: string, zip: string) {
79
- this.city = city;
80
- this.zip = zip;
81
- }
57
+ @partialEq(skip) // Don't compare cached values
58
+ @hash(skip)
59
+ cachedScore: number;
82
60
  }
83
61
 
84
- /** @derive(PartialEq) */
85
- class Person {
86
- name: string;
87
- address: Address;
88
-
89
- constructor(name: string, address: Address) {
90
- this.name = name;
91
- this.address = address;
92
- }
93
- }`} />
94
-
95
- ```typescript
96
- const addr1 = new Address("NYC", "10001");
97
- const addr2 = new Address("NYC", "10001");
98
-
99
- const p1 = new Person("Alice", addr1);
100
- const p2 = new Person("Alice", addr2);
101
-
102
- console.log(p1.equals(p2)); // true (deep equality via Address.equals)
103
- ```
104
-
105
- ## Interface Support
106
-
107
- PartialEq works with interfaces. For interfaces, a namespace is generated with an `equals` function:
108
-
109
- <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
110
-
111
- ```typescript
112
- const p1: Point = { x: 10, y: 20 };
113
- const p2: Point = { x: 10, y: 20 };
114
- const p3: Point = { x: 5, y: 5 };
115
-
116
- console.log(Point.equals(p1, p2)); // true
117
- console.log(Point.equals(p1, p3)); // false
118
- ```
119
-
120
- ## Enum Support
121
-
122
- PartialEq works with enums. For enums, strict equality comparison is used:
123
-
124
- <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
125
-
126
- ```typescript
127
- console.log(Status.equals(Status.Active, Status.Active)); // true
128
- console.log(Status.equals(Status.Active, Status.Inactive)); // false
129
- ```
130
-
131
- ## Type Alias Support
132
-
133
- PartialEq works with type aliases. For object types, field-by-field comparison is used:
134
-
135
- <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
136
-
137
- ```typescript
138
- const p1: Point = { x: 10, y: 20 };
139
- const p2: Point = { x: 10, y: 20 };
140
-
141
- console.log(Point.equals(p1, p2)); // true
142
- ```
143
-
144
- For union types, strict equality is used:
145
-
146
- <InteractiveMacro code={`/** @derive(PartialEq) */
147
- type ApiStatus = "loading" | "success" | "error";`} />
148
-
149
- ```typescript
150
- console.log(ApiStatus.equals("success", "success")); // true
151
- console.log(ApiStatus.equals("success", "error")); // false
62
+ // Generated:
63
+ // equals(other: unknown): boolean {
64
+ // if (this === other) return true;
65
+ // if (!(other instanceof User)) return false;
66
+ // const typedOther = other as User;
67
+ // return this.id === typedOther.id &&
68
+ // this.name === typedOther.name;
69
+ // }
152
70
  ```
153
71
 
154
- ## Common Patterns
155
-
156
- ### Finding Items in Arrays
157
-
158
- <InteractiveMacro code={`/** @derive(PartialEq) */
159
- class Product {
160
- sku: string;
161
- name: string;
162
-
163
- constructor(sku: string, name: string) {
164
- this.sku = sku;
165
- this.name = name;
166
- }
167
- }`} />
168
-
169
- ```typescript
170
- const products = [
171
- new Product("A1", "Widget"),
172
- new Product("B2", "Gadget"),
173
- new Product("C3", "Gizmo")
174
- ];
175
-
176
- const target = new Product("B2", "Gadget");
177
- const found = products.find(p => p.equals(target));
72
+ ## Equality Contract
178
73
 
179
- console.log(found); // Product { sku: "B2", name: "Gadget" }
180
- ```
181
-
182
- ### Use with Hash
183
-
184
- When using objects as keys in Map-like structures, combine PartialEq with Hash:
185
-
186
- <InteractiveMacro code={`/** @derive(PartialEq, Hash) */
187
- class Key {
188
- id: number;
189
- type: string;
190
-
191
- constructor(id: number, type: string) {
192
- this.id = id;
193
- this.type = type;
194
- }
195
- }`} />
196
-
197
- ```typescript
198
- const k1 = new Key(1, "user");
199
- const k2 = new Key(1, "user");
74
+ When implementing `PartialEq`, consider also implementing `Hash`:
200
75
 
201
- // Equal objects should have equal hash codes
202
- console.log(k1.equals(k2)); // true
203
- console.log(k1.hashCode() === k2.hashCode()); // true
204
- ```
76
+ - **Reflexivity**: `a.equals(a)` is always true
77
+ - **Symmetry**: `a.equals(b)` implies `b.equals(a)`
78
+ - **Hash consistency**: Equal objects must have equal hash codes
@@ -1,188 +1,96 @@
1
1
  # PartialOrd
2
2
 
3
- *The `PartialOrd` macro generates a `compareTo()` method that implements partial ordering, returning `-1`, `0`, `1`, or `null` for incomparable values.*
3
+ The `PartialOrd` macro generates a `compareTo()` method for **partial ordering**
4
+ comparison. This is analogous to Rust's `PartialOrd` trait, enabling comparison
5
+ between values where some pairs may be incomparable.
4
6
 
5
- ## Basic Usage
7
+ ## Generated Output
6
8
 
7
- <MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
9
+ | Type | Generated Code | Description |
10
+ |------|----------------|-------------|
11
+ | Class | `compareTo(other): Option<number>` | Instance method with optional result |
12
+ | Enum | `partialCompareEnumName(a: EnumName, b: EnumName): Option<number>` | Standalone function returning Option |
13
+ | Interface | `partialCompareInterfaceName(a: InterfaceName, b: InterfaceName): Option<number>` | Standalone function with Option |
14
+ | Type Alias | `partialCompareTypeName(a: TypeName, b: TypeName): Option<number>` | Standalone function with Option |
8
15
 
9
- ```typescript
10
- const t1 = new Temperature(20);
11
- const t2 = new Temperature(30);
12
- const t3 = new Temperature(20);
13
-
14
- console.log(t1.compareTo(t2)); // -1 (t1 < t2)
15
- console.log(t2.compareTo(t1)); // 1 (t2 > t1)
16
- console.log(t1.compareTo(t3)); // 0 (t1 == t3)
16
+ ## Configuration
17
17
 
18
- // Returns null for incomparable types
19
- console.log(t1.compareTo("not a Temperature")); // null
20
- ```
18
+ The `functionNamingStyle` option in `macroforge.json` controls naming:
19
+ - `"suffix"` (default): Suffixes with type name (e.g., `partialCompareMyType`)
20
+ - `"prefix"`: Prefixes with type name (e.g., `myTypePartialCompare`)
21
+ - `"generic"`: Uses TypeScript generics (e.g., `partialCompare<T extends MyType>`)
22
+ - `"namespace"`: Legacy namespace wrapping
21
23
 
22
24
  ## Return Values
23
25
 
24
- The `compareTo()` method returns:
25
-
26
- - `-1` → `this` is less than `other`
27
-
28
- - `0` → `this` equals `other`
29
-
30
- - `1` → `this` is greater than `other`
31
-
32
- - `null` → Values are incomparable (e.g., different types)
33
-
34
- ## Comparison Logic
35
-
36
- The PartialOrd macro compares fields in declaration order with type checking:
37
-
38
- - `number` / `bigint` → Direct numeric comparison
39
-
40
- - `string` → Uses `localeCompare()`
41
-
42
- - `boolean` → `false < true`
26
+ Unlike `Ord`, `PartialOrd` returns an `Option<number>` to handle incomparable values:
43
27
 
44
- - `Date` Compares timestamps; returns `null` if not both Date instances
28
+ - **Option.some(-1)**: `this` is less than `other`
29
+ - **Option.some(0)**: `this` is equal to `other`
30
+ - **Option.some(1)**: `this` is greater than `other`
31
+ - **Option.none()**: Values are incomparable
45
32
 
46
- - `Array` Lexicographic comparison; returns `null` if not both arrays
33
+ ## When to Use PartialOrd vs Ord
47
34
 
48
- - `Object` Calls `compareTo()` if available
35
+ - **PartialOrd**: When some values may not be comparable
36
+ - Example: Floating-point NaN values
37
+ - Example: Mixed-type unions
38
+ - Example: Type mismatches between objects
49
39
 
50
- - **Type mismatch** Returns `null`
40
+ - **Ord**: When all values are guaranteed comparable (total ordering)
51
41
 
52
- ## Field Options
42
+ ## Comparison Strategy
53
43
 
54
- ### @ord(skip)
44
+ Fields are compared **lexicographically** in declaration order:
55
45
 
56
- Use `@ord(skip)` to exclude a field from ordering comparison:
46
+ 1. Compare first field
47
+ 2. If incomparable, return `Option.none()`
48
+ 3. If not equal, return that result wrapped in `Option.some()`
49
+ 4. Otherwise, compare next field
50
+ 5. Continue until a difference is found or all fields are equal
57
51
 
58
- <MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
52
+ ## Type-Specific Comparisons
59
53
 
60
- ```typescript
61
- const i1 = new Item(10, "Widget", "A useful widget");
62
- const i2 = new Item(10, "Widget", "Different description");
63
-
64
- console.log(i1.compareTo(i2)); // 0 (description is skipped)
65
- ```
54
+ | Type | Comparison Method |
55
+ |------|-------------------|
56
+ | `number`/`bigint` | Direct comparison, returns some() |
57
+ | `string` | `localeCompare()` wrapped in some() |
58
+ | `boolean` | false &lt; true, wrapped in some() |
59
+ | null/undefined | Returns none() for mismatched nullability |
60
+ | Arrays | Lexicographic, propagates none() on incomparable elements |
61
+ | `Date` | Timestamp comparison, none() if invalid |
62
+ | Objects | Unwraps nested Option from compareTo() |
66
63
 
67
- ## Handling Null Results
64
+ ## Field-Level Options
68
65
 
69
- When using PartialOrd, always handle the `null` case:
66
+ The `@ord` decorator supports:
70
67
 
71
- <InteractiveMacro code={`/** @derive(PartialOrd) */
72
- class Value {
73
- amount: number;
68
+ - `skip` - Exclude the field from ordering comparison
74
69
 
75
- constructor(amount: number) {
76
- this.amount = amount;
77
- }
78
- }`} />
70
+ ## Example
79
71
 
80
72
  ```typescript
81
- function safeCompare(a: Value, b: unknown): string {
82
- const result = a.compareTo(b);
83
- if (result === null) {
84
- return "incomparable";
85
- } else if (result < 0) {
86
- return "less than";
87
- } else if (result > 0) {
88
- return "greater than";
89
- } else {
90
- return "equal";
91
- }
73
+ @derive(PartialOrd)
74
+ class Temperature {
75
+ value: number | null; // null represents "unknown"
76
+ unit: string;
92
77
  }
93
78
 
94
- const v = new Value(100);
95
- console.log(safeCompare(v, new Value(50))); // "greater than"
96
- console.log(safeCompare(v, "string")); // "incomparable"
97
- ```
98
-
99
- ## Sorting with PartialOrd
100
-
101
- When sorting, handle `null` values appropriately:
102
-
103
- <InteractiveMacro code={`/** @derive(PartialOrd) */
104
- class Score {
105
- value: number;
106
-
107
- constructor(value: number) {
108
- this.value = value;
109
- }
110
- }`} />
111
-
112
- ```typescript
113
- const scores = [
114
- new Score(100),
115
- new Score(50),
116
- new Score(75)
117
- ];
118
-
119
- // Safe sort that handles null (treats null as equal)
120
- scores.sort((a, b) => a.compareTo(b) ?? 0);
121
- // Result: [Score(50), Score(75), Score(100)]
122
- ```
123
-
124
- ## Interface Support
125
-
126
- PartialOrd works with interfaces. For interfaces, a namespace is generated with a `compareTo` function:
127
-
128
- <MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
129
-
130
- ```typescript
131
- const m1: Measurement = { value: 10, unit: "kg" };
132
- const m2: Measurement = { value: 10, unit: "lb" };
133
-
134
- console.log(Measurement.compareTo(m1, m2)); // 1 (kg > lb alphabetically)
135
- ```
136
-
137
- ## Enum Support
138
-
139
- PartialOrd works with enums:
140
-
141
- <MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
142
-
143
- ```typescript
144
- console.log(Size.compareTo(Size.Small, Size.Large)); // -1
145
- console.log(Size.compareTo(Size.Large, Size.Small)); // 1
146
- ```
147
-
148
- ## Type Alias Support
149
-
150
- PartialOrd works with type aliases:
151
-
152
- <MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
153
-
154
- ```typescript
155
- const i1: Interval = { start: 0, end: 10 };
156
- const i2: Interval = { start: 0, end: 20 };
157
-
158
- console.log(Interval.compareTo(i1, i2)); // -1
79
+ // Generated:
80
+ // compareTo(other: unknown): Option<number> {
81
+ // if (this === other) return Option.some(0);
82
+ // if (!(other instanceof Temperature)) return Option.none();
83
+ // const typedOther = other as Temperature;
84
+ // const cmp0 = ...; // Compare value field
85
+ // if (cmp0 === null) return Option.none();
86
+ // if (cmp0 !== 0) return Option.some(cmp0);
87
+ // const cmp1 = ...; // Compare unit field
88
+ // if (cmp1 === null) return Option.none();
89
+ // if (cmp1 !== 0) return Option.some(cmp1);
90
+ // return Option.some(0);
91
+ // }
159
92
  ```
160
93
 
161
- ## PartialOrd vs Ord
94
+ ## Required Import
162
95
 
163
- Choose between `Ord` and `PartialOrd` based on your use case:
164
-
165
- - **Ord** → Use when all values are always comparable (never returns null)
166
-
167
- - **PartialOrd** → Use when comparing with `unknown` types or when some values might be incomparable
168
-
169
- <InteractiveMacro code={`// PartialOrd is safer for public APIs that accept unknown input
170
- /** @derive(PartialOrd) */
171
- class SafeValue {
172
- data: number;
173
- constructor(data: number) {
174
- this.data = data;
175
- }
176
-
177
- // Can safely compare with any value
178
- isGreaterThan(other: unknown): boolean {
179
- const result = this.compareTo(other);
180
- return result !== null && result > 0;
181
- }
182
- }`} />
183
-
184
- ```typescript
185
- const safe = new SafeValue(100);
186
- console.log(safe.isGreaterThan(new SafeValue(50))); // true
187
- console.log(safe.isGreaterThan("invalid")); // false
188
- ```
96
+ The generated code automatically adds an import for `Option` from `macroforge/utils`.