@macroforge/mcp-server 0.1.37 → 0.1.39

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 (43) hide show
  1. package/docs/api/api-overview.md +13 -13
  2. package/docs/api/expand-sync.md +8 -8
  3. package/docs/api/native-plugin.md +15 -15
  4. package/docs/api/position-mapper.md +6 -6
  5. package/docs/api/transform-sync.md +11 -11
  6. package/docs/builtin-macros/clone.md +43 -23
  7. package/docs/builtin-macros/debug.md +50 -18
  8. package/docs/builtin-macros/default.md +79 -28
  9. package/docs/builtin-macros/deserialize/cycleforward-reference-support.md +11 -0
  10. package/docs/builtin-macros/deserialize/example.md +1625 -0
  11. package/docs/builtin-macros/deserialize/overview.md +15 -10
  12. package/docs/builtin-macros/deserialize/union-type-deserialization.md +27 -0
  13. package/docs/builtin-macros/deserialize/validation.md +34 -0
  14. package/docs/builtin-macros/deserialize.md +1608 -23
  15. package/docs/builtin-macros/hash.md +87 -20
  16. package/docs/builtin-macros/macros-overview.md +40 -40
  17. package/docs/builtin-macros/ord.md +56 -31
  18. package/docs/builtin-macros/partial-eq/example.md +526 -0
  19. package/docs/builtin-macros/partial-eq/overview.md +39 -0
  20. package/docs/builtin-macros/partial-eq.md +184 -26
  21. package/docs/builtin-macros/partial-ord.md +68 -30
  22. package/docs/builtin-macros/serialize/example.md +139 -0
  23. package/docs/builtin-macros/serialize/overview.md +32 -0
  24. package/docs/builtin-macros/serialize/type-specific-serialization.md +22 -0
  25. package/docs/builtin-macros/serialize.md +130 -28
  26. package/docs/concepts/architecture.md +2 -2
  27. package/docs/concepts/derive-system.md +25 -39
  28. package/docs/concepts/how-macros-work.md +8 -4
  29. package/docs/custom-macros/custom-overview.md +23 -23
  30. package/docs/custom-macros/rust-setup.md +31 -31
  31. package/docs/custom-macros/ts-macro-derive.md +107 -107
  32. package/docs/custom-macros/ts-quote.md +226 -226
  33. package/docs/getting-started/first-macro.md +38 -28
  34. package/docs/getting-started/installation.md +15 -15
  35. package/docs/integration/cli.md +9 -9
  36. package/docs/integration/configuration.md +16 -16
  37. package/docs/integration/mcp-server.md +6 -6
  38. package/docs/integration/svelte-preprocessor.md +40 -41
  39. package/docs/integration/typescript-plugin.md +13 -12
  40. package/docs/integration/vite-plugin.md +12 -12
  41. package/docs/language-servers/zed.md +1 -1
  42. package/docs/sections.json +88 -2
  43. package/package.json +2 -2
@@ -8,18 +8,11 @@ objects to be used as keys in hash-based collections.
8
8
 
9
9
  | Type | Generated Code | Description |
10
10
  |------|----------------|-------------|
11
- | Class | `hashCode(): number` | Instance method computing hash from all fields |
12
- | Enum | `hashCodeEnumName(value: EnumName): number` | Standalone function hashing by enum value |
13
- | Interface | `hashCodeInterfaceName(value: InterfaceName): number` | Standalone function computing hash |
14
- | Type Alias | `hashCodeTypeName(value: TypeName): number` | Standalone function computing hash |
11
+ | Class | `classNameHashCode(value)` + `static hashCode(value)` | Standalone function + static wrapper method |
12
+ | Enum | `enumNameHashCode(value: EnumName): number` | Standalone function hashing by enum value |
13
+ | Interface | `interfaceNameHashCode(value: InterfaceName): number` | Standalone function computing hash |
14
+ | Type Alias | `typeNameHashCode(value: TypeName): number` | Standalone function computing hash |
15
15
 
