@macroforge/mcp-server 0.1.32 → 0.1.34
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 +68 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/docs-loader.d.ts +133 -5
- package/dist/tools/docs-loader.d.ts.map +1 -1
- package/dist/tools/docs-loader.js +131 -15
- package/dist/tools/docs-loader.js.map +1 -1
- package/dist/tools/index.d.ts +48 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +163 -14
- package/dist/tools/index.js.map +1 -1
- package/docs/api/api-overview.md +24 -46
- package/docs/api/expand-sync.md +24 -51
- package/docs/api/native-plugin.md +24 -56
- package/docs/api/position-mapper.md +34 -76
- package/docs/api/transform-sync.md +27 -59
- package/docs/builtin-macros/clone.md +150 -68
- package/docs/builtin-macros/debug.md +216 -81
- package/docs/builtin-macros/default.md +234 -91
- package/docs/builtin-macros/deserialize.md +891 -166
- package/docs/builtin-macros/hash.md +238 -82
- package/docs/builtin-macros/macros-overview.md +42 -103
- package/docs/builtin-macros/ord.md +205 -92
- package/docs/builtin-macros/partial-eq.md +178 -97
- package/docs/builtin-macros/partial-ord.md +209 -98
- package/docs/builtin-macros/serialize.md +326 -137
- package/docs/concepts/architecture.md +40 -99
- package/docs/concepts/derive-system.md +132 -125
- package/docs/concepts/how-macros-work.md +52 -84
- package/docs/custom-macros/custom-overview.md +17 -39
- package/docs/custom-macros/rust-setup.md +22 -55
- package/docs/custom-macros/ts-macro-derive.md +43 -107
- package/docs/custom-macros/ts-quote.md +177 -507
- package/docs/getting-started/first-macro.md +108 -33
- package/docs/getting-started/installation.md +32 -73
- package/docs/integration/cli.md +70 -156
- package/docs/integration/configuration.md +32 -75
- package/docs/integration/integration-overview.md +16 -55
- package/docs/integration/mcp-server.md +30 -69
- package/docs/integration/svelte-preprocessor.md +60 -83
- package/docs/integration/typescript-plugin.md +32 -74
- package/docs/integration/vite-plugin.md +30 -79
- package/docs/language-servers/ls-overview.md +22 -46
- package/docs/language-servers/svelte.md +30 -69
- package/docs/language-servers/zed.md +34 -72
- package/docs/roadmap/roadmap.md +54 -130
- package/docs/sections.json +3 -262
- package/package.json +2 -2
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
# PartialOrd
|
|
2
|
+
*The `PartialOrd` macro generates a `compareTo()` method for **partial ordering** comparison. This is analogous to Rust's `PartialOrd` trait, enabling comparison between values where some pairs may be incomparable.*
|
|
3
|
+
## Basic Usage
|
|
4
|
+
**Before:**
|
|
5
|
+
```
|
|
6
|
+
/** @derive(PartialOrd) */
|
|
7
|
+
class Temperature {
|
|
8
|
+
celsius: number;
|
|
2
9
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
+
constructor(celsius: number) {
|
|
11
|
+
this.celsius = celsius;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
**After:**
|
|
16
|
+
```
|
|
17
|
+
import { Option } from 'macroforge/utils';
|
|
18
|
+
|
|
19
|
+
class Temperature {
|
|
20
|
+
celsius: number;
|
|
21
|
+
|
|
22
|
+
constructor(celsius: number) {
|
|
23
|
+
this.celsius = celsius;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
compareTo(other: unknown): Option<number> {
|
|
27
|
+
if (this === other) return Option.some(0);
|
|
28
|
+
if (!(other instanceof Temperature)) return Option.none();
|
|
29
|
+
const typedOther = other as Temperature;
|
|
30
|
+
const cmp0 =
|
|
31
|
+
this.celsius < typedOther.celsius ? -1 : this.celsius > typedOther.celsius ? 1 : 0;
|
|
32
|
+
if (cmp0 === null) return Option.none();
|
|
33
|
+
if (cmp0 !== 0) return Option.some(cmp0);
|
|
34
|
+
return Option.some(0);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
``` ```
|
|
10
38
|
const t1 = new Temperature(20);
|
|
11
39
|
const t2 = new Temperature(30);
|
|
12
40
|
const t3 = new Temperature(20);
|
|
@@ -17,67 +45,88 @@ console.log(t1.compareTo(t3)); // 0 (t1 == t3)
|
|
|
17
45
|
|
|
18
46
|
// Returns null for incomparable types
|
|
19
47
|
console.log(t1.compareTo("not a Temperature")); // null
|
|
48
|
+
``` ## Return Values
|
|
49
|
+
The `compareTo()` method returns:
|
|
50
|
+
- `-1` → `this` is less than `other`
|
|
51
|
+
- `0` → `this` equals `other`
|
|
52
|
+
- `1` → `this` is greater than `other`
|
|
53
|
+
- `null` → Values are incomparable (e.g., different types)
|
|
54
|
+
## Comparison Logic
|
|
55
|
+
The PartialOrd macro compares fields in declaration order with type checking:
|
|
56
|
+
- `number` / `bigint` → Direct numeric comparison
|
|
57
|
+
- `string` → Uses `localeCompare()`
|
|
58
|
+
- `boolean` → `false < true`
|
|
59
|
+
- `Date` → Compares timestamps; returns `null` if not both Date instances
|
|
60
|
+
- `Array` → Lexicographic comparison; returns `null` if not both arrays
|
|
61
|
+
- `Object` → Calls `compareTo()` if available
|
|
62
|
+
- **Type mismatch** → Returns `null`
|
|
63
|
+
## Field Options
|
|
64
|
+
### @ord(skip)
|
|
65
|
+
Use `@ord(skip)` to exclude a field from ordering comparison:
|
|
66
|
+
**Before:**
|
|
20
67
|
```
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
/** @derive(PartialOrd) */
|
|
69
|
+
class Item {
|
|
70
|
+
price: number;
|
|
71
|
+
name: string;
|
|
72
|
+
|
|
73
|
+
/** @ord(skip) */
|
|
74
|
+
description: string;
|
|
75
|
+
|
|
76
|
+
constructor(price: number, name: string, description: string) {
|
|
77
|
+
this.price = price;
|
|
78
|
+
this.name = name;
|
|
79
|
+
this.description = description;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
**After:**
|
|
84
|
+
```
|
|
85
|
+
import { Option } from 'macroforge/utils';
|
|
86
|
+
|
|
87
|
+
class Item {
|
|
88
|
+
price: number;
|
|
89
|
+
name: string;
|
|
90
|
+
|
|
91
|
+
description: string;
|
|
92
|
+
|
|
93
|
+
constructor(price: number, name: string, description: string) {
|
|
94
|
+
this.price = price;
|
|
95
|
+
this.name = name;
|
|
96
|
+
this.description = description;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
compareTo(other: unknown): Option<number> {
|
|
100
|
+
if (this === other) return Option.some(0);
|
|
101
|
+
if (!(other instanceof Item)) return Option.none();
|
|
102
|
+
const typedOther = other as Item;
|
|
103
|
+
const cmp0 = this.price < typedOther.price ? -1 : this.price > typedOther.price ? 1 : 0;
|
|
104
|
+
if (cmp0 === null) return Option.none();
|
|
105
|
+
if (cmp0 !== 0) return Option.some(cmp0);
|
|
106
|
+
const cmp1 = this.name.localeCompare(typedOther.name);
|
|
107
|
+
if (cmp1 === null) return Option.none();
|
|
108
|
+
if (cmp1 !== 0) return Option.some(cmp1);
|
|
109
|
+
return Option.some(0);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
``` ```
|
|
61
113
|
const i1 = new Item(10, "Widget", "A useful widget");
|
|
62
114
|
const i2 = new Item(10, "Widget", "Different description");
|
|
63
115
|
|
|
64
116
|
console.log(i1.compareTo(i2)); // 0 (description is skipped)
|
|
117
|
+
``` ## Handling Null Results
|
|
118
|
+
When using PartialOrd, always handle the `null` case:
|
|
119
|
+
**Source:**
|
|
65
120
|
```
|
|
66
|
-
|
|
67
|
-
## Handling Null Results
|
|
68
|
-
|
|
69
|
-
When using PartialOrd, always handle the `null` case:
|
|
70
|
-
|
|
71
|
-
<InteractiveMacro code={`/** @derive(PartialOrd) */
|
|
121
|
+
/** @derive(PartialOrd) */
|
|
72
122
|
class Value {
|
|
73
123
|
amount: number;
|
|
74
124
|
|
|
75
125
|
constructor(amount: number) {
|
|
76
126
|
this.amount = amount;
|
|
77
127
|
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
128
|
+
}
|
|
129
|
+
``` ```
|
|
81
130
|
function safeCompare(a: Value, b: unknown): string {
|
|
82
131
|
const result = a.compareTo(b);
|
|
83
132
|
if (result === null) {
|
|
@@ -94,22 +143,19 @@ function safeCompare(a: Value, b: unknown): string {
|
|
|
94
143
|
const v = new Value(100);
|
|
95
144
|
console.log(safeCompare(v, new Value(50))); // "greater than"
|
|
96
145
|
console.log(safeCompare(v, "string")); // "incomparable"
|
|
146
|
+
``` ## Sorting with PartialOrd
|
|
147
|
+
When sorting, handle `null` values appropriately:
|
|
148
|
+
**Source:**
|
|
97
149
|
```
|
|
98
|
-
|
|
99
|
-
## Sorting with PartialOrd
|
|
100
|
-
|
|
101
|
-
When sorting, handle `null` values appropriately:
|
|
102
|
-
|
|
103
|
-
<InteractiveMacro code={`/** @derive(PartialOrd) */
|
|
150
|
+
/** @derive(PartialOrd) */
|
|
104
151
|
class Score {
|
|
105
152
|
value: number;
|
|
106
153
|
|
|
107
154
|
constructor(value: number) {
|
|
108
155
|
this.value = value;
|
|
109
156
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
157
|
+
}
|
|
158
|
+
``` ```
|
|
113
159
|
const scores = [
|
|
114
160
|
new Score(100),
|
|
115
161
|
new Score(50),
|
|
@@ -119,54 +165,120 @@ const scores = [
|
|
|
119
165
|
// Safe sort that handles null (treats null as equal)
|
|
120
166
|
scores.sort((a, b) => a.compareTo(b) ?? 0);
|
|
121
167
|
// Result: [Score(50), Score(75), Score(100)]
|
|
168
|
+
``` ## Interface Support
|
|
169
|
+
PartialOrd works with interfaces. For interfaces, a namespace is generated with a `compareTo` function:
|
|
170
|
+
**Before:**
|
|
122
171
|
```
|
|
172
|
+
/** @derive(PartialOrd) */
|
|
173
|
+
interface Measurement {
|
|
174
|
+
value: number;
|
|
175
|
+
unit: string;
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
**After:**
|
|
179
|
+
```
|
|
180
|
+
import { Option } from 'macroforge/utils';
|
|
123
181
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
|
|
182
|
+
interface Measurement {
|
|
183
|
+
value: number;
|
|
184
|
+
unit: string;
|
|
185
|
+
}
|
|
129
186
|
|
|
130
|
-
|
|
187
|
+
export namespace Measurement {
|
|
188
|
+
export function compareTo(self: Measurement, other: Measurement): Option<number> {
|
|
189
|
+
if (self === other) return Option.some(0);
|
|
190
|
+
const cmp0 = self.value < other.value ? -1 : self.value > other.value ? 1 : 0;
|
|
191
|
+
if (cmp0 === null) return Option.none();
|
|
192
|
+
if (cmp0 !== 0) return Option.some(cmp0);
|
|
193
|
+
const cmp1 = self.unit.localeCompare(other.unit);
|
|
194
|
+
if (cmp1 === null) return Option.none();
|
|
195
|
+
if (cmp1 !== 0) return Option.some(cmp1);
|
|
196
|
+
return Option.some(0);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
``` ```
|
|
131
200
|
const m1: Measurement = { value: 10, unit: "kg" };
|
|
132
201
|
const m2: Measurement = { value: 10, unit: "lb" };
|
|
133
202
|
|
|
134
203
|
console.log(Measurement.compareTo(m1, m2)); // 1 (kg > lb alphabetically)
|
|
204
|
+
``` ## Enum Support
|
|
205
|
+
PartialOrd works with enums:
|
|
206
|
+
**Before:**
|
|
135
207
|
```
|
|
208
|
+
/** @derive(PartialOrd) */
|
|
209
|
+
enum Size {
|
|
210
|
+
Small = 1,
|
|
211
|
+
Medium = 2,
|
|
212
|
+
Large = 3
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
**After:**
|
|
216
|
+
```
|
|
217
|
+
import { Option } from 'macroforge/utils';
|
|
136
218
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
219
|
+
enum Size {
|
|
220
|
+
Small = 1,
|
|
221
|
+
Medium = 2,
|
|
222
|
+
Large = 3
|
|
223
|
+
}
|
|
142
224
|
|
|
143
|
-
|
|
225
|
+
export namespace Size {
|
|
226
|
+
export function compareTo(a: Size, b: Size): Option<number> {
|
|
227
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
228
|
+
return Option.some(a < b ? -1 : a > b ? 1 : 0);
|
|
229
|
+
}
|
|
230
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
231
|
+
return Option.some(a.localeCompare(b));
|
|
232
|
+
}
|
|
233
|
+
return a === b ? Option.some(0) : Option.none();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
``` ```
|
|
144
237
|
console.log(Size.compareTo(Size.Small, Size.Large)); // -1
|
|
145
238
|
console.log(Size.compareTo(Size.Large, Size.Small)); // 1
|
|
239
|
+
``` ## Type Alias Support
|
|
240
|
+
PartialOrd works with type aliases:
|
|
241
|
+
**Before:**
|
|
146
242
|
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
```
|
|
243
|
+
/** @derive(PartialOrd) */
|
|
244
|
+
type Interval = {
|
|
245
|
+
start: number;
|
|
246
|
+
end: number;
|
|
247
|
+
};
|
|
248
|
+
```
|
|
249
|
+
**After:**
|
|
250
|
+
```
|
|
251
|
+
import { Option } from 'macroforge/utils';
|
|
252
|
+
|
|
253
|
+
type Interval = {
|
|
254
|
+
start: number;
|
|
255
|
+
end: number;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export namespace Interval {
|
|
259
|
+
export function compareTo(a: Interval, b: Interval): Option<number> {
|
|
260
|
+
if (a === b) return Option.some(0);
|
|
261
|
+
const cmp0 = a.start < b.start ? -1 : a.start > b.start ? 1 : 0;
|
|
262
|
+
if (cmp0 === null) return Option.none();
|
|
263
|
+
if (cmp0 !== 0) return Option.some(cmp0);
|
|
264
|
+
const cmp1 = a.end < b.end ? -1 : a.end > b.end ? 1 : 0;
|
|
265
|
+
if (cmp1 === null) return Option.none();
|
|
266
|
+
if (cmp1 !== 0) return Option.some(cmp1);
|
|
267
|
+
return Option.some(0);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
``` ```
|
|
155
271
|
const i1: Interval = { start: 0, end: 10 };
|
|
156
272
|
const i2: Interval = { start: 0, end: 20 };
|
|
157
273
|
|
|
158
274
|
console.log(Interval.compareTo(i1, i2)); // -1
|
|
275
|
+
``` ## PartialOrd vs Ord
|
|
276
|
+
Choose between `Ord` and `PartialOrd` based on your use case:
|
|
277
|
+
- **Ord** → Use when all values are always comparable (never returns null)
|
|
278
|
+
- **PartialOrd** → Use when comparing with `unknown` types or when some values might be incomparable
|
|
279
|
+
**Source:**
|
|
159
280
|
```
|
|
160
|
-
|
|
161
|
-
## PartialOrd vs Ord
|
|
162
|
-
|
|
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
|
|
281
|
+
// PartialOrd is safer for public APIs that accept unknown input
|
|
170
282
|
/** @derive(PartialOrd) */
|
|
171
283
|
class SafeValue {
|
|
172
284
|
data: number;
|
|
@@ -179,9 +291,8 @@ class SafeValue {
|
|
|
179
291
|
const result = this.compareTo(other);
|
|
180
292
|
return result !== null && result > 0;
|
|
181
293
|
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
294
|
+
}
|
|
295
|
+
``` ```
|
|
185
296
|
const safe = new SafeValue(100);
|
|
186
297
|
console.log(safe.isGreaterThan(new SafeValue(50))); // true
|
|
187
298
|
console.log(safe.isGreaterThan("invalid")); // false
|