@macroforge/mcp-server 0.1.17

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 (46) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +47 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/tools/docs-loader.d.ts +30 -0
  6. package/dist/tools/docs-loader.d.ts.map +1 -0
  7. package/dist/tools/docs-loader.js +112 -0
  8. package/dist/tools/docs-loader.js.map +1 -0
  9. package/dist/tools/index.d.ts +6 -0
  10. package/dist/tools/index.d.ts.map +1 -0
  11. package/dist/tools/index.js +348 -0
  12. package/dist/tools/index.js.map +1 -0
  13. package/docs/api/api-overview.md +75 -0
  14. package/docs/api/expand-sync.md +121 -0
  15. package/docs/api/native-plugin.md +106 -0
  16. package/docs/api/position-mapper.md +127 -0
  17. package/docs/api/transform-sync.md +98 -0
  18. package/docs/builtin-macros/clone.md +180 -0
  19. package/docs/builtin-macros/debug.md +222 -0
  20. package/docs/builtin-macros/default.md +192 -0
  21. package/docs/builtin-macros/deserialize.md +662 -0
  22. package/docs/builtin-macros/hash.md +205 -0
  23. package/docs/builtin-macros/macros-overview.md +169 -0
  24. package/docs/builtin-macros/ord.md +258 -0
  25. package/docs/builtin-macros/partial-eq.md +306 -0
  26. package/docs/builtin-macros/partial-ord.md +268 -0
  27. package/docs/builtin-macros/serialize.md +321 -0
  28. package/docs/concepts/architecture.md +139 -0
  29. package/docs/concepts/derive-system.md +173 -0
  30. package/docs/concepts/how-macros-work.md +124 -0
  31. package/docs/custom-macros/custom-overview.md +84 -0
  32. package/docs/custom-macros/rust-setup.md +146 -0
  33. package/docs/custom-macros/ts-macro-derive.md +307 -0
  34. package/docs/custom-macros/ts-quote.md +696 -0
  35. package/docs/getting-started/first-macro.md +120 -0
  36. package/docs/getting-started/installation.md +110 -0
  37. package/docs/integration/cli.md +207 -0
  38. package/docs/integration/configuration.md +116 -0
  39. package/docs/integration/integration-overview.md +51 -0
  40. package/docs/integration/typescript-plugin.md +96 -0
  41. package/docs/integration/vite-plugin.md +126 -0
  42. package/docs/language-servers/ls-overview.md +47 -0
  43. package/docs/language-servers/svelte-ls.md +80 -0
  44. package/docs/language-servers/zed-extensions.md +84 -0
  45. package/docs/sections.json +258 -0
  46. package/package.json +48 -0