16
- ## Configuration
17
-
18
- The `functionNamingStyle` option in `macroforge.json` controls naming:
19
- - `"prefix"` (default): Prefixes with type name (e.g., `myTypeHashCode`)
20
- - `"suffix"`: Suffixes with type name (e.g., `hashCodeMyType`)
21
- - `"generic"`: Uses TypeScript generics (e.g., `hashCode<T extends MyType>`)
22
- - `"namespace"`: Legacy namespace wrapping
23
16
 
24
17
  ## Hash Algorithm
25
18
 
@@ -55,23 +48,97 @@ The `@hash` decorator supports:
55
48
 
56
49
  ## Example
57
50
 
51
+ ```typescript before
52
+ /** @derive(Hash, PartialEq) */
53
+ class User {
54
+ id: number;
55
+ name: string;
56
+
57
+ /** @hash({ skip: true }) */
58
+ cachedScore: number;
59
+ }
60
+ ```
61
+
62
+ ```typescript after
63
+ class User {
64
+ id: number;
65
+ name: string;
66
+
67
+ cachedScore: number;
68
+
69
+ static hashCode(value: User): number {
70
+ return userHashCode(value);
71
+ }
72
+
73
+ static equals(a: User, b: User): boolean {
74
+ return userEquals(a, b);
75
+ }
76
+ }
77
+
78
+ export function userHashCode(value: User): number {
79
+ let hash = 17;
80
+ hash =
81
+ (hash * 31 +
82
+ (Number.isInteger(value.id)
83
+ ? value.id | 0
84
+ : value.id
85
+ .toString()
86
+ .split('')
87
+ .reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) |
88
+ 0;
89
+ hash =
90
+ (hash * 31 +
91
+ (value.name ?? '').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0)) |
92
+ 0;
93
+ return hash;
94
+ }
95
+
96
+ export function userEquals(a: User, b: User): boolean {
97
+ if (a === b) return true;
98
+ return a.id === b.id && a.name === b.name && a.cachedScore === b.cachedScore;
99
+ }
100
+ ```
101
+
102
+ Generated output:
103
+
58
104
  ```typescript
59
- @derive(Hash, PartialEq)
60
105
  class User {
61
106
  id: number;
62
107
  name: string;
63
108
 
64
- @hash(skip) // Cached value shouldn't affect hash
65
109
  cachedScore: number;
110
+
111
+ static hashCode(value: User): number {
112
+ return userHashCode(value);
113
+ }
114
+
115
+ static equals(a: User, b: User): boolean {
116
+ return userEquals(a, b);
117
+ }
66
118
  }
67
119
 
68
- // Generated:
69
- // hashCode(): number {
70
- // let hash = 17;
71
- // hash = (hash * 31 + (Number.isInteger(this.id) ? this.id | 0 : ...)) | 0;
72
- // hash = (hash * 31 + (this.name ?? '').split('').reduce(...)) | 0;
73
- // return hash;
74
- // }
120
+ export function userHashCode(value: User): number {
121
+ let hash = 17;
122
+ hash =
123
+ (hash * 31 +
124
+ (Number.isInteger(value.id)
125
+ ? value.id | 0
126
+ : value.id
127
+ .toString()
128
+ .split('')
129
+ .reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) |
130
+ 0;
131
+ hash =
132
+ (hash * 31 +
133
+ (value.name ?? '').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0)) |
134
+ 0;
135
+ return hash;
136
+ }
137
+
138
+ export function userEquals(a: User, b: User): boolean {
139
+ if (a === b) return true;
140
+ return a.id === b.id && a.name === b.name && a.cachedScore === b.cachedScore;
141
+ }
75
142
  ```
76
143
 
77
144
  ## Hash Contract
@@ -16,57 +16,57 @@
16
16
  Built-in macros don't require imports. Just use them with `@derive`:
