typespec-rust-emitter 0.12.0 → 0.13.1
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/AGENTS.md +82 -80
- package/CHANGELOG.md +24 -0
- package/dist/src/decorators/cache_control.d.ts +6 -0
- package/dist/src/decorators/cache_control.js +9 -0
- package/dist/src/decorators/cache_control.js.map +1 -0
- package/dist/src/decorators/etag_cache.d.ts +6 -0
- package/dist/src/decorators/etag_cache.js +9 -0
- package/dist/src/decorators/etag_cache.js.map +1 -0
- package/dist/src/decorators/index.d.ts +6 -0
- package/dist/src/decorators/index.js +7 -0
- package/dist/src/decorators/index.js.map +1 -0
- package/dist/src/decorators/rust_attr.d.ts +3 -0
- package/dist/src/decorators/rust_attr.js +45 -0
- package/dist/src/decorators/rust_attr.js.map +1 -0
- package/dist/src/decorators/rust_derive.d.ts +3 -0
- package/dist/src/decorators/rust_derive.js +39 -0
- package/dist/src/decorators/rust_derive.js.map +1 -0
- package/dist/src/decorators/rust_impl.d.ts +2 -0
- package/dist/src/decorators/rust_impl.js +19 -0
- package/dist/src/decorators/rust_impl.js.map +1 -0
- package/dist/src/decorators/rust_self.d.ts +3 -0
- package/dist/src/decorators/rust_self.js +35 -0
- package/dist/src/decorators/rust_self.js.map +1 -0
- package/dist/src/emitter.d.ts +2 -11
- package/dist/src/emitter.js +7 -1282
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/formatter/index.d.ts +2 -0
- package/dist/src/formatter/index.js +3 -0
- package/dist/src/formatter/index.js.map +1 -0
- package/dist/src/formatter/mappings.d.ts +4 -0
- package/dist/src/formatter/mappings.js +68 -0
- package/dist/src/formatter/mappings.js.map +1 -0
- package/dist/src/formatter/strings.d.ts +4 -0
- package/dist/src/formatter/strings.js +32 -0
- package/dist/src/formatter/strings.js.map +1 -0
- package/dist/src/generator/etag_router.d.ts +28 -0
- package/dist/src/generator/etag_router.js +76 -0
- package/dist/src/generator/etag_router.js.map +1 -0
- package/dist/src/generator/index.d.ts +5 -0
- package/dist/src/generator/index.js +6 -0
- package/dist/src/generator/index.js.map +1 -0
- package/dist/src/generator/response_enums.d.ts +6 -0
- package/dist/src/generator/response_enums.js +58 -0
- package/dist/src/generator/response_enums.js.map +1 -0
- package/dist/src/generator/router.d.ts +7 -0
- package/dist/src/generator/router.js +231 -0
- package/dist/src/generator/router.js.map +1 -0
- package/dist/src/generator/server_trait.d.ts +6 -0
- package/dist/src/generator/server_trait.js +97 -0
- package/dist/src/generator/server_trait.js.map +1 -0
- package/dist/src/generator/types_file.d.ts +11 -0
- package/dist/src/generator/types_file.js +209 -0
- package/dist/src/generator/types_file.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.js +1 -1
- package/dist/src/lib.js.map +1 -1
- package/dist/src/models/index.d.ts +2 -0
- package/dist/src/models/index.js +3 -0
- package/dist/src/models/index.js.map +1 -0
- package/dist/src/models/keys.d.ts +6 -0
- package/dist/src/models/keys.js +8 -0
- package/dist/src/models/keys.js.map +1 -0
- package/dist/src/models/types.d.ts +45 -0
- package/dist/src/models/types.js +2 -0
- package/dist/src/models/types.js.map +1 -0
- package/dist/src/parser/decorators.d.ts +18 -0
- package/dist/src/parser/decorators.js +28 -0
- package/dist/src/parser/decorators.js.map +1 -0
- package/dist/src/parser/index.d.ts +6 -0
- package/dist/src/parser/index.js +7 -0
- package/dist/src/parser/index.js.map +1 -0
- package/dist/src/parser/operations.d.ts +13 -0
- package/dist/src/parser/operations.js +127 -0
- package/dist/src/parser/operations.js.map +1 -0
- package/dist/src/parser/parameters.d.ts +5 -0
- package/dist/src/parser/parameters.js +98 -0
- package/dist/src/parser/parameters.js.map +1 -0
- package/dist/src/parser/responses.d.ts +13 -0
- package/dist/src/parser/responses.js +132 -0
- package/dist/src/parser/responses.js.map +1 -0
- package/dist/src/parser/routes.d.ts +4 -0
- package/dist/src/parser/routes.js +36 -0
- package/dist/src/parser/routes.js.map +1 -0
- package/dist/src/parser/types.d.ts +9 -0
- package/dist/src/parser/types.js +157 -0
- package/dist/src/parser/types.js.map +1 -0
- package/dist/test/etag_cache.test.d.ts +1 -0
- package/dist/test/etag_cache.test.js +86 -0
- package/dist/test/etag_cache.test.js.map +1 -0
- package/dist/test/test-host.d.ts +11 -0
- package/dist/test/test-host.js +28 -0
- package/dist/test/test-host.js.map +1 -1
- package/example/main.tsp +30 -1
- package/example/output-rust/Cargo.lock +48 -0
- package/example/output-rust/Cargo.toml +1 -0
- package/example/output-rust/src/generated/server.rs +153 -12
- package/example/output-rust/src/generated/types.rs +6 -0
- package/example/output-rust/src/main.rs +65 -27
- package/justfile +31 -2
- package/package.json +1 -1
- package/scripts/update-golden.js +36 -0
- package/src/decorators/cache_control.ts +14 -0
- package/src/decorators/etag_cache.ts +14 -0
- package/src/decorators/index.ts +6 -0
- package/src/decorators/rust_attr.ts +61 -0
- package/src/decorators/rust_derive.ts +55 -0
- package/src/decorators/rust_impl.ts +29 -0
- package/src/decorators/rust_self.ts +42 -0
- package/src/emitter.ts +18 -1654
- package/src/formatter/index.ts +2 -0
- package/src/formatter/mappings.ts +70 -0
- package/src/formatter/strings.ts +33 -0
- package/src/generator/etag_router.ts +97 -0
- package/src/generator/index.ts +5 -0
- package/src/generator/response_enums.ts +76 -0
- package/src/generator/router.ts +284 -0
- package/src/generator/server_trait.ts +134 -0
- package/src/generator/types_file.ts +297 -0
- package/src/index.ts +3 -1
- package/src/lib.ts +1 -1
- package/src/lib.tsp +3 -1
- package/src/models/index.ts +2 -0
- package/src/models/keys.ts +7 -0
- package/src/models/types.ts +54 -0
- package/src/parser/decorators.ts +34 -0
- package/src/parser/index.ts +6 -0
- package/src/parser/operations.ts +158 -0
- package/src/parser/parameters.ts +117 -0
- package/src/parser/responses.ts +170 -0
- package/src/parser/routes.ts +47 -0
- package/src/parser/types.ts +215 -0
- package/test/etag_cache.test.ts +104 -0
- package/test/golden/etag_cache/server.rs +110 -0
- package/test/golden/etag_cache/spec.tsp +20 -0
- package/test/golden/etag_cache/types.rs +13 -0
- package/test/test-host.ts +43 -0
package/AGENTS.md
CHANGED
|
@@ -1,120 +1,122 @@
|
|
|
1
|
-
# TypeSpec Rust Emitter
|
|
1
|
+
# TypeSpec Rust Emitter: Project Governance & Guidelines
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This document serves as the authoritative guide for all contributors (human and AI) to the TypeSpec Rust Emitter project. It defines the architectural philosophy, development workflows, and quality standards required to maintain a high-quality, modular, and reliable emitter.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 1. Architecture Overview
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The emitter is built on a **Modular Pipeline** architecture. It transforms TypeSpec models and operations into idiomatic Rust code through a series of decoupled stages.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
### Core Modules
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
| Module | Responsibility |
|
|
14
|
+
| :-------------------- | :---------------------------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| **`src/parser/`** | The "Discovery" layer. Traverses the TypeSpec AST to extract structured data (routes, parameters, responses, types). |
|
|
16
|
+
| **`src/generator/`** | The "Writer" layer. Takes parsed data and produces Rust source code. No TypeSpec-specific traversal should happen here. |
|
|
17
|
+
| **`src/decorators/`** | Implementation of TypeSpec `extern dec` functions. They attach metadata (via Symbols) used by the parser. |
|
|
18
|
+
| **`src/models/`** | Shared TypeScript interfaces and constant keys (Symbols) used for metadata storage. |
|
|
19
|
+
| **`src/formatter/`** | Naming convention logic (PascalCase to snake_case) and Rust identifier sanitization. |
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
- If multiple interpretations exist, present them - don't pick silently.
|
|
17
|
-
- If a simpler approach exists, say so. Push back when warranted.
|
|
18
|
-
- If something is unclear, stop. Name what's confusing. Ask.
|
|
21
|
+
### Data Flow
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
1. **Emit Stage**: TypeSpec compiler calls `$onEmit`.
|
|
24
|
+
2. **Parsing Stage**: The `Parser` traverses the program, identifying namespaces, models, and operations. Metadata from decorators is retrieved.
|
|
25
|
+
3. **Generation Stage**: The `Generator` receives parsed metadata and emits strings for `types.rs` and `server.rs`.
|
|
26
|
+
4. **Output Stage**: Files are written to the output directory.
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
---
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
- No abstractions for single-use code.
|
|
26
|
-
- No "flexibility" or "configurability" that wasn't requested.
|
|
27
|
-
- No error handling for impossible scenarios.
|
|
28
|
-
- If you write 200 lines and it could be 50, rewrite it.
|
|
30
|
+
## 2. Onboarding & Workflow
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
### Prerequisites
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
- **Node.js**: v18+
|
|
35
|
+
- **Rust**: Latest stable/nightly (for example validation).
|
|
36
|
+
- **Just**: Command runner (`just`).
|
|
37
|
+
- **TypeSpec**: `@typespec/compiler`.
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
### Common Commands
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
```bash
|
|
42
|
+
# Build the TypeScript project
|
|
43
|
+
npm run build
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- Match existing style, even if you'd do it differently.
|
|
41
|
-
- If you notice unrelated dead code, mention it - don't delete it.
|
|
45
|
+
# Run TypeScript tests (including Golden File assertions)
|
|
46
|
+
just test
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
# Re-emit example code and run cargo check/clippy on it
|
|
49
|
+
just check-rust
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
# Run EVERYTHING (Use this before any PR)
|
|
52
|
+
just check-all
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
# Update golden files for a specific feature
|
|
55
|
+
just update-golden <feature_name>
|
|
56
|
+
```
|
|
49
57
|
|
|
50
|
-
|
|
58
|
+
---
|
|
51
59
|
|
|
52
|
-
|
|
60
|
+
## 3. Feature Contribution Pipeline
|
|
53
61
|
|
|
54
|
-
|
|
62
|
+
Every new feature must follow the **Standard Feature Lifecycle**:
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
1. **Define TypeSpec API**: Add necessary decorators or models to `src/lib.tsp`.
|
|
65
|
+
2. **Implement Decorator**: Add a handler in `src/decorators/` and export it via `src/index.ts`.
|
|
66
|
+
3. **Update Parser**: Enhance `src/parser/` to detect and extract the new metadata.
|
|
67
|
+
4. **Implement Generator**: Add logic in `src/generator/` to emit the corresponding Rust constructs (e.g., traits, attributes, or struct fields).
|
|
68
|
+
5. **Create Test & Example**:
|
|
69
|
+
- Add a unit test in `test/` using the `emit` helper.
|
|
70
|
+
- Update `example/main.tsp` to demonstrate the feature in a real-world context.
|
|
59
71
|
|
|
60
|
-
|
|
72
|
+
---
|
|
61
73
|
|
|
62
|
-
|
|
63
|
-
1. [Step] → verify: [check]
|
|
64
|
-
2. [Step] → verify: [check]
|
|
65
|
-
3. [Step] → verify: [check]
|
|
66
|
-
```
|
|
74
|
+
## 4. Testing & Validation Protocol
|
|
67
75
|
|
|
68
|
-
|
|
76
|
+
Quality is enforced through a strict multi-layered validation system.
|
|
69
77
|
|
|
70
|
-
|
|
78
|
+
### Mandatory Test Structure
|
|
71
79
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
npm run build && npm test
|
|
80
|
+
- **1 Dedicated Test**: Every feature must have exactly one test file in `test/` (e.g., `test/etag_cache.test.ts`).
|
|
81
|
+
- **1 Functional Example**: The feature must be used in `example/main.tsp`.
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
npm run lint
|
|
78
|
-
npm run format
|
|
83
|
+
### Golden File Testing
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
We use "Golden Files" to ensure deterministic output.
|
|
86
|
+
|
|
87
|
+
- Expected outputs are stored in `test/golden/<feature>/`.
|
|
88
|
+
- Use `compareWithGolden(emitted, "feature", "file.rs")` in your tests.
|
|
89
|
+
- If output changes are intentional, use `just update-golden <feature>` to refresh the baseline.
|
|
90
|
+
|
|
91
|
+
### Rust Integrity Check
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
All code generated in the `example/` directory must be valid Rust.
|
|
85
94
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
| `src/emitter.ts` | Main codegen (~1600 lines) |
|
|
89
|
-
| `src/lib.tsp` | Decorator declarations |
|
|
90
|
-
| `src/index.ts` | Exports |
|
|
91
|
-
| `test/hello.test.ts` | Unit tests |
|
|
92
|
-
| `example/lib/` | Demo TypeSpec specs |
|
|
93
|
-
| `example/output-rust/` | Generated Rust |
|
|
95
|
+
- **`just check-rust`** automatically runs `cargo check` and `cargo clippy` on the generated code.
|
|
96
|
+
- **Zero Warning Policy**: Code that generates warnings in clippy is considered a failure.
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
---
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
please confirm there are no errors by writing a test for your task,
|
|
99
|
-
then running `npm test` and `just check-rust`.
|
|
100
|
-
After ensuring everything works as expected, run `npm run format` and `npm run lint`
|
|
101
|
-
and ensure there are no linting errors or warnings.
|
|
100
|
+
## 5. Coding Standards & Maintenance
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
write the changelog of what you did,
|
|
105
|
-
then run `just publish` to publish the new version to the npm registry.
|
|
102
|
+
### Rust Best Practices
|
|
106
103
|
|
|
107
|
-
|
|
104
|
+
- **Idiomatic Code**: Use standard Rust patterns (e.g., `Result` for errors, `Option` for nullables).
|
|
105
|
+
- **Pluggability**: Prefer Traits over hardcoded implementations (see `EtagCache` trait).
|
|
106
|
+
- **Documentation**: Generated code should include `///` doc comments derived from TypeSpec `@doc` decorators.
|
|
108
107
|
|
|
109
|
-
|
|
110
|
-
and `git push --tags` to push the tags to the remote.
|
|
108
|
+
### Maintenance Guidelines
|
|
111
109
|
|
|
112
|
-
|
|
110
|
+
- **Surgical Changes**: Only modify the files directly related to your task. Avoid "cleaning up" adjacent files.
|
|
111
|
+
- **Backward Compatibility**: Ensure that new features do not break existing Rust compilation in the example project.
|
|
112
|
+
- **Dependencies**: New Rust dependencies in generated code must be added to `example/output-rust/Cargo.toml`.
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
---
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
2. Update `CHANGELOG.md` (include issue refs)
|
|
118
|
-
3. Run `just publish`
|
|
116
|
+
## 6. Release Process
|
|
119
117
|
|
|
120
|
-
|
|
118
|
+
1. **Version Bump**: Increment version in `package.json` (SemVer).
|
|
119
|
+
2. **Changelog**: Update `CHANGELOG.md` with a concise summary.
|
|
120
|
+
3. **Final Verification**: Run `just check-all`.
|
|
121
|
+
4. **Git commit**: Run `git commit -m "Your message"`, `git tag v<MAJOR>.<MINOR>.<PATCH>`, `git push && git push --tags`
|
|
122
|
+
5. **Publish**: (To be handled by repository owners) `just publish`.
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.13.1] - 2026-05-12
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **@etagCache with @useAuth**: Cached handlers now preserve auth claims and forward `cache` in the correct argument order.
|
|
13
|
+
- **Cached handler generation**: ETag-aware handlers now reuse the same extractor list as normal routes, which keeps path and auth extraction aligned.
|
|
14
|
+
|
|
15
|
+
## [0.13.0] - 2026-05-12
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **@cacheControl decorator**: New decorator to define `Cache-Control` headers for operations.
|
|
20
|
+
- Example: `@cacheControl("public, max-age=3600")` adds the corresponding header to the response.
|
|
21
|
+
- **Enhanced @etagCache decorator**: Refactored to support an optional `etagKey`.
|
|
22
|
+
- If provided, `etagKey` is used as the cache key base (e.g., `@etagCache("my-key")`).
|
|
23
|
+
- Otherwise, defaults to an operation-specific key based on path parameters.
|
|
24
|
+
- **Golden File Testing**: Introduced a robust testing framework using "Golden Files" to ensure deterministic output and easier verification of generator changes.
|
|
25
|
+
- **Modular Pipeline Architecture**: Major internal refactor decomposing the monolithic emitter into decoupled modules (`parser`, `generator`, `decorators`, `models`, `formatter`).
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **Clippy hygiene**: Fixed multiple clippy warnings in generated code, including `let_and_return`, `needless_borrow`, and `collapsible_if`.
|
|
30
|
+
- **Response Headers**: Fixed an issue where `ETag` headers from the cache were not being properly injected into the response on cache-miss (but valid content) paths.
|
|
31
|
+
|
|
8
32
|
## [0.12.0] - 2026-05-11
|
|
9
33
|
|
|
10
34
|
### Added
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DecoratorContext, Operation } from "@typespec/compiler";
|
|
2
|
+
/**
|
|
3
|
+
* @cacheControl decorator implementation.
|
|
4
|
+
* Stores the cache control value on the operation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function $cacheControl(context: DecoratorContext, target: Operation, value: string): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { cacheControlKey } from "../models/keys.js";
|
|
2
|
+
/**
|
|
3
|
+
* @cacheControl decorator implementation.
|
|
4
|
+
* Stores the cache control value on the operation.
|
|
5
|
+
*/
|
|
6
|
+
export function $cacheControl(context, target, value) {
|
|
7
|
+
context.program.stateMap(cacheControlKey).set(target, value);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=cache_control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache_control.js","sourceRoot":"","sources":["../../../src/decorators/cache_control.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAyB,EACzB,MAAiB,EACjB,KAAa;IAEb,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DecoratorContext, Operation } from "@typespec/compiler";
|
|
2
|
+
/**
|
|
3
|
+
* @etagCache decorator implementation.
|
|
4
|
+
* Stores the optional etagKey on the operation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function $etagCache(context: DecoratorContext, target: Operation, etagKey?: string): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { etagCacheKey } from "../models/keys.js";
|
|
2
|
+
/**
|
|
3
|
+
* @etagCache decorator implementation.
|
|
4
|
+
* Stores the optional etagKey on the operation.
|
|
5
|
+
*/
|
|
6
|
+
export function $etagCache(context, target, etagKey) {
|
|
7
|
+
context.program.stateMap(etagCacheKey).set(target, etagKey ?? true);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=etag_cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"etag_cache.js","sourceRoot":"","sources":["../../../src/decorators/etag_cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,OAAyB,EACzB,MAAiB,EACjB,OAAgB;IAEhB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getNamespaceFullName, } from "@typespec/compiler";
|
|
2
|
+
import { rustAttrKey } from "../models/keys.js";
|
|
3
|
+
export function $rustAttr(context, target, attr) {
|
|
4
|
+
if (target.kind !== "Model" &&
|
|
5
|
+
target.kind !== "Enum" &&
|
|
6
|
+
target.kind !== "ModelProperty") {
|
|
7
|
+
context.program.reportDiagnostic({
|
|
8
|
+
code: "rust-attr-invalid-target",
|
|
9
|
+
message: `@rustAttr can only be applied to models, enums, and model properties`,
|
|
10
|
+
severity: "error",
|
|
11
|
+
target: context.decoratorTarget,
|
|
12
|
+
});
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let ns;
|
|
16
|
+
if (target.kind === "Model") {
|
|
17
|
+
ns = target.namespace;
|
|
18
|
+
}
|
|
19
|
+
else if (target.kind === "Enum") {
|
|
20
|
+
ns = target.namespace;
|
|
21
|
+
}
|
|
22
|
+
else if (target.kind === "ModelProperty") {
|
|
23
|
+
ns = target.model?.namespace;
|
|
24
|
+
}
|
|
25
|
+
const nsFullName = ns ? getNamespaceFullName(ns) : "";
|
|
26
|
+
if (!nsFullName.startsWith("TypeSpec")) {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
const info = target[rustAttrKey];
|
|
29
|
+
if (info) {
|
|
30
|
+
if (!info.attrs.includes(attr)) {
|
|
31
|
+
info.attrs.push(attr);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
target[rustAttrKey] = { attrs: [attr] };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function $rustAttrs(context, target, ...attrs) {
|
|
41
|
+
for (const attr of attrs) {
|
|
42
|
+
$rustAttr(context, target, attr);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=rust_attr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust_attr.js","sourceRoot":"","sources":["../../../src/decorators/rust_attr.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,GAGrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,UAAU,SAAS,CACvB,OAAyB,EACzB,MAAY,EACZ,IAAY;IAEZ,IACE,MAAM,CAAC,IAAI,KAAK,OAAO;QACvB,MAAM,CAAC,IAAI,KAAK,MAAM;QACtB,MAAM,CAAC,IAAI,KAAK,eAAe,EAC/B,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC/B,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,sEAAsE;YAC/E,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,EAAyB,CAAC;IAC9B,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;IACxB,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAClC,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;IACxB,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QAC3C,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC;IAC/B,CAAC;IAED,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACvC,8DAA8D;QAC9D,MAAM,IAAI,GAAI,MAAc,CAAC,WAAW,CAA6B,CAAC;QACtE,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,8DAA8D;YAC7D,MAAc,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,OAAyB,EACzB,MAAY,EACZ,GAAG,KAAe;IAElB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getNamespaceFullName, } from "@typespec/compiler";
|
|
2
|
+
import { rustDeriveKey } from "../models/keys.js";
|
|
3
|
+
export function $rustDerive(context, target, derive) {
|
|
4
|
+
if (target.kind !== "Model" && target.kind !== "Enum") {
|
|
5
|
+
context.program.reportDiagnostic({
|
|
6
|
+
code: "rust-derive-invalid-target",
|
|
7
|
+
message: `@rustDerive can only be applied to models and enums`,
|
|
8
|
+
severity: "error",
|
|
9
|
+
target: context.decoratorTarget,
|
|
10
|
+
});
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const ns = target.kind === "Model"
|
|
14
|
+
? target.namespace
|
|
15
|
+
? getNamespaceFullName(target.namespace)
|
|
16
|
+
: ""
|
|
17
|
+
: target.namespace
|
|
18
|
+
? getNamespaceFullName(target.namespace)
|
|
19
|
+
: "";
|
|
20
|
+
if (!ns.startsWith("TypeSpec")) {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
const info = target[rustDeriveKey];
|
|
23
|
+
if (info) {
|
|
24
|
+
if (!info.derives.includes(derive)) {
|
|
25
|
+
info.derives.push(derive);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
target[rustDeriveKey] = { derives: [derive] };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function $rustDerives(context, target, ...derives) {
|
|
35
|
+
for (const derive of derives) {
|
|
36
|
+
$rustDerive(context, target, derive);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=rust_derive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust_derive.js","sourceRoot":"","sources":["../../../src/decorators/rust_derive.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,MAAM,UAAU,WAAW,CACzB,OAAyB,EACzB,MAAY,EACZ,MAAc;IAEd,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACtD,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC/B,IAAI,EAAE,4BAA4B;YAClC,OAAO,EAAE,qDAAqD;YAC9D,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GACN,MAAM,CAAC,IAAI,KAAK,OAAO;QACrB,CAAC,CAAC,MAAM,CAAC,SAAS;YAChB,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC;YACxC,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,MAAM,CAAC,SAAS;YAChB,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC;YACxC,CAAC,CAAC,EAAE,CAAC;IAEX,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,8DAA8D;QAC9D,MAAM,IAAI,GAAI,MAAc,CAAC,aAAa,CAA+B,CAAC;QAC1E,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,8DAA8D;YAC7D,MAAc,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;QACzD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAAyB,EACzB,MAAY,EACZ,GAAG,OAAiB;IAEpB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getNamespaceFullName, } from "@typespec/compiler";
|
|
2
|
+
import { rustImplKey } from "../models/keys.js";
|
|
3
|
+
export function $rustImpl(context, target, impl) {
|
|
4
|
+
if (target.kind !== "Model") {
|
|
5
|
+
context.program.reportDiagnostic({
|
|
6
|
+
code: "rust-impl-invalid-target",
|
|
7
|
+
message: `@rustImpl can only be applied to models`,
|
|
8
|
+
severity: "error",
|
|
9
|
+
target: context.decoratorTarget,
|
|
10
|
+
});
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const ns = target.namespace ? getNamespaceFullName(target.namespace) : "";
|
|
14
|
+
if (!ns.startsWith("TypeSpec")) {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
target[rustImplKey] = { impl: impl };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=rust_impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust_impl.js","sourceRoot":"","sources":["../../../src/decorators/rust_impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,UAAU,SAAS,CACvB,OAAyB,EACzB,MAAY,EACZ,IAAY;IAEZ,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC/B,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,yCAAyC;YAClD,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE1E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,8DAA8D;QAC7D,MAAc,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getNamespaceFullName, } from "@typespec/compiler";
|
|
2
|
+
import { rustSelfReceiverKey } from "../models/keys.js";
|
|
3
|
+
export function $rustMut(context, target) {
|
|
4
|
+
if (target.kind !== "Operation") {
|
|
5
|
+
context.program.reportDiagnostic({
|
|
6
|
+
code: "rust-mut-invalid-target",
|
|
7
|
+
message: `@rustMut can only be applied to operations`,
|
|
8
|
+
severity: "error",
|
|
9
|
+
target: context.decoratorTarget,
|
|
10
|
+
});
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const ns = target.namespace ? getNamespaceFullName(target.namespace) : "";
|
|
14
|
+
if (!ns.startsWith("TypeSpec")) {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
target[rustSelfReceiverKey] = "&mut self";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function $rustOwn(context, target) {
|
|
20
|
+
if (target.kind !== "Operation") {
|
|
21
|
+
context.program.reportDiagnostic({
|
|
22
|
+
code: "rust-own-invalid-target",
|
|
23
|
+
message: `@rustOwn can only be applied to operations`,
|
|
24
|
+
severity: "error",
|
|
25
|
+
target: context.decoratorTarget,
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const ns = target.namespace ? getNamespaceFullName(target.namespace) : "";
|
|
30
|
+
if (!ns.startsWith("TypeSpec")) {
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
target[rustSelfReceiverKey] = "self";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=rust_self.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust_self.js","sourceRoot":"","sources":["../../../src/decorators/rust_self.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,UAAU,QAAQ,CAAC,OAAyB,EAAE,MAAY;IAC9D,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC/B,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,4CAA4C;YACrD,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,8DAA8D;QAC7D,MAAc,CAAC,mBAAmB,CAAC,GAAG,WAAW,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAyB,EAAE,MAAY;IAC9D,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC/B,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,4CAA4C;YACrD,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,8DAA8D;QAC7D,MAAc,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC;IAChD,CAAC;AACH,CAAC"}
|
package/dist/src/emitter.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import { EmitContext
|
|
2
|
-
|
|
3
|
-
moduleName?: string;
|
|
4
|
-
}
|
|
5
|
-
export declare function $rustDerive(context: DecoratorContext, target: Type, derive: string): void;
|
|
6
|
-
export declare function $rustDerives(context: DecoratorContext, target: Type, ...derives: string[]): void;
|
|
7
|
-
export declare function $rustAttr(context: DecoratorContext, target: Type, attr: string): void;
|
|
8
|
-
export declare function $rustAttrs(context: DecoratorContext, target: Type, ...attrs: string[]): void;
|
|
9
|
-
export declare function $rustImpl(context: DecoratorContext, target: Type, impl: string): void;
|
|
10
|
-
export declare function $rustMut(context: DecoratorContext, target: Type): void;
|
|
11
|
-
export declare function $rustOwn(context: DecoratorContext, target: Type): void;
|
|
1
|
+
import { EmitContext } from "@typespec/compiler";
|
|
2
|
+
import { RustEmitterOptions } from "./models/types.js";
|
|
12
3
|
export declare function $onEmit(context: EmitContext<RustEmitterOptions>, _options?: RustEmitterOptions): Promise<void>;
|