@@ -0,0 +1,121 @@
1
+ # expandSync()
2
+
3
+ *Expands macros in TypeScript code synchronously and returns the transformed output.*
4
+
5
+ ## Signature
6
+
7
+ ```typescript
8
+ function expandSync(
9
+ code: string,
10
+ filepath: string,
11
+ options?: ExpandOptions
12
+ ): ExpandResult
13
+ ```
14
+
15
+ ## Parameters
16
+
17
+ | `code`
18
+ | `string`
19
+ | TypeScript source code to transform
20
+
21
+ | `filepath`
22
+ | `string`
23
+ | File path (used for error reporting)
24
+
25
+ | `options`
26
+ | `ExpandOptions`
27
+ | Optional configuration
28
+
29
+ ## ExpandOptions
30
+
31
+ ```typescript
32
+ interface ExpandOptions {
33
+ // Keep @derive decorators in output (default: false)
34
+ keepDecorators?: boolean;
35
+ }
36
+ ```
37
+
38
+ ## ExpandResult
39
+
40
+ ```typescript
41
+ interface ExpandResult {
42
+ // Transformed TypeScript code
43
+ code: string;
44
+
45
+ // Generated type declarations (.d.ts content)
46
+ types?: string;
47
+
48
+ // Macro expansion metadata (JSON string)
49
+ metadata?: string;
50
+
51
+ // Warnings and errors from macro expansion
52
+ diagnostics: MacroDiagnostic[];
53
+
54
+ // Position mapping data for source maps
55
+ sourceMapping?: SourceMappingResult;
56
+ }
57
+ ```
58
+
59
+ ## MacroDiagnostic
60
+
61
+ ```typescript
62
+ interface MacroDiagnostic {
63
+ message: string;
64
+ severity: "error" | "warning" | "info";
65
+ span: {
66
+ start: number;
67
+ end: number;
68
+ };
69
+ }
70
+ ```
71
+
72
+ ## Example
73
+
74
+ ```typescript
75
+ import { expandSync } from "macroforge";
76
+
77
+ const sourceCode = \`
78
+ import { Debug } from "macroforge";
79
+
80
+ /** @derive(Debug) */
81
+ class User {
82
+ name: string;
83
+ age: number;
84
+
85
+ constructor(name: string, age: number) {
86
+ this.name = name;
87
+ this.age = age;
88
+ }
89
+ }
90
+ \`;
91
+
92
+ const result = expandSync(sourceCode, "user.ts");
93
+
94
+ console.log("Transformed code:");
95
+ console.log(result.code);
96
+
97
+ if (result.types) {
98
+ console.log("Type declarations:");
99
+ console.log(result.types);
100
+ }
101
+
102
+ if (result.diagnostics.length > 0) {
103
+ for (const diag of result.diagnostics) {
104
+ console.log(\`[\${diag.severity}] \${diag.message}\`);
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## Error Handling
110
+
111
+ Syntax errors and macro errors are returned in the `diagnostics` array, not thrown as exceptions:
112
+
113
+ ```typescript
114
+ const result = expandSync(invalidCode, "file.ts");
115
+
116
+ for (const diag of result.diagnostics) {
117
+ if (diag.severity === "error") {
118
+ console.error(\`Error at \${diag.span.start}: \${diag.message}\`);
119
+ }
120
+ }
121
+ ```
@@ -0,0 +1,106 @@
1
+ # NativePlugin
2
+
3
+ *A stateful plugin class with version-based caching, designed for integration with language servers and IDEs.*
4
+
5
+ ## Constructor
6
+
7
+ ```typescript
8
+ const plugin = new NativePlugin();
9
+ ```
10
+
11
+ ## Methods
12
+
13
+ ### processFile()
14
+
15
+ Process a file with version-based caching:
16
+
17
+ ```typescript
18
+ processFile(
19
+ filepath: string,
20
+ code: string,
21
+ options?: ProcessFileOptions
22
+ ): ExpandResult
23
+ ```
24
+
25
+ ```typescript
26
+ interface ProcessFileOptions {
27
+ // Cache key - if unchanged, returns cached result
28
+ version?: string;
29
+ }
30
+ ```
31
+
32
+ ### getMapper()
33
+
34
+ Get the position mapper for a previously processed file:
35
+
36
+ ```typescript
37
+ getMapper(filepath: string): NativeMapper | null
38
+ ```
39
+
40
+ ### mapDiagnostics()
41
+
42
+ Map diagnostics from expanded positions to original positions:
43
+
44
+ ```typescript
45
+ mapDiagnostics(
46
+ filepath: string,
47
+ diagnostics: JsDiagnostic[]
48
+ ): JsDiagnostic[]
49
+ ```
50
+
51
+ ### log() / setLogFile()
52
+
53
+ Logging utilities for debugging:
54
+
55
+ ```typescript
56
+ log(message: string): void
57
+ setLogFile(path: string): void
58
+ ```
59
+
60
+ ## Caching Behavior
61
+
62
+ The plugin caches expansion results by file path and version:
63
+
64
+ ```typescript
65
+ const plugin = new NativePlugin();
66
+
67
+ // First call - performs expansion
68
+ const result1 = plugin.processFile("user.ts", code, { version: "1" });
69
+
70
+ // Same version - returns cached result instantly
71
+ const result2 = plugin.processFile("user.ts", code, { version: "1" });
72
+
73
+ // Different version - re-expands
74
+ const result3 = plugin.processFile("user.ts", newCode, { version: "2" });
75
+ ```
76
+
77
+ ## Example: Language Server Integration
78
+
79
+ ```typescript
80
+ import { NativePlugin } from "macroforge";
81
+
82
+ class MacroforgeLanguageService {
83
+ private plugin = new NativePlugin();
84
+
85
+ processDocument(uri: string, content: string, version: number) {
86
+ // Process with version-based caching
87
+ const result = this.plugin.processFile(uri, content, {
88
+ version: String(version)
89
+ });
90
+
91
+ // Get mapper for position translation
92
+ const mapper = this.plugin.getMapper(uri);
93
+
94
+ return { result, mapper };
95
+ }
96
+
97
+ getSemanticDiagnostics(uri: string, diagnostics: Diagnostic[]) {
98
+ // Map positions from expanded to original
99
+ return this.plugin.mapDiagnostics(uri, diagnostics);
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## Thread Safety
105
+
106
+ 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.
@@ -0,0 +1,127 @@
1
+ # PositionMapper
2
+
3
+ *Maps positions between original source code and macro-expanded code. Essential for accurate error reporting and debugging.*
4
+
5
+ ## Getting a Mapper
6
+
7
+ ```typescript
8
+ import { NativePlugin, PositionMapper } from "macroforge";
9
+
10
+ const plugin = new NativePlugin();
11
+ const result = plugin.processFile("user.ts", code, { version: "1" });
12
+
13
+ // Get the mapper for this file
14
+ const mapper = plugin.getMapper("user.ts");
15
+ if (mapper) {
16
+ // Use the mapper...
17
+ }
18
+ ```
19
+
20
+ ## Methods
21
+
22
+ ### isEmpty()
23
+
24
+ Check if the mapper has any mappings:
25
+
26
+ ```typescript
27
+ isEmpty(): boolean
28
+ ```
29
+
30
+ ### originalToExpanded()
31
+
32
+ Map a position from original to expanded code:
33
+
34
+ ```typescript
35
+ originalToExpanded(pos: number): number
36
+ ```
37
+
38
+ ### expandedToOriginal()
39
+
40
+ Map a position from expanded to original code:
41
+
42
+ ```typescript
43
+ expandedToOriginal(pos: number): number | null
44
+ ```
45
+
46
+ Returns `null` if the position is in generated code.
47
+
48
+ ### isInGenerated()
49
+
50
+ Check if a position is in macro-generated code:
51
+
52
+ ```typescript
53
+ isInGenerated(pos: number): boolean
54
+ ```
55
+
56
+ ### generatedBy()
57
+
58
+ Get the name of the macro that generated code at a position:
59
+
60
+ ```typescript
61
+ generatedBy(pos: number): string | null
62
+ ```
63
+
64
+ ### mapSpanToOriginal()
65
+
66
+ Map a span (range) from expanded to original code:
67
+
68
+ ```typescript
69
+ mapSpanToOriginal(start: number, length: number): SpanResult | null
70
+
71
+ interface SpanResult {
72
+ start: number;
73
+ length: number;
74
+ }
75
+ ```
76
+
77
+ ### mapSpanToExpanded()
78
+
79
+ Map a span from original to expanded code:
80
+
81
+ ```typescript
82
+ mapSpanToExpanded(start: number, length: number): SpanResult
83
+ ```
84
+
85
+ ## Example: Error Position Mapping
86
+
87
+ ```typescript
88
+ import { NativePlugin } from "macroforge";
89
+
90
+ const plugin = new NativePlugin();
91
+
92
+ function mapError(filepath: string, expandedPos: number, message: string) {
93
+ const mapper = plugin.getMapper(filepath);
94
+ if (!mapper) return null;
95
+
96
+ // Check if the error is in generated code
97
+ if (mapper.isInGenerated(expandedPos)) {
98
+ const macroName = mapper.generatedBy(expandedPos);
99
+ return {
100
+ message: \`Error in code generated by @derive(\${macroName}): \${message}\`,
101
+ // Find the @derive decorator position
102
+ position: findDecoratorPosition(filepath)
103
+ };
104
+ }
105
+
106
+ // Map to original position
107
+ const originalPos = mapper.expandedToOriginal(expandedPos);
108
+ if (originalPos !== null) {
109
+ return {
110
+ message,
111
+ position: originalPos
112
+ };
113
+ }
114
+
115
+ return null;
116
+ }
117
+ ```
118
+
119
+ ## Performance
120
+
121
+ Position mapping uses binary search with O(log n) complexity:
122
+
123
+ - Fast lookups even for large files
124
+
125
+ - Minimal memory overhead
126
+
127
+ - Thread-safe access
@@ -0,0 +1,98 @@
1
+ # transformSync()
2
+
3
+ *A lower-level transform function that returns additional metadata alongside the transformed code.*
4
+
5
+ ## Signature
6
+
7
+ ```typescript
8
+ function transformSync(
9
+ code: string,
10
+ filepath: string
11
+ ): TransformResult
12
+ ```
13
+
14
+ ## Parameters
15
+
16
+ | `code`
17
+ | `string`
18
+ | TypeScript source code to transform
19
+
20
+ | `filepath`
21
+ | `string`
22
+ | File path (used for error reporting)
23
+
24
+ ## TransformResult
25
+
26
+ ```typescript
27
+ interface TransformResult {
28
+ // Transformed TypeScript code
29
+ code: string;
30
+
31
+ // Source map (JSON string, not yet implemented)
32
+ map?: string;
33
+
34
+ // Generated type declarations
35
+ types?: string;
36
+
37
+ // Macro expansion metadata
38
+ metadata?: string;
39
+ }
40
+ ```
41
+
42
+ ## Comparison with expandSync()
43
+
44
+ | Options
45
+ | Yes
46
+ | No
47
+
48
+ | Diagnostics
49
+ | Yes
50
+ | No
51
+
52
+ | Source Mapping
53
+ | Yes
54
+ | Limited
55
+
56
+ | Use Case
57
+ | General purpose
58
+ | Build tools
59
+
60
+ ## Example
61
+
62
+ ```typescript
63
+ import { transformSync } from "macroforge";
64
+
65
+ const sourceCode = \`
66
+ /** @derive(Debug) */
67
+ class User {
68
+ name: string;
69
+ }
70
+ \`;
71
+
72
+ const result = transformSync(sourceCode, "user.ts");
73
+
74
+ console.log(result.code);
75
+
76
+ if (result.types) {
77
+ // Write to .d.ts file
78
+ fs.writeFileSync("user.d.ts", result.types);
79
+ }
80
+
81
+ if (result.metadata) {
82
+ // Parse and use metadata
83
+ const meta = JSON.parse(result.metadata);
84
+ console.log("Macros expanded:", meta);
85
+ }
86
+ ```
87
+
88
+ ## When to Use
89
+
90
+ Use `transformSync` when:
91
+
92
+ - Building custom integrations
93
+
94
+ - You need raw output without diagnostics
95
+
96
+ - You're implementing a build tool plugin
97
+
98
+ Use `expandSync` for most other use cases, as it provides better error handling.
@@ -0,0 +1,180 @@
1
+ # Clone
2
+
3
+ *The `Clone` macro generates a `clone()` method that creates a copy of the object.*
4
+
5
+ ## Basic Usage
6
+
7
+ ```typescript
8
+ /** @derive(Clone) */
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
+ }
18
+
19
+ const original = new Point(10, 20);
20
+ const copy = original.clone();
21
+
22
+ console.log(copy.x, copy.y); // 10, 20
23
+ console.log(original === copy); // false (different instances)
24
+ ```
25
+
26
+ ## Generated Code
27
+
28
+ ```typescript
29
+ clone(): Point {
30
+ return new Point(this.x, this.y);
31
+ }
32
+ ```
33
+
34
+ ## How It Works
35
+
36
+ The Clone macro:
37
+
38
+ 1. Creates a new instance of the class
39
+
40
+ 2. Passes all field values to the constructor
41
+
42
+ 3. Returns the new instance
43
+
44
+ This creates a **shallow clone** - primitive values are copied, but object references remain the same.
45
+
46
+ ## With Nested Objects
47
+
48
+ ```typescript
49
+ /** @derive(Clone) */
50
+ class User {
51
+ name: string;
52
+ address: { city: string; zip: string };
53
+
54
+ constructor(name: string, address: { city: string; zip: string }) {
55
+ this.name = name;
56
+ this.address = address;
57
+ }
58
+ }
59
+
60
+ const original = new User("Alice", { city: "NYC", zip: "10001" });
61
+ const copy = original.clone();
62
+
63
+ // The address object is the same reference
64
+ console.log(original.address === copy.address); // true
65
+
66
+ // Modifying the copy's address affects the original
67
+ copy.address.city = "LA";
68
+ console.log(original.address.city); // "LA"
69
+ ```
70
+
71
+ For deep cloning of nested objects, you would need to implement custom clone methods or use a deep clone utility.
72
+
73
+ ## Combining with Eq
74
+
75
+ Clone works well with Eq for creating independent copies that compare as equal:
76
+
77
+ ```typescript
78
+ /** @derive(Clone, Eq) */
79
+ class Point {
80
+ x: number;
81
+ y: number;
82
+
83
+ constructor(x: number, y: number) {
84
+ this.x = x;
85
+ this.y = y;
86
+ }
87
+ }
88
+
89
+ const original = new Point(10, 20);
90
+ const copy = original.clone();
91
+
92
+ console.log(original === copy); // false (different instances)
93
+ console.log(original.equals(copy)); // true (same values)
94
+ ```
95
+
96
+ ## Interface Support
97
+
98
+ Clone also works with interfaces. For interfaces, a namespace is generated with a `clone` function:
99
+
100
+ ```typescript
101
+ /** @derive(Clone) */
102
+ interface Point {
103
+ x: number;
104
+ y: number;
105
+ }
106
+
107
+ // Generated:
108
+ // export namespace Point {
109
+ // export function clone(self: Point): Point {
110
+ // return { x: self.x, y: self.y };
111
+ // }
112
+ // }
113
+
114
+ const original: Point = { x: 10, y: 20 };
115
+ const copy = Point.clone(original);
116
+
117
+ console.log(copy.x, copy.y); // 10, 20
118
+ console.log(original === copy); // false (different objects)
119
+ ```
120
+
121
+ ## Enum Support
122
+
123
+ Clone also works with enums. For enums, the clone function simply returns the value as-is, since enum values are primitives and don't need cloning:
124
+
125
+ ```typescript
126
+ /** @derive(Clone) */
127
+ enum Status {
128
+ Active = "active",
129
+ Inactive = "inactive",
130
+ }
131
+
132
+ // Generated:
133
+ // export namespace Status {
134
+ // export function clone(value: Status): Status {
135
+ // return value;
136
+ // }
137
+ // }
138
+
139
+ const original = Status.Active;
140
+ const copy = Status.clone(original);
141
+
142
+ console.log(copy); // "active"
143
+ console.log(original === copy); // true (same primitive value)
144
+ ```
145
+
146
+ ## Type Alias Support
147
+
148
+ Clone works with type aliases. For object types, a shallow copy is created using spread:
149
+
150
+ ```typescript
151
+ /** @derive(Clone) */
152
+ type Point = {
153
+ x: number;
154
+ y: number;
155
+ };
156
+
157
+ // Generated:
158
+ // export namespace Point {
159
+ // export function clone(value: Point): Point {
160
+ // return { ...value };
161
+ // }
162
+ // }
163
+
164
+ const original: Point = { x: 10, y: 20 };
165
+ const copy = Point.clone(original);
166
+
167
+ console.log(copy.x, copy.y); // 10, 20
168
+ console.log(original === copy); // false (different objects)
169
+ ```
170
+
171
+ For union types, the value is returned as-is (unions of primitives don't need cloning):
172
+
173
+ ```typescript
174
+ /** @derive(Clone) */
175
+ type ApiStatus = "loading" | "success" | "error";
176
+
177
+ const status: ApiStatus = "success";
178
+ const copy = ApiStatus.clone(status);
179
+ console.log(copy); // "success"
180
+ ```