17
17
  ```
18
18
  /** @derive(Debug, Clone, PartialEq) */
19
- class User {
19
+ class User &#123;
20
20
  name: string;
21
21
  age: number;
22
22
 
23
- constructor(name: string, age: number) {
23
+ constructor(name: string, age: number) &#123;
24
24
  this.name = name;
25
25
  this.age = age;
26
- }
27
- }
26
+ &#125;
27
+ &#125;
28
28
  ``` ## Interface Support
29
29
  All built-in macros work with interfaces. For interfaces, methods are generated as functions in a namespace with the same name, using `self` as the first parameter:
30
30
  ```
31
31
  /** @derive(Debug, Clone, PartialEq) */
32
- interface Point {
32
+ interface Point &#123;
33
33
  x: number;
34
34
  y: number;
35
- }
35
+ &#125;
36
36
 
37
37
  // Generated namespace:
38
- // namespace Point {
39
- // export function toString(self: Point): string { ... }
40
- // export function clone(self: Point): Point { ... }
41
- // export function equals(self: Point, other: Point): boolean { ... }
42
- // export function hashCode(self: Point): number { ... }
43
- // }
38
+ // namespace Point &#123;
39
+ // export function toString(self: Point): string &#123; ... &#125;
40
+ // export function clone(self: Point): Point &#123; ... &#125;
41
+ // export function equals(self: Point, other: Point): boolean &#123; ... &#125;
42
+ // export function hashCode(self: Point): number &#123; ... &#125;
43
+ // &#125;
44
44
 
45
- const point: Point = { x: 10, y: 20 };
45
+ const point: Point = &#123; x: 10, y: 20 &#125;;
46
46
 
47
47
  // Use the namespace functions
48
- console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
49
- const copy = Point.clone(point); // { x: 10, y: 20 }
48
+ console.log(Point.toString(point)); // "Point &#123; x: 10, y: 20 &#125;"
49
+ const copy = Point.clone(point); // &#123; x: 10, y: 20 &#125;
50
50
  console.log(Point.equals(point, copy)); // true
51
51
  ``` ## Enum Support
52
52
  All built-in macros work with enums. For enums, methods are generated as functions in a namespace with the same name:
53
53
  ```
54
54
  /** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
55
- enum Status {
55
+ enum Status &#123;
56
56
  Active = "active",
57
57
  Inactive = "inactive",
58
58
  Pending = "pending",
59
- }
59
+ &#125;
60
60
 
61
61
  // Generated namespace:
62
- // namespace Status {
63
- // export function toString(value: Status): string { ... }
64
- // export function clone(value: Status): Status { ... }
65
- // export function equals(a: Status, b: Status): boolean { ... }
66
- // export function hashCode(value: Status): number { ... }
67
- // export function toJSON(value: Status): string | number { ... }
68
- // export function fromJSON(data: unknown): Status { ... }
69
- // }
62
+ // namespace Status &#123;
63
+ // export function toString(value: Status): string &#123; ... &#125;
64
+ // export function clone(value: Status): Status &#123; ... &#125;
65
+ // export function equals(a: Status, b: Status): boolean &#123; ... &#125;
66
+ // export function hashCode(value: Status): number &#123; ... &#125;
67
+ // export function toJSON(value: Status): string | number &#123; ... &#125;
68
+ // export function fromJSON(data: unknown): Status &#123; ... &#125;
69
+ // &#125;
70
70
 
71
71
  // Use the namespace functions
72
72
  console.log(Status.toString(Status.Active)); // "Status.Active"
@@ -77,24 +77,24 @@ const parsed = Status.fromJSON("active"); // Status.Active
77
77
  All built-in macros work with type aliases. For object type aliases, field-aware methods are generated in a namespace:
78
78
  ```
