@macroforge/mcp-server 0.1.65 → 0.1.72
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 +7 -4
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/tools/docs-loader.d.ts.map +1 -1
- package/dist/tools/docs-loader.js +1 -1
- package/dist/tools/docs-loader.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +84 -85
- package/dist/tools/index.js.map +1 -1
- package/docs/BOOK.md +8 -33
- package/docs/api/api-overview.md +4 -4
- package/docs/api/expand-sync.md +3 -2
- package/docs/api/native-plugin.md +5 -2
- package/docs/api/position-mapper.md +7 -4
- package/docs/api/transform-sync.md +7 -5
- package/docs/builtin-macros/deserialize/all-options.md +7 -21
- package/docs/builtin-macros/deserialize/combining-with-serialize.md +7 -5
- package/docs/builtin-macros/deserialize/enum-support.md +8 -6
- package/docs/builtin-macros/deserialize/error-handling.md +10 -9
- package/docs/builtin-macros/deserialize/interface-support.md +9 -4
- package/docs/builtin-macros/deserialize/runtime-validation.md +10 -21
- package/docs/builtin-macros/deserialize/serde-options.md +19 -31
- package/docs/builtin-macros/deserialize/type-alias-support.md +7 -6
- package/docs/builtin-macros/macros-overview/detailed-documentation.md +9 -9
- package/docs/builtin-macros/macros-overview/enum-support.md +3 -2
- package/docs/builtin-macros/macros-overview/interface-support.md +3 -2
- package/docs/builtin-macros/macros-overview/overview.md +13 -12
- package/docs/builtin-macros/macros-overview/type-alias-support.md +3 -2
- package/docs/builtin-macros/macros-overview.md +27 -23
- package/docs/builtin-macros/partial-eq/example.md +188 -232
- package/docs/builtin-macros/partial-eq/overview.md +18 -18
- package/docs/builtin-macros/serialize/example.md +11 -3
- package/docs/builtin-macros/serialize/overview.md +12 -11
- package/docs/builtin-macros/serialize/type-specific-serialization.md +12 -12
- package/docs/concepts/architecture.md +23 -22
- package/docs/concepts/derive-system/built-in-vs-custom-macros.md +4 -3
- package/docs/concepts/derive-system/overview.md +27 -24
- package/docs/concepts/derive-system.md +31 -27
- package/docs/concepts/how-macros-work.md +23 -21
- package/docs/custom-macros/custom-overview.md +9 -8
- package/docs/custom-macros/rust-setup.md +11 -10
- package/docs/custom-macros/ts-macro-derive/accessing-field-data.md +2 -1
- package/docs/custom-macros/ts-macro-derive/adding-imports.md +2 -1
- package/docs/custom-macros/ts-macro-derive/attribute-options.md +1 -1
- package/docs/custom-macros/ts-macro-derive/complete-example.md +1 -1
- package/docs/custom-macros/ts-macro-derive/deriveinput-structure.md +1 -1
- package/docs/custom-macros/ts-macro-derive/function-signature.md +1 -1
- package/docs/custom-macros/ts-macro-derive/overview.md +3 -2
- package/docs/custom-macros/ts-macro-derive/parsing-input.md +1 -1
- package/docs/custom-macros/ts-macro-derive/returning-errors.md +1 -1
- package/docs/custom-macros/ts-macro-derive.md +7 -4
- package/docs/custom-macros/ts-quote/backtick-template-literals.md +5 -3
- package/docs/custom-macros/ts-quote/comments-and.md +3 -2
- package/docs/custom-macros/ts-quote/complete-example-json-derive-macro.md +12 -11
- package/docs/custom-macros/ts-quote/conditionals-ifif.md +1 -1
- package/docs/custom-macros/ts-quote/identifier-concatenation-content.md +5 -3
- package/docs/custom-macros/ts-quote/interpolation-expr.md +18 -11
- package/docs/custom-macros/ts-quote/iteration-for.md +1 -1
- package/docs/custom-macros/ts-quote/local-constants-let.md +1 -1
- package/docs/custom-macros/ts-quote/match-expressions-match.md +1 -1
- package/docs/custom-macros/ts-quote/overview.md +4 -2
- package/docs/custom-macros/ts-quote/pattern-matching-if-let.md +2 -2
- package/docs/custom-macros/ts-quote/pattern-matching-iflet.md +1 -1
- package/docs/custom-macros/ts-quote/quick-reference.md +24 -23
- package/docs/custom-macros/ts-quote/side-effects-do.md +6 -5
- package/docs/custom-macros/ts-quote/string-interpolation-text-expr.md +3 -3
- package/docs/custom-macros/ts-quote/string-interpolation-textexpr.md +1 -1
- package/docs/custom-macros/ts-quote/tsstream-injection-typescript.md +3 -2
- package/docs/custom-macros/ts-quote/while-loops-while.md +1 -1
- package/docs/custom-macros/ts-quote.md +30 -19
- package/docs/getting-started/first-macro.md +5 -4
- package/docs/getting-started/installation.md +20 -17
- package/docs/integration/cli.md +11 -5
- package/docs/integration/configuration.md +7 -9
- package/docs/integration/integration-overview.md +5 -5
- package/docs/integration/mcp-server.md +17 -8
- package/docs/integration/svelte-preprocessor.md +18 -14
- package/docs/integration/typescript-plugin.md +14 -12
- package/docs/integration/vite-plugin.md +13 -11
- package/docs/language-servers/ls-overview.md +18 -12
- package/docs/language-servers/svelte-ls.md +9 -11
- package/docs/language-servers/svelte.md +18 -17
- package/docs/language-servers/zed-extensions.md +14 -11
- package/docs/language-servers/zed.md +19 -13
- package/docs/roadmap/roadmap.md +8 -6
- package/package.json +5 -5
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# PartialEq
|
|
2
2
|
|
|
3
|
-
The `PartialEq` macro generates an `equals()` method for field-by-field
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The `PartialEq` macro generates an `equals()` method for field-by-field structural equality
|
|
4
|
+
comparison. This is analogous to Rust's `PartialEq` trait, enabling value-based equality semantics
|
|
5
|
+
instead of reference equality.
|
|
6
6
|
|
|
7
7
|
## Generated Output
|
|
8
8
|
|
|
9
|
-
| Type
|
|
10
|
-
|
|
11
|
-
| Class
|
|
12
|
-
| Enum
|
|
13
|
-
| Interface
|
|
14
|
-
| Type Alias | `equalsTypeName(a: TypeName, b: TypeName): boolean`
|
|
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 |
|
|
15
15
|
|
|
16
16
|
## Comparison Strategy
|
|
17
17
|
|
|
@@ -23,17 +23,17 @@ The generated equality check:
|
|
|
23
23
|
|
|
24
24
|
## Type-Specific Comparisons
|
|
25
25
|
|
|
26
|
-
| Type
|
|
27
|
-
|
|
28
|
-
| Primitives | Strict equality (`===`)
|
|
29
|
-
| Arrays
|
|
30
|
-
| `Date`
|
|
31
|
-
| `Map`
|
|
32
|
-
| `Set`
|
|
33
|
-
| Objects
|
|
26
|
+
| Type | Comparison Method |
|
|
27
|
+
| ---------- | ----------------------------------------- |
|
|
28
|
+
| Primitives | Strict equality (`===`) |
|
|
29
|
+
| Arrays | Length + element-by-element (recursive) |
|
|
30
|
+
| `Date` | `getTime()` comparison |
|
|
31
|
+
| `Map` | Size + entry-by-entry comparison |
|
|
32
|
+
| `Set` | Size + membership check |
|
|
33
|
+
| Objects | Calls `equals()` if available, else `===` |
|
|
34
34
|
|
|
35
35
|
## Field-Level Options
|
|
36
36
|
|
|
37
37
|
The `@partialEq` decorator supports:
|
|
38
38
|
|
|
39
|
-
- `skip` - Exclude the field from equality comparison
|
|
39
|
+
- `skip` - Exclude the field from equality comparison
|
|
@@ -38,7 +38,10 @@ class User {
|
|
|
38
38
|
@param value - The value to serialize
|
|
39
39
|
@param ctx - The serialization context */
|
|
40
40
|
|
|
41
|
-
static serializeWithContext(
|
|
41
|
+
static serializeWithContext(
|
|
42
|
+
value: User,
|
|
43
|
+
ctx: SerializeContext
|
|
44
|
+
): Record<string, unknown> {
|
|
42
45
|
return userSerializeWithContext(value, ctx);
|
|
43
46
|
}
|
|
44
47
|
}
|
|
@@ -53,6 +56,7 @@ class User {
|
|
|
53
56
|
} /** @internal Serializes with an existing context for nested/cyclic object graphs.
|
|
54
57
|
@param value - The value to serialize
|
|
55
58
|
@param ctx - The serialization context */
|
|
59
|
+
|
|
56
60
|
export function userSerializeWithContext(
|
|
57
61
|
value: User,
|
|
58
62
|
ctx: SerializeContext
|
|
@@ -98,7 +102,10 @@ class User {
|
|
|
98
102
|
@param value - The value to serialize
|
|
99
103
|
@param ctx - The serialization context */
|
|
100
104
|
|
|
101
|
-
static serializeWithContext(
|
|
105
|
+
static serializeWithContext(
|
|
106
|
+
value: User,
|
|
107
|
+
ctx: SerializeContext
|
|
108
|
+
): Record<string, unknown> {
|
|
102
109
|
return userSerializeWithContext(value, ctx);
|
|
103
110
|
}
|
|
104
111
|
}
|
|
@@ -113,6 +120,7 @@ class User {
|
|
|
113
120
|
} /** @internal Serializes with an existing context for nested/cyclic object graphs.
|
|
114
121
|
@param value - The value to serialize
|
|
115
122
|
@param ctx - The serialization context */
|
|
123
|
+
|
|
116
124
|
export function userSerializeWithContext(
|
|
117
125
|
value: User,
|
|
118
126
|
ctx: SerializeContext
|
|
@@ -136,4 +144,4 @@ export function userSerializeWithContext(
|
|
|
136
144
|
|
|
137
145
|
## Required Import
|
|
138
146
|
|
|
139
|
-
The generated code automatically imports `SerializeContext` from `macroforge/serde`.
|
|
147
|
+
The generated code automatically imports `SerializeContext` from `macroforge/serde`.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Serialize
|
|
2
2
|
|
|
3
|
-
The `Serialize` macro generates JSON serialization methods with **cycle detection**
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The `Serialize` macro generates JSON serialization methods with **cycle detection** and object
|
|
4
|
+
identity tracking. This enables serialization of complex object graphs including circular
|
|
5
|
+
references.
|
|
6
6
|
|
|
7
7
|
## Generated Methods
|
|
8
8
|
|
|
9
|
-
| Type
|
|
10
|
-
|
|
11
|
-
| Class
|
|
12
|
-
| Enum
|
|
13
|
-
| Interface
|
|
14
|
-
| Type Alias | `typeNameSerialize(value)`, etc.
|
|
9
|
+
| Type | Generated Code | Description |
|
|
10
|
+
| ---------- | ---------------------------------------------------------- | ------------------------------------------- |
|
|
11
|
+
| Class | `classNameSerialize(value)` + `static serialize(value)` | Standalone function + static wrapper method |
|
|
12
|
+
| Enum | `enumNameSerialize(value)`, `enumNameSerializeWithContext` | Standalone functions |
|
|
13
|
+
| Interface | `interfaceNameSerialize(value)`, etc. | Standalone functions |
|
|
14
|
+
| Type Alias | `typeNameSerialize(value)`, etc. | Standalone functions |
|
|
15
15
|
|
|
16
16
|
## Cycle Detection Protocol
|
|
17
17
|
|
|
@@ -22,11 +22,12 @@ The generated code handles circular references using `__id` and `__ref` markers:
|
|
|
22
22
|
"__type": "User",
|
|
23
23
|
"__id": 1,
|
|
24
24
|
"name": "Alice",
|
|
25
|
-
"friend": { "__ref": 2 }
|
|
25
|
+
"friend": { "__ref": 2 } // Reference to object with __id: 2
|
|
26
26
|
}
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
When an object is serialized:
|
|
30
|
+
|
|
30
31
|
1. Check if it's already been serialized (has an `__id`)
|
|
31
32
|
2. If so, return `{ "__ref": existingId }` instead
|
|
32
|
-
3. Otherwise, register the object and serialize its fields
|
|
33
|
+
3. Otherwise, register the object and serialize its fields
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
## Type-Specific Serialization
|
|
2
2
|
|
|
3
|
-
| Type
|
|
4
|
-
|
|
5
|
-
| Primitives | Direct value
|
|
6
|
-
| `Date`
|
|
7
|
-
| Arrays
|
|
8
|
-
| `Map<K,V>` | For primitive-like values, `Object.fromEntries(map.entries())`; for `Date`/`Date
|
|
9
|
-
| `Set<T>`
|
|
10
|
-
| Nullable
|
|
11
|
-
| Objects
|
|
3
|
+
| Type | Serialization Strategy |
|
|
4
|
+
| ---------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
5
|
+
| Primitives | Direct value |
|
|
6
|
+
| `Date` | `toISOString()` |
|
|
7
|
+
| Arrays | For primitive-like element types, pass through; for `Date`/`Date |
|
|
8
|
+
| `Map<K,V>` | For primitive-like values, `Object.fromEntries(map.entries())`; for `Date`/`Date |
|
|
9
|
+
| `Set<T>` | Convert to array; element handling matches `Array<T>` |
|
|
10
|
+
| Nullable | Include `null` explicitly; for primitive-like and `Date` unions the generator avoids runtime `SerializeWithContext` checks |
|
|
11
|
+
| Objects | Call `SerializeWithContext(ctx)` if available (to support user-defined implementations) |
|
|
12
12
|
|
|
13
|
-
Note: the generator specializes some code paths based on the declared TypeScript type to
|
|
14
|
-
|
|
13
|
+
Note: the generator specializes some code paths based on the declared TypeScript type to avoid
|
|
14
|
+
runtime feature detection on primitives and literal unions.
|
|
15
15
|
|
|
16
16
|
## Field-Level Options
|
|
17
17
|
|
|
@@ -19,4 +19,4 @@ The `@serde` decorator supports:
|
|
|
19
19
|
|
|
20
20
|
- `skip` / `skipSerializing` - Exclude field from serialization
|
|
21
21
|
- `rename = "jsonKey"` - Use different JSON property name
|
|
22
|
-
- `flatten` - Merge nested object's fields into parent
|
|
22
|
+
- `flatten` - Merge nested object's fields into parent
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
-
Macroforge is built as a native Node.js module using Rust and NAPI-RS. It leverages SWC for fast
|
|
3
|
+
Macroforge is built as a native Node.js module using Rust and NAPI-RS. It leverages SWC for fast
|
|
4
|
+
TypeScript parsing and code generation.
|
|
4
5
|
|
|
5
6
|
## Overview
|
|
6
7
|
|
|
@@ -26,41 +27,41 @@ TypeScript parsing & codegen
|
|
|
26
27
|
|
|
27
28
|
The foundation layer provides:
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
- Fast TypeScript/JavaScript parsing
|
|
31
|
+
- AST representation
|
|
32
|
+
- Code generation (AST → source code)
|
|
32
33
|
|
|
33
34
|
### macroforge\_ts\_syn
|
|
34
35
|
|
|
35
36
|
A Rust crate that provides:
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
- TypeScript-specific AST types
|
|
39
|
+
- Parsing utilities for macro input
|
|
40
|
+
- Derive input structures (class fields, decorators, etc.)
|
|
40
41
|
|
|
41
42
|
### macroforge\_ts\_quote
|
|
42
43
|
|
|
43
44
|
Template-based code generation similar to Rust's `quote!`:
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
- `ts_template!` - Generate TypeScript code from templates
|
|
47
|
+
- `body!` - Generate class body members
|
|
48
|
+
- Control flow: `{"{#for}"}`, `{"{#if}"}`, `{"{$let}"}`
|
|
48
49
|
|
|
49
50
|
### macroforge\_ts\_macros
|
|
50
51
|
|
|
51
52
|
The procedural macro attribute for defining derive macros:
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
- `#[ts_macro_derive(Name)]` attribute
|
|
55
|
+
- Automatic registration with the macro system
|
|
56
|
+
- Error handling and span tracking
|
|
56
57
|
|
|
57
58
|
### NAPI-RS Bindings
|
|
58
59
|
|
|
59
60
|
Bridges Rust and Node.js:
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
- Exposes `expandSync`, `transformSync`, etc.
|
|
63
|
+
- Provides the `NativePlugin` class for caching
|
|
64
|
+
- Handles data marshaling between Rust and JavaScript
|
|
64
65
|
|
|
65
66
|
## Data Flow
|
|
66
67
|
|
|
@@ -98,10 +99,10 @@ to JavaScript with source mapping
|
|
|
98
99
|
|
|
99
100
|
## Performance Characteristics
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
- **Thread-safe**: Each expansion runs in an isolated thread with a 32MB stack
|
|
103
|
+
- **Caching**: `NativePlugin` caches results by file version
|
|
104
|
+
- **Binary search**: Position mapping uses O(log n) lookups
|
|
105
|
+
- **Zero-copy**: SWC's arena allocator minimizes allocations
|
|
105
106
|
|
|
106
107
|
## Re-exported Crates
|
|
107
108
|
|
|
@@ -122,5 +123,5 @@ use macroforge_ts::swc_ecma_ast;
|
|
|
122
123
|
|
|
123
124
|
## Next Steps
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
- [Write custom macros](../../docs/custom-macros)
|
|
127
|
+
- [Explore the API reference](../../docs/api)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
## Built-in vs Custom Macros
|
|
2
2
|
|
|
3
|
-
Macroforge comes with built-in macros that work out of the box. You can also create custom macros in
|
|
3
|
+
Macroforge comes with built-in macros that work out of the box. You can also create custom macros in
|
|
4
|
+
Rust and use them via the `import macro` statement.
|
|
4
5
|
|
|
5
6
|
| Type | Import Required | Examples |
|
|
6
7
|
| -------- | --------------- | ------------------------------------------------------------------------------- |
|
|
@@ -9,5 +10,5 @@ Macroforge comes with built-in macros that work out of the box. You can also cre
|
|
|
9
10
|
|
|
10
11
|
## Next Steps
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
- [Explore built-in macros](../../docs/builtin-macros)
|
|
14
|
+
- [Create custom macros](../../docs/custom-macros)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# The Derive System
|
|
2
2
|
|
|
3
|
-
The derive system is inspired by Rust's derive macros. It allows you to automatically implement
|
|
3
|
+
The derive system is inspired by Rust's derive macros. It allows you to automatically implement
|
|
4
|
+
common patterns by annotating your classes with `@derive`.
|
|
4
5
|
|
|
5
6
|
## Syntax Reference
|
|
6
7
|
|
|
7
|
-
Macroforge uses JSDoc comments for all macro annotations. This ensures compatibility with standard
|
|
8
|
+
Macroforge uses JSDoc comments for all macro annotations. This ensures compatibility with standard
|
|
9
|
+
TypeScript tooling.
|
|
8
10
|
|
|
9
11
|
### The @derive Statement
|
|
10
12
|
|
|
@@ -23,10 +25,10 @@ class MyClass {
|
|
|
23
25
|
|
|
24
26
|
Syntax rules:
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
- Must be inside a JSDoc comment (`/** */`)
|
|
29
|
+
- Must appear immediately before the class/interface declaration
|
|
30
|
+
- Multiple macros can be comma-separated: `@derive(A, B, C)`
|
|
31
|
+
- Multiple `@derive` statements can be stacked
|
|
30
32
|
|
|
31
33
|
Source
|
|
32
34
|
|
|
@@ -52,10 +54,10 @@ TypeScript
|
|
|
52
54
|
|
|
53
55
|
Syntax rules:
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
- Must be inside a JSDoc comment (`/** */`)
|
|
58
|
+
- Can appear anywhere in the file (typically at the top)
|
|
59
|
+
- Multiple macros can be imported: `import macro { A, B } from "pkg";`
|
|
60
|
+
- Multiple import statements can be used for different packages
|
|
59
61
|
|
|
60
62
|
TypeScript
|
|
61
63
|
|
|
@@ -72,7 +74,8 @@ class User {
|
|
|
72
74
|
|
|
73
75
|
Built-in macros
|
|
74
76
|
|
|
75
|
-
Built-in macros (Debug, Clone, Default, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize) do
|
|
77
|
+
Built-in macros (Debug, Clone, Default, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize) do
|
|
78
|
+
not require an import statement.
|
|
76
79
|
|
|
77
80
|
### Field Attributes
|
|
78
81
|
|
|
@@ -167,11 +170,11 @@ export function userSerializeWithContext(
|
|
|
167
170
|
|
|
168
171
|
Syntax rules:
|
|
169
172
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
- Must be inside a JSDoc comment immediately before the field
|
|
174
|
+
- Options use object literal syntax: `@attr({ key: value })`
|
|
175
|
+
- Boolean options: `@attr({ skip: true })`
|
|
176
|
+
- String options: `@attr({ rename: "newName" })`
|
|
177
|
+
- Multiple attributes can be on separate lines or combined
|
|
175
178
|
|
|
176
179
|
Common field attributes by macro:
|
|
177
180
|
|
|
@@ -185,16 +188,16 @@ Common field attributes by macro:
|
|
|
185
188
|
|
|
186
189
|
## How It Works
|
|
187
190
|
|
|
188
|
-
1.
|
|
189
|
-
2.
|
|
190
|
-
3.
|
|
191
|
-
4.
|
|
191
|
+
1. **Declaration**: You write `@derive(MacroName)` before a class
|
|
192
|
+
2. **Discovery**: Macroforge finds all derive decorators in your code
|
|
193
|
+
3. **Expansion**: Each named macro receives the class AST and generates code
|
|
194
|
+
4. **Injection**: Generated methods/properties are added to the class
|
|
192
195
|
|
|
193
196
|
## What Can Be Derived
|
|
194
197
|
|
|
195
198
|
The derive system works on:
|
|
196
199
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
- **Classes**: The primary target for derive macros
|
|
201
|
+
- **Interfaces**: Macros generate companion namespace functions
|
|
202
|
+
- **Enums**: Macros generate namespace functions for enum values
|
|
203
|
+
- **Type aliases**: Both object types and union types are supported
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# The Derive System
|
|
2
2
|
|
|
3
|
-
The derive system is inspired by Rust's derive macros. It allows you to automatically implement
|
|
3
|
+
The derive system is inspired by Rust's derive macros. It allows you to automatically implement
|
|
4
|
+
common patterns by annotating your classes with `@derive`.
|
|
4
5
|
|
|
5
6
|
## Syntax Reference
|
|
6
7
|
|
|
7
|
-
Macroforge uses JSDoc comments for all macro annotations. This ensures compatibility with standard
|
|
8
|
+
Macroforge uses JSDoc comments for all macro annotations. This ensures compatibility with standard
|
|
9
|
+
TypeScript tooling.
|
|
8
10
|
|
|
9
11
|
### The @derive Statement
|
|
10
12
|
|
|
@@ -23,10 +25,10 @@ class MyClass {
|
|
|
23
25
|
|
|
24
26
|
Syntax rules:
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
- Must be inside a JSDoc comment (`/** */`)
|
|
29
|
+
- Must appear immediately before the class/interface declaration
|
|
30
|
+
- Multiple macros can be comma-separated: `@derive(A, B, C)`
|
|
31
|
+
- Multiple `@derive` statements can be stacked
|
|
30
32
|
|
|
31
33
|
Source
|
|
32
34
|
|
|
@@ -52,10 +54,10 @@ TypeScript
|
|
|
52
54
|
|
|
53
55
|
Syntax rules:
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
- Must be inside a JSDoc comment (`/** */`)
|
|
58
|
+
- Can appear anywhere in the file (typically at the top)
|
|
59
|
+
- Multiple macros can be imported: `import macro { A, B } from "pkg";`
|
|
60
|
+
- Multiple import statements can be used for different packages
|
|
59
61
|
|
|
60
62
|
TypeScript
|
|
61
63
|
|
|
@@ -72,7 +74,8 @@ class User {
|
|
|
72
74
|
|
|
73
75
|
Built-in macros
|
|
74
76
|
|
|
75
|
-
Built-in macros (Debug, Clone, Default, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize) do
|
|
77
|
+
Built-in macros (Debug, Clone, Default, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize) do
|
|
78
|
+
not require an import statement.
|
|
76
79
|
|
|
77
80
|
### Field Attributes
|
|
78
81
|
|
|
@@ -167,11 +170,11 @@ export function userSerializeWithContext(
|
|
|
167
170
|
|
|
168
171
|
Syntax rules:
|
|
169
172
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
- Must be inside a JSDoc comment immediately before the field
|
|
174
|
+
- Options use object literal syntax: `@attr({ key: value })`
|
|
175
|
+
- Boolean options: `@attr({ skip: true })`
|
|
176
|
+
- String options: `@attr({ rename: "newName" })`
|
|
177
|
+
- Multiple attributes can be on separate lines or combined
|
|
175
178
|
|
|
176
179
|
Common field attributes by macro:
|
|
177
180
|
|
|
@@ -185,23 +188,24 @@ Common field attributes by macro:
|
|
|
185
188
|
|
|
186
189
|
## How It Works
|
|
187
190
|
|
|
188
|
-
1.
|
|
189
|
-
2.
|
|
190
|
-
3.
|
|
191
|
-
4.
|
|
191
|
+
1. **Declaration**: You write `@derive(MacroName)` before a class
|
|
192
|
+
2. **Discovery**: Macroforge finds all derive decorators in your code
|
|
193
|
+
3. **Expansion**: Each named macro receives the class AST and generates code
|
|
194
|
+
4. **Injection**: Generated methods/properties are added to the class
|
|
192
195
|
|
|
193
196
|
## What Can Be Derived
|
|
194
197
|
|
|
195
198
|
The derive system works on:
|
|
196
199
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
- **Classes**: The primary target for derive macros
|
|
201
|
+
- **Interfaces**: Macros generate companion namespace functions
|
|
202
|
+
- **Enums**: Macros generate namespace functions for enum values
|
|
203
|
+
- **Type aliases**: Both object types and union types are supported
|
|
201
204
|
|
|
202
205
|
## Built-in vs Custom Macros
|
|
203
206
|
|
|
204
|
-
Macroforge comes with built-in macros that work out of the box. You can also create custom macros in
|
|
207
|
+
Macroforge comes with built-in macros that work out of the box. You can also create custom macros in
|
|
208
|
+
Rust and use them via the `import macro` statement.
|
|
205
209
|
|
|
206
210
|
| Type | Import Required | Examples |
|
|
207
211
|
| -------- | --------------- | ------------------------------------------------------------------------------- |
|
|
@@ -210,5 +214,5 @@ Macroforge comes with built-in macros that work out of the box. You can also cre
|
|
|
210
214
|
|
|
211
215
|
## Next Steps
|
|
212
216
|
|
|
213
|
-
|
|
214
|
-
|
|
217
|
+
- [Explore built-in macros](../../docs/builtin-macros)
|
|
218
|
+
- [Create custom macros](../../docs/custom-macros)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# How Macros Work
|
|
2
2
|
|
|
3
|
-
Macroforge performs compile-time code generation by parsing your TypeScript, expanding macros, and
|
|
3
|
+
Macroforge performs compile-time code generation by parsing your TypeScript, expanding macros, and
|
|
4
|
+
outputting transformed code. This happens before your code runs, resulting in zero runtime overhead.
|
|
4
5
|
|
|
5
6
|
## Compile-Time Expansion
|
|
6
7
|
|
|
7
8
|
Unlike runtime solutions that use reflection or proxies, Macroforge expands macros at compile time:
|
|
8
9
|
|
|
9
|
-
1.
|
|
10
|
-
2.
|
|
11
|
-
3.
|
|
12
|
-
4.
|
|
10
|
+
1. **Parse**: Your TypeScript code is parsed into an AST using SWC
|
|
11
|
+
2. **Find**: Macroforge finds `@derive` decorators and their associated items
|
|
12
|
+
3. **Expand**: Each macro generates new code based on the class structure
|
|
13
|
+
4. **Output**: The transformed TypeScript is written out, ready for normal compilation
|
|
13
14
|
|
|
14
15
|
Before (Your Code)
|
|
15
16
|
|
|
@@ -42,10 +43,10 @@ export function userToString(value: User): string {
|
|
|
42
43
|
|
|
43
44
|
Because code generation happens at compile time, there's no:
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
- Runtime reflection or metadata
|
|
47
|
+
- Proxy objects or wrappers
|
|
48
|
+
- Additional dependencies in your bundle
|
|
49
|
+
- Performance cost at runtime
|
|
49
50
|
|
|
50
51
|
The generated code is plain TypeScript that compiles to efficient JavaScript.
|
|
51
52
|
|
|
@@ -53,13 +54,14 @@ The generated code is plain TypeScript that compiles to efficient JavaScript.
|
|
|
53
54
|
|
|
54
55
|
Macroforge tracks the relationship between your source code and the expanded output. This means:
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
- Errors in generated code point back to your source
|
|
58
|
+
- Debugging works correctly
|
|
59
|
+
- IDE features like "go to definition" work as expected
|
|
59
60
|
|
|
60
61
|
Error positioning
|
|
61
62
|
|
|
62
|
-
The TypeScript plugin uses source mapping to show errors at the `@derive` decorator position, not in
|
|
63
|
+
The TypeScript plugin uses source mapping to show errors at the `@derive` decorator position, not in
|
|
64
|
+
the generated code.
|
|
63
65
|
|
|
64
66
|
## Execution Flow
|
|
65
67
|
|
|
@@ -91,19 +93,19 @@ Macroforge integrates at two key points:
|
|
|
91
93
|
|
|
92
94
|
The TypeScript plugin intercepts language server calls to provide:
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
- Diagnostics that reference your source, not expanded code
|
|
97
|
+
- Completions for generated methods
|
|
98
|
+
- Hover information showing what macros generate
|
|
97
99
|
|
|
98
100
|
### Build (Vite Plugin)
|
|
99
101
|
|
|
100
102
|
The Vite plugin runs macro expansion during the build process:
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
- Transforms files before they reach the TypeScript compiler
|
|
105
|
+
- Generates type declaration files (.d.ts)
|
|
106
|
+
- Produces metadata for debugging
|
|
105
107
|
|
|
106
108
|
## Next Steps
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
- [Learn about the derive system](../docs/concepts/derive-system)
|
|
111
|
+
- [Explore the architecture](../docs/concepts/architecture)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# Custom Macros
|
|
2
2
|
|
|
3
|
-
Macroforge allows you to create custom derive macros in Rust. Your macros have full access to the
|
|
3
|
+
Macroforge allows you to create custom derive macros in Rust. Your macros have full access to the
|
|
4
|
+
class AST and can generate any TypeScript code.
|
|
4
5
|
|
|
5
6
|
## Overview
|
|
6
7
|
|
|
7
8
|
Custom macros are written in Rust and compiled to native Node.js addons. The process involves:
|
|
8
9
|
|
|
9
|
-
1.
|
|
10
|
-
2.
|
|
11
|
-
3.
|
|
12
|
-
4.
|
|
10
|
+
1. Creating a Rust crate with NAPI bindings
|
|
11
|
+
2. Defining macro functions with `#[ts_macro_derive]`
|
|
12
|
+
3. Using `macroforge_ts_quote` to generate TypeScript code
|
|
13
|
+
4. Building and publishing as an npm package
|
|
13
14
|
|
|
14
15
|
## Quick Example
|
|
15
16
|
|
|
@@ -78,6 +79,6 @@ The `import macro` comment tells Macroforge which package provides the macro.
|
|
|
78
79
|
|
|
79
80
|
Follow these guides to create your own macros:
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
- [Set up a Rust macro crate](../docs/custom-macros/rust-setup)
|
|
83
|
+
- [Learn the #\[ts\_macro\_derive\] attribute](../docs/custom-macros/ts-macro-derive)
|
|
84
|
+
- [Learn the template syntax](../docs/custom-macros/ts-quote)
|