@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
@@ -2,14 +2,14 @@
2
2
  <span class="stats svelte-1c8t0id">52 exported items *Macroforge provides a programmatic API for expanding macros in TypeScript code.*
3
3
  ## Overview
4
4
  ```
5
- import {
5
+ import &#123;
6
6
  expandSync,
7
7
  transformSync,
8
8
  checkSyntax,
9
9
  parseImportSources,
10
10
  NativePlugin,
11
11
  PositionMapper
12
- } from "macroforge";
12
+ &#125; from "macroforge";
13
13
  ``` ## Core Functions
14
14
  | Function | Description |
15
15
  | --- | --- |
@@ -24,28 +24,28 @@ import {
24
24
  | [`PositionMapper`](../docs/api/position-mapper) | Maps positions between original and expanded code |
25
25
  ## Quick Example
26
26
  ```
27
- import { expandSync } from "macroforge";
27
+ import &#123; expandSync &#125; from "macroforge";
28
28
 
29
- const sourceCode = `
29
+ const sourceCode = \`
30
30
  /** @derive(Debug) */
31
- class User {
31
+ class User &#123;
32
32
  name: string;
33
- constructor(name: string) {
33
+ constructor(name: string) &#123;
34
34
  this.name = name;
35
- }
36
- }
37
- `;
35
+ &#125;
36
+ &#125;
37
+ \`;
38
38
 
39
- const result = expandSync(sourceCode, "user.ts", {
39
+ const result = expandSync(sourceCode, "user.ts", &#123;
40
40
  keepDecorators: false
41
- });
41
+ &#125;);
42
42
 
43
43
  console.log(result.code);
44
44
  // Output: class with toString() method generated
45
45
 
46
- if (result.diagnostics.length > 0) {
46
+ if (result.diagnostics.length > 0) &#123;
47
47
  console.error("Errors:", result.diagnostics);
48
- }
48
+ &#125;
49
49
  ``` ## Detailed Reference
50
50
  - [`expandSync()`](../docs/api/expand-sync) - Full options and return types
51
51
  - [`transformSync()`](../docs/api/transform-sync) - Transform with source maps
@@ -15,13 +15,13 @@ function expandSync(
15
15
  | `options` | `ExpandOptions` | Optional configuration |
16
16
  ## ExpandOptions
17
17
  ```
18
- interface ExpandOptions {
18
+ interface ExpandOptions &#123;
19
19
  // Keep @derive decorators in output (default: false)
20
20
  keepDecorators?: boolean;
21
- }
21
+ &#125;
22
22
  ``` ## ExpandResult
23
23
  ```
24
- interface ExpandResult {
24
+ interface ExpandResult &#123;
25
25
  // Transformed TypeScript code
26
26
  code: string;
27
27
 
@@ -36,17 +36,17 @@ interface ExpandResult {
36
36
 
37
37
  // Position mapping data for source maps
38
38
  sourceMapping?: SourceMappingResult;
39
- }
39
+ &#125;
40
40
  ``` ## MacroDiagnostic
41
41
  ```
42
- interface MacroDiagnostic {
42
+ interface MacroDiagnostic &#123;
43
43
  message: string;
44
44
  severity: "error" | "warning" | "info";
45
- span: {
45
+ span: &#123;
46
46
  start: number;
47
47
  end: number;
48
- };
49
- }
48
+ &#125;;
49
+ &#125;
50
50
  ``` ## Example
51
51
  ```
52
52
  import { expandSync } from "macroforge";
@@ -13,10 +13,10 @@ processFile(
13
13
  options?: ProcessFileOptions
14
14
  ): ExpandResult
15
15
  ``` ```
16
- interface ProcessFileOptions {
16
+ interface ProcessFileOptions &#123;
17
17
  // Cache key - if unchanged, returns cached result
18
18
  version?: string;
19
- }
19
+ &#125;
20
20
  ``` ### getMapper()
21
21
  Get the position mapper for a previously processed file:
22
22
  ```
@@ -39,36 +39,36 @@ setLogFile(path: string): void
39
39
  const plugin = new NativePlugin();
40
40
 
41
41
  // First call - performs expansion
42
- const result1 = plugin.processFile("user.ts", code, { version: "1" });
42
+ const result1 = plugin.processFile("user.ts", code, &#123; version: "1" &#125;);
43
43
 
44
44
  // Same version - returns cached result instantly
45
- const result2 = plugin.processFile("user.ts", code, { version: "1" });
45
+ const result2 = plugin.processFile("user.ts", code, &#123; version: "1" &#125;);
46
46
 
47
47
  // Different version - re-expands
48
- const result3 = plugin.processFile("user.ts", newCode, { version: "2" });
48
+ const result3 = plugin.processFile("user.ts", newCode, &#123; version: "2" &#125;);
49
49
  ``` ## Example: Language Server Integration
50
50
  ```
51
- import { NativePlugin } from "macroforge";
51
+ import &#123; NativePlugin &#125; from "macroforge";
52
52
 
53
- class MacroforgeLanguageService {
53
+ class MacroforgeLanguageService &#123;
54
54
  private plugin = new NativePlugin();
55
55
 
56
- processDocument(uri: string, content: string, version: number) {
56
+ processDocument(uri: string, content: string, version: number) &#123;
57
57
  // Process with version-based caching
58
- const result = this.plugin.processFile(uri, content, {
58
+ const result = this.plugin.processFile(uri, content, &#123;
59
59
  version: String(version)
60
- });
60
+ &#125;);
61
61
 
62
62
  // Get mapper for position translation
63
63
  const mapper = this.plugin.getMapper(uri);
64
64
 
65
- return { result, mapper };
66
- }
65
+ return &#123; result, mapper &#125;;
66
+ &#125;
67
67
 
68
- getSemanticDiagnostics(uri: string, diagnostics: Diagnostic[]) {
68
+ getSemanticDiagnostics(uri: string, diagnostics: Diagnostic[]) &#123;
69
69
  // Map positions from expanded to original
70
70
  return this.plugin.mapDiagnostics(uri, diagnostics);
71
- }
72
- }
71
+ &#125;
72
+ &#125;
73
73
  ``` ## Thread Safety
74
74
  The `NativePlugin` class is thread-safe and can be used from multiple async contexts. Each file is processed in an isolated thread with its own stack space.
@@ -2,16 +2,16 @@
2
2
  *Bidirectional position mapper for translating between original and expanded source positions. This mapper enables IDE features like error reporting, go-to-definition, and hover to work correctly with macro-expanded code by translating positions between the original source (what the user wrote) and the expanded source (what the compiler sees).*
3
3
  ## Getting a Mapper
4
4
  ```
5
- import { NativePlugin, PositionMapper } from "macroforge";
5
+ import &#123; NativePlugin, PositionMapper &#125; from "macroforge";
6
6
 
7
7
  const plugin = new NativePlugin();
8
- const result = plugin.processFile("user.ts", code, { version: "1" });
8
+ const result = plugin.processFile("user.ts", code, &#123; version: "1" &#125;);
9
9
 
10
10
  // Get the mapper for this file
11
11
  const mapper = plugin.getMapper("user.ts");
12
- if (mapper) {
12
+ if (mapper) &#123;
13
13
  // Use the mapper...
14
- }
14
+ &#125;
15
15
  ``` ## Methods
16
16
  ### isEmpty()
17
17
  Check if the mapper has any mappings:
@@ -39,10 +39,10 @@ generatedBy(pos: number): string | null
39
39
  ```
40
40
  mapSpanToOriginal(start: number, length: number): SpanResult | null
41
41
 
42
- interface SpanResult {
42
+ interface SpanResult &#123;
43
43
  start: number;
44
44
  length: number;
45
- }
45
+ &#125;
46
46
  ``` ### mapSpanToExpanded()
47
47
  Map a span from original to expanded code:
48
48
  ```
@@ -13,7 +13,7 @@ function transformSync(
13
13
  | `filepath` | `string` | File path (used for error reporting) |
14
14
  ## TransformResult
15
15
  ```
16
- interface TransformResult {
16
+ interface TransformResult &#123;
17
17
  // Transformed TypeScript code
18
18
  code: string;
19
19
 
@@ -25,7 +25,7 @@ interface TransformResult {
25
25
 
26
26
  // Macro expansion metadata
27
27
  metadata?: string;
28
- }
28
+ &#125;
29
29
  ``` ## Comparison with expandSync()
30
30
  | Feature | `expandSync` | `transformSync` |
31
31
  | --- | --- | --- |
@@ -35,29 +35,29 @@ interface TransformResult {
35
35
  | Use Case | General purpose | Build tools |
36
36
  ## Example
37
37
  ```
38
- import { transformSync } from "macroforge";
38
+ import &#123; transformSync &#125; from "macroforge";
39
39
 
40
- const sourceCode = `
40
+ const sourceCode = \`
41
41
  /** @derive(Debug) */
42
- class User {
42
+ class User &#123;
43
43
  name: string;
44
- }
45
- `;
44
+ &#125;
45
+ \`;
46
46
 
47
47
  const result = transformSync(sourceCode, "user.ts");
48
48
 
49
49
  console.log(result.code);
50
50
 
51
- if (result.types) {
51
+ if (result.types) &#123;
52
52
  // Write to .d.ts file
53
53
  fs.writeFileSync("user.d.ts", result.types);
54
- }
54
+ &#125;
55
55
 
56
- if (result.metadata) {
56
+ if (result.metadata) &#123;
57
57
  // Parse and use metadata
58
58
  const meta = JSON.parse(result.metadata);
59
59
  console.log("Macros expanded:", meta);
60
- }
60
+ &#125;
61
61
  ``` ## When to Use
62
62
  Use `transformSync` when:
63
63
  - Building custom integrations
@@ -8,18 +8,11 @@ independent copies of values.
8
8
 
9
9
  | Type | Generated Code | Description |
10
10
  |------|----------------|-------------|
11
- | Class | `clone(): ClassName` | Instance method creating a new instance with copied fields |
12
- | Enum | `cloneEnumName(value: EnumName): EnumName` | Standalone function (enums are primitives, returns value as-is) |
13
- | Interface | `cloneInterfaceName(value: InterfaceName): InterfaceName` | Standalone function creating a new object literal |
14
- | Type Alias | `cloneTypeName(value: TypeName): TypeName` | Standalone function with spread copy for objects |
11
+ | Class | `classNameClone(value)` + `static clone(value)` | Standalone function + static wrapper method |
12
+ | Enum | `enumNameClone(value: EnumName): EnumName` | Standalone function (enums are primitives, returns value as-is) |
13
+ | Interface | `interfaceNameClone(value: InterfaceName): InterfaceName` | Standalone function creating a new object literal |
14
+ | Type Alias | `typeNameClone(value: TypeName): TypeName` | Standalone function with spread copy for objects |
15
15
 
16
- ## Configuration
17
-
18
- The `functionNamingStyle` option in `macroforge.json` controls naming:
19
- - `"prefix"` (default): Prefixes with type name (e.g., `myTypeClone`)
20
- - `"suffix"`: Suffixes with type name (e.g., `cloneMyType`)
21
- - `"generic"`: Uses TypeScript generics (e.g., `clone<T extends MyType>`)
22
- - `"namespace"`: Legacy namespace wrapping
23
16
 
24
17
  ## Cloning Strategy
25
18
 
@@ -34,28 +27,55 @@ and the caller should clone them explicitly.
34
27
 
35
28
  ## Example
36
29
 
37
- ```typescript
38
- @derive(Clone)
30
+ ```typescript before
31
+ /** @derive(Clone) */
32
+ class Point {
33
+ x: number;
34
+ y: number;
35
+ }
36
+ ```
37
+
38
+ ```typescript after
39
39
  class Point {
40
40
  x: number;
41
41
  y: number;
42
+
43
+ static clone(value: Point): Point {
44
+ return pointClone(value);
45
+ }
46
+ }
47
+
48
+ export function pointClone(value: Point): Point {
49
+ const cloned = Object.create(Object.getPrototypeOf(value));
50
+ cloned.x = value.x;
51
+ cloned.y = value.y;
52
+ return cloned;
42
53
  }
54
+ ```
55
+
56
+ Generated output:
57
+
58
+ ```typescript
59
+ class Point {
60
+ x: number;
61
+ y: number;
43
62
 
44
- // Generated:
45
- // clone(): Point {
46
- // const cloned = Object.create(Object.getPrototypeOf(this));
47
- // cloned.x = this.x;
48
- // cloned.y = this.y;
49
- // return cloned;
50
- // }
63
+ static clone(value: Point): Point {
64
+ return pointClone(value);
65
+ }
66
+ }
51
67
 
52
- const p1 = new Point();
53
- const p2 = p1.clone(); // Creates a new Point with same values
68
+ export function pointClone(value: Point): Point {
69
+ const cloned = Object.create(Object.getPrototypeOf(value));
70
+ cloned.x = value.x;
71
+ cloned.y = value.y;
72
+ return cloned;
73
+ }
54
74
  ```
55
75
 
56
76
  ## Implementation Notes
57
77
 
58
- - **Classes**: Uses `Object.create(Object.getPrototypeOf(this))` to preserve
78
+ - **Classes**: Uses `Object.create(Object.getPrototypeOf(value))` to preserve
59
79
  the prototype chain, ensuring `instanceof` checks work correctly
60
80
  - **Enums**: Simply returns the value (enums are primitives in TypeScript)
61
81
  - **Interfaces/Type Aliases**: Creates new object literals with spread operator
@@ -5,24 +5,17 @@ TypeScript classes, interfaces, enums, and type aliases.
5
5
 
6
6
  ## Generated Output
7
7
 
8
- **Classes**: Generates an instance method returning a string
9
- like `"ClassName { field1: value1, field2: value2 }"`.
8
+ **Classes**: Generates a standalone function `classNameToString(value)` and a static wrapper
9
+ method `static toString(value)` returning a string like `"ClassName { field1: value1, field2: value2 }"`.
10
10
 
11
- **Enums**: Generates a standalone function `toStringEnumName(value)` that performs
11
+ **Enums**: Generates a standalone function `enumNameToString(value)` that performs
12
12
  reverse lookup on numeric enums.
13
13
 
14
- **Interfaces**: Generates a standalone function `toStringInterfaceName(value)`.
14
+ **Interfaces**: Generates a standalone function `interfaceNameToString(value)`.
15
15
 
16
16
  **Type Aliases**: Generates a standalone function using JSON.stringify for
17
17
  complex types, or field enumeration for object types.
18
18
 
19
- ## Configuration
20
-
21
- The `functionNamingStyle` option in `macroforge.json` controls naming:
22
- - `"prefix"` (default): Prefixes with type name (e.g., `myTypeToString`)
23
- - `"suffix"`: Suffixes with type name (e.g., `toStringMyType`)
24
- - `"generic"`: Uses TypeScript generics (e.g., `toString<T extends MyType>`)
25
- - `"namespace"`: Legacy namespace wrapping
26
19
 
27
20
  ## Field-Level Options
28
21
 
@@ -33,20 +26,59 @@ The `@debug` decorator supports:
33
26
 
34
27
  ## Example
35
28
 
29
+ ```typescript before
30
+ /** @derive(Debug) */
31
+ class User {
32
+ /** @debug({ rename: "id" }) */
33
+ userId: number;
34
+
35
+ /** @debug({ skip: true }) */
36
+ password: string;
37
+
38
+ email: string;
39
+ }
40
+ ```
41
+
42
+ ```typescript after
43
+ class User {
44
+ userId: number;
45
+
46
+ password: string;
47
+
48
+ email: string;
49
+
50
+ static toString(value: User): string {
51
+ return userToString(value);
52
+ }
53
+ }
54
+
55
+ export function userToString(value: User): string {
56
+ const parts: string[] = [];
57
+ parts.push('id: ' + value.userId);
58
+ parts.push('email: ' + value.email);
59
+ return 'User { ' + parts.join(', ') + ' }';
60
+ }
61
+ ```
62
+
63
+ Generated output:
64
+
36
65
  ```typescript
37
- @derive(Debug)
38
66
  class User {
39
- @debug(rename = "id")
40
67
  userId: number;
41
68
 
42
- @debug(skip)
43
69
  password: string;
44
70
 
45
71
  email: string;
72
+
73
+ static toString(value: User): string {
74
+ return userToString(value);
75
+ }
46
76
  }
47
77
 
48
- // Generated:
49
- // toString(): string {
50
- // return "User { id: " + this.userId + ", email: " + this.email + " }";
51
- // }
78
+ export function userToString(value: User): string {
79
+ const parts: string[] = [];
80
+ parts.push('id: ' + value.userId);
81
+ parts.push('email: ' + value.email);
82
+ return 'User { ' + parts.join(', ') + ' }';
83
+ }
52
84
  ```
@@ -13,13 +13,6 @@ a standard way to create "zero" or "empty" instances of types.
13
13
  | Interface | `defaultValueInterfaceName(): InterfaceName` | Standalone function returning object literal |
14
14
  | Type Alias | `defaultValueTypeName(): TypeName` | Standalone function with type-appropriate default |
15
15
 
16
- ## Configuration
17
-
18
- The `functionNamingStyle` option in `macroforge.json` controls naming:
19
- - `"prefix"` (default): Prefixes with type name (e.g., `myTypeDefaultValue`)
20
- - `"suffix"`: Suffixes with type name (e.g., `defaultValueMyType`)
21
- - `"generic"`: Uses TypeScript generics (e.g., `defaultValue<T extends MyType>`)
22
- - `"namespace"`: Legacy namespace wrapping
23
16
 
24
17
  ## Default Values by Type
25
18
 
@@ -50,47 +43,105 @@ The `@default` decorator allows specifying explicit default values:
50
43
 
51
44
  ## Example
52
45
 
53
- ```typescript
54
- @derive(Default)
46
+ ```typescript before
47
+ /** @derive(Default) */
55
48
  class UserSettings {
56
- @default("light")
49
+ /** @default("light") */
57
50
  theme: string;
58
51
 
59
- @default(10)
52
+ /** @default(10) */
60
53
  pageSize: number;
61
54
 
62
- notifications: boolean; // Uses type default: false
55
+ notifications: boolean; // Uses type default: false
63
56
  }
57
+ ```
58
+
59
+ ```typescript after
60
+ class UserSettings {
61
+ theme: string;
64
62
 
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
- // }
63
+ pageSize: number;
64
+
65
+ notifications: boolean; // Uses type default: false
66
+
67
+ static defaultValue(): UserSettings {
68
+ const instance = new UserSettings();
69
+ instance.theme = 'light';
70
+ instance.pageSize = 10;
71
+ instance.notifications = false;
72
+ return instance;
73
+ }
74
+ }
75
+ ```
76
+
77
+ Generated output:
78
+
79
+ ```typescript
80
+ class UserSettings {
81
+ theme: string;
82
+
83
+ pageSize: number;
84
+
85
+ notifications: boolean; // Uses type default: false
86
+
87
+ static defaultValue(): UserSettings {
88
+ const instance = new UserSettings();
89
+ instance.theme = 'light';
90
+ instance.pageSize = 10;
91
+ instance.notifications = false;
92
+ return instance;
93
+ }
94
+ }
73
95
  ```
74
96
 
75
97
  ## Enum Defaults
76
98
 
77
99
  For enums, mark one variant with `@default`:
78
100
 
101
+ ```typescript before
102
+ /** @derive(Default) */
103
+ enum Status {
104
+ /** @default */
105
+ Pending,
106
+ Active,
107
+ Completed
108
+ }
109
+ ```
110
+
111
+ ```typescript after
112
+ enum Status {
113
+ /** @default */
114
+ Pending,
115
+ Active,
116
+ Completed
117
+ }
118
+
119
+ export function statusDefaultValue(): Status {
120
+ return Status.Pending;
121
+ }
122
+
123
+ export const Status = {
124
+ defaultValue: statusDefaultValue
125
+ } as const;
126
+ ```
127
+
128
+ Generated output:
129
+
79
130
  ```typescript
80
- @derive(Default)
81
131
  enum Status {
82
- @default
132
+ /** @default */
83
133
  Pending,
84
134
  Active,
85
135
  Completed
86
136
  }
87
137
 
88
- // Generated:
89
- // export namespace Status {
90
- // export function defaultValue(): Status {
91
- // return Status.Pending;
92
- // }
93
- // }
138
+ export function statusDefaultValue(): Status {
139
+ return Status.Pending;
140
+ }
141
+
142
+ export const Status = {
143
+ defaultValue: statusDefaultValue
144
+ } as const;
94
145
  ```
95
146
 
96
147
  ## Error Handling
@@ -0,0 +1,11 @@
1
+ ## Cycle/Forward-Reference Support
2
+
3
+ Uses deferred patching to handle references:
4
+
5
+ 1. When encountering `{ "__ref": id }`, returns a `PendingRef` marker
6
+ 2. Continues deserializing other fields
7
+ 3. After all objects are created, `ctx.applyPatches()` resolves all pending references
8
+
9
+ References only apply to object-shaped, serializable values. The generator avoids probing for
10
+ `__ref` on primitive-like fields (including literal unions and `T | null` where `T` is primitive-like),
11
+ and it parses `Date` / `Date | null` from ISO strings without treating them as references.