79
79
  /** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
80
- type Point = {
80
+ type Point = &#123;
81
81
  x: number;
82
82
  y: number;
83
- };
83
+ &#125;;
84
84
 
85
85
  // Generated namespace:
86
- // namespace Point {
87
- // export function toString(value: Point): string { ... }
88
- // export function clone(value: Point): Point { ... }
89
- // export function equals(a: Point, b: Point): boolean { ... }
90
- // export function hashCode(value: Point): number { ... }
91
- // export function toJSON(value: Point): Record<string, unknown> { ... }
92
- // export function fromJSON(data: unknown): Point { ... }
93
- // }
86
+ // namespace Point &#123;
87
+ // export function toString(value: Point): string &#123; ... &#125;
88
+ // export function clone(value: Point): Point &#123; ... &#125;
89
+ // export function equals(a: Point, b: Point): boolean &#123; ... &#125;
90
+ // export function hashCode(value: Point): number &#123; ... &#125;
91
+ // export function toJSON(value: Point): Record&#x3C;string, unknown> &#123; ... &#125;
92
+ // export function fromJSON(data: unknown): Point &#123; ... &#125;
93
+ // &#125;
94
94
 
95
- const point: Point = { x: 10, y: 20 };
96
- console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
97
- const copy = Point.clone(point); // { x: 10, y: 20 }
95
+ const point: Point = &#123; x: 10, y: 20 &#125;;
96
+ console.log(Point.toString(point)); // "Point &#123; x: 10, y: 20 &#125;"
97
+ const copy = Point.clone(point); // &#123; x: 10, y: 20 &#125;
98
98
  console.log(Point.equals(point, copy)); // true
99
99
  ``` Union type aliases also work, using JSON-based implementations:
100
100
  ```
@@ -102,7 +102,7 @@ console.log(Point.equals(point, copy)); // true
102
102
  type ApiStatus = "loading" | "success" | "error";
103
103
 
104
104
  const status: ApiStatus = "success";
105
- console.log(ApiStatus.toString(status)); // "ApiStatus(\"success\")"
105
+ console.log(ApiStatus.toString(status)); // "ApiStatus(\\"success\\")"
106
106
  console.log(ApiStatus.equals("success", "success")); // true
107
107
  ``` ## Combining Macros
108
108
  All macros can be used together. They don't conflict and each generates independent methods:
@@ -111,7 +111,7 @@ const user = new User("Alice", 30);
111
111
 
112
112
  // Debug
113
113
  console.log(user.toString());
114
- // "User { name: Alice, age: 30 }"
114
+ // "User &#123; name: Alice, age: 30 &#125;"
115
115
 
116
116
  // Clone
117
117
  const copy = user.clone();
@@ -8,29 +8,22 @@ compared with a guaranteed ordering relationship.
8
8
 
9
9
  | Type | Generated Code | Description |
10
10
  |------|----------------|-------------|
11
- | Class | `compareTo(other): number` | Instance method returning -1, 0, or 1 |
12
- | Enum | `compareEnumName(a: EnumName, b: EnumName): number` | Standalone function comparing enum values |
13
- | Interface | `compareInterfaceName(a: InterfaceName, b: InterfaceName): number` | Standalone function comparing fields |
14
- | Type Alias | `compareTypeName(a: TypeName, b: TypeName): number` | Standalone function with type-appropriate comparison |
11
+ | Class | `classNameCompare(a, b)` + `static compareTo(a, b)` | Standalone function + static wrapper method |
12
+ | Enum | `enumNameCompare(a: EnumName, b: EnumName): number` | Standalone function comparing enum values |
13
+ | Interface | `interfaceNameCompare(a: InterfaceName, b: InterfaceName): number` | Standalone function comparing fields |
14
+ | Type Alias | `typeNameCompare(a: TypeName, b: TypeName): number` | Standalone function with type-appropriate comparison |
15
15
 
16
- ## Configuration
17
-
18
- The `functionNamingStyle` option in `macroforge.json` controls naming:
19
- - `"prefix"` (default): Prefixes with type name (e.g., `myTypeCompare`)
20
- - `"suffix"`: Suffixes with type name (e.g., `compareMyType`)
21
- - `"generic"`: Uses TypeScript generics (e.g., `compare<T extends MyType>`)
22
- - `"namespace"`: Legacy namespace wrapping
23
16
 
24
17
  ## Return Values
25
18
 
26
19
  Unlike `PartialOrd`, `Ord` provides **total ordering** - every pair of values
27
20
  can be compared:
28
21
 
29
- - **-1**: `this` is less than `other`
30
- - **0**: `this` is equal to `other`
31
- - **1**: `this` is greater than `other`
22
+ - **-1**: `a` is less than `b`
23
+ - **0**: `a` is equal to `b`
24
+ - **1**: `a` is greater than `b`
32
25
 
33
- The method **never returns null** - all values must be comparable.
26
+ The function **never returns null** - all values must be comparable.
34
27
 
35
28
  ## Comparison Strategy
36
29
 
@@ -60,29 +53,61 @@ The `@ord` decorator supports:
60
53
 
61
54
  ## Example
62
55
 
56
+ ```typescript before
57
+ /** @derive(Ord) */
58
+ class Version {
59
+ major: number;
60
+ minor: number;
61
+ patch: number;
62
+ }
63
+ ```
64
+
65
+ ```typescript after
66
+ class Version {
67
+ major: number;
68
+ minor: number;
69
+ patch: number;
70
+
71
+ static compareTo(a: Version, b: Version): number {
72
+ return versionCompare(a, b);
73
+ }
74
+ }
75
+
76
+ export function versionCompare(a: Version, b: Version): number {
77
+ if (a === b) return 0;
78
+ const cmp0 = a.major < b.major ? -1 : a.major > b.major ? 1 : 0;
79
+ if (cmp0 !== 0) return cmp0;
80
+ const cmp1 = a.minor < b.minor ? -1 : a.minor > b.minor ? 1 : 0;
81
+ if (cmp1 !== 0) return cmp1;
82
+ const cmp2 = a.patch < b.patch ? -1 : a.patch > b.patch ? 1 : 0;
83
+ if (cmp2 !== 0) return cmp2;
84
+ return 0;
85
+ }
86
+ ```
87
+
88
+ Generated output:
89
+
63
90
  ```typescript
64
- @derive(Ord)
65
91
  class Version {
66
92
  major: number;
67
93
  minor: number;
68
94
  patch: number;
95
+
96
+ static compareTo(a: Version, b: Version): number {
97
+ return versionCompare(a, b);
98
+ }
69
99
  }
70
100
 
71
- // Generated:
72
- // compareTo(other: Version): number {
73
- // if (this === other) return 0;
74
- // const typedOther = other;
75
- // const cmp0 = this.major < typedOther.major ? -1 : this.major > typedOther.major ? 1 : 0;
76
- // if (cmp0 !== 0) return cmp0;
77
- // const cmp1 = this.minor < typedOther.minor ? -1 : ...;
78
- // if (cmp1 !== 0) return cmp1;
79
- // const cmp2 = this.patch < typedOther.patch ? -1 : ...;
80
- // if (cmp2 !== 0) return cmp2;
81
- // return 0;
82
- // }
83
-
84
- // Usage:
85
- versions.sort((a, b) => a.compareTo(b));
101
+ export function versionCompare(a: Version, b: Version): number {
102
+ if (a === b) return 0;
103
+ const cmp0 = a.major < b.major ? -1 : a.major > b.major ? 1 : 0;
104
+ if (cmp0 !== 0) return cmp0;
105
+ const cmp1 = a.minor < b.minor ? -1 : a.minor > b.minor ? 1 : 0;
106
+ if (cmp1 !== 0) return cmp1;
107
+ const cmp2 = a.patch < b.patch ? -1 : a.patch > b.patch ? 1 : 0;
108
+ if (cmp2 !== 0) return cmp2;
109
+ return 0;
110
+ }
86
111
  ```
87
112
 
88
113
  ## Ord vs PartialOrd