typespec-rust-emitter 0.14.0 → 0.14.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/CHANGELOG.md +8 -0
- package/dist/src/generator/etag_router.d.ts +1 -0
- package/dist/src/generator/etag_router.js +22 -5
- package/dist/src/generator/etag_router.js.map +1 -1
- package/dist/src/generator/router.js +1 -0
- package/dist/src/generator/router.js.map +1 -1
- package/dist/test/etag_cache.test.js +48 -0
- package/dist/test/etag_cache.test.js.map +1 -1
- package/example/main.tsp +17 -0
- package/example/output-rust/src/generated/server.rs +74 -0
- package/example/output-rust/src/main.rs +27 -2
- package/package.json +1 -1
- package/src/generator/etag_router.ts +24 -4
- package/src/generator/router.ts +1 -0
- package/test/etag_cache.test.ts +65 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ 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.14.1] - 2026-05-12
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **ETag cache handler generation**: Cached handlers no longer emit invalid `mut service.method(...)` calls when combined with `@rustMut`.
|
|
13
|
+
- **ETag cache key templates**: Query placeholders in `@etagCache` now resolve to `params.<field>` values, including optional query parameters.
|
|
14
|
+
- **Example coverage**: The demo spec now includes a cached mutable route that exercises query interpolation and optional query values.
|
|
15
|
+
|
|
8
16
|
## [0.14.0] - 2026-05-12
|
|
9
17
|
|
|
10
18
|
### Changed
|
|
@@ -20,6 +20,7 @@ export declare function generateEtagCacheTrait(): string;
|
|
|
20
20
|
export declare function generateEtagHandler(opts: {
|
|
21
21
|
handlerFnName: string;
|
|
22
22
|
pathParams: ParameterInfo[];
|
|
23
|
+
queryParams?: ParameterInfo[];
|
|
23
24
|
extractorLines: string[];
|
|
24
25
|
serverArgsStr: string;
|
|
25
26
|
responseName: string;
|
|
@@ -25,17 +25,31 @@ function rustStringLiteral(value) {
|
|
|
25
25
|
.replace(/\t/g, "\\t")}"`;
|
|
26
26
|
}
|
|
27
27
|
function buildCacheKeyExpression(opts) {
|
|
28
|
-
const { handlerFnName, etagKey, pathParams } = opts;
|
|
28
|
+
const { handlerFnName, etagKey, pathParams, queryParams = [] } = opts;
|
|
29
29
|
const pathSuffix = pathParams.map((p) => `{${p.rustName}}`).join(":");
|
|
30
30
|
const paramNames = new Map();
|
|
31
31
|
for (const param of pathParams) {
|
|
32
32
|
paramNames.set(param.name, param.rustName);
|
|
33
33
|
paramNames.set(param.rustName, param.rustName);
|
|
34
34
|
}
|
|
35
|
+
const queryParamNames = new Map();
|
|
36
|
+
for (const param of queryParams) {
|
|
37
|
+
queryParamNames.set(param.name, param);
|
|
38
|
+
queryParamNames.set(param.rustName, param);
|
|
39
|
+
}
|
|
35
40
|
let template = etagKey ?? handlerFnName;
|
|
41
|
+
const formatArgs = [];
|
|
36
42
|
template = template.replace(/\{([^}]+)\}/g, (match, name) => {
|
|
37
43
|
const rustName = paramNames.get(name);
|
|
38
|
-
|
|
44
|
+
if (rustName) {
|
|
45
|
+
return `{${rustName}}`;
|
|
46
|
+
}
|
|
47
|
+
const queryParam = queryParamNames.get(name);
|
|
48
|
+
if (queryParam) {
|
|
49
|
+
formatArgs.push(`params.${queryParam.rustName}`);
|
|
50
|
+
return queryParam.rustType.startsWith("Option<") ? "{:?}" : "{}";
|
|
51
|
+
}
|
|
52
|
+
return match;
|
|
39
53
|
});
|
|
40
54
|
const hasExplicitPathParam = pathParams.some((param) => template.includes(`{${param.name}}`) ||
|
|
41
55
|
template.includes(`{${param.rustName}}`));
|
|
@@ -45,7 +59,8 @@ function buildCacheKeyExpression(opts) {
|
|
|
45
59
|
if (!template.includes("{")) {
|
|
46
60
|
return rustStringLiteral(template);
|
|
47
61
|
}
|
|
48
|
-
|
|
62
|
+
const args = formatArgs.length > 0 ? `, ${formatArgs.join(", ")}` : "";
|
|
63
|
+
return `format!(${rustStringLiteral(template)}${args})`;
|
|
49
64
|
}
|
|
50
65
|
/**
|
|
51
66
|
* generateEtagHandler
|
|
@@ -59,12 +74,14 @@ function buildCacheKeyExpression(opts) {
|
|
|
59
74
|
* @param responseName PascalCase name of the response enum, e.g. "ArticlesGetArticleResponse"
|
|
60
75
|
*/
|
|
61
76
|
export function generateEtagHandler(opts) {
|
|
62
|
-
const { handlerFnName, pathParams, extractorLines, serverArgsStr, etagKey, cacheControl, serviceBinding = "service", } = opts;
|
|
77
|
+
const { handlerFnName, pathParams, queryParams = [], extractorLines, serverArgsStr, etagKey, cacheControl, serviceBinding = "service", } = opts;
|
|
63
78
|
const effectiveCacheKey = buildCacheKeyExpression({
|
|
64
79
|
handlerFnName,
|
|
65
80
|
etagKey,
|
|
66
81
|
pathParams,
|
|
82
|
+
queryParams,
|
|
67
83
|
});
|
|
84
|
+
const serviceReceiver = serviceBinding.replace(/^mut\s+/, "");
|
|
68
85
|
const operationExtractors = extractorLines.length > 0 ? `${extractorLines.join("\n")}\n` : "";
|
|
69
86
|
const finalResponseLogic = ` match result {
|
|
70
87
|
Ok(response) => {
|
|
@@ -105,7 +122,7 @@ where
|
|
|
105
122
|
return res;
|
|
106
123
|
}
|
|
107
124
|
// Forward to business logic
|
|
108
|
-
let result = ${
|
|
125
|
+
let result = ${serviceReceiver}.${handlerFnName}(${serverArgsStr}).await;
|
|
109
126
|
${finalResponseLogic}
|
|
110
127
|
}`;
|
|
111
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"etag_router.js","sourceRoot":"","sources":["../../../src/generator/etag_router.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;CASR,CAAC;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,IAAI,KAAK;SACb,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;AAC9B,CAAC;AAED,SAAS,uBAAuB,CAAC,
|
|
1
|
+
{"version":3,"file":"etag_router.js","sourceRoot":"","sources":["../../../src/generator/etag_router.ts"],"names":[],"mappings":"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"}
|
|
@@ -82,6 +82,7 @@ export function generateRouter(program, namespaceGroups, anonymousEnums) {
|
|
|
82
82
|
const code = generateEtagHandler({
|
|
83
83
|
handlerFnName,
|
|
84
84
|
pathParams,
|
|
85
|
+
queryParams,
|
|
85
86
|
extractorLines,
|
|
86
87
|
serverArgsStr: cachedServerArgs.join(", "),
|
|
87
88
|
responseName: `${nsName}${toPascalCase(opInfo.name)}Response`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/generator/router.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,UAAU,cAAc,CAC5B,OAAgB,EAChB,eAAoE,EACpE,cAAwD;IAExD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,gBAAgB,GAAa,EAAE,CAAC;IACtC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACzC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CACnD,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,MAAM,MAAM,GAAG,YAAY,CACzB,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CACpD,CAAC;QAEF,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;YACvE,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC3C,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAExB,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9D,MAAM,WAAW,GAAG,aAAa,CAAC;YAClC,MAAM,WAAW,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACzC,MAAM,YAAY,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;YAEzC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;YAC1E,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAC9B,CAAC;YACF,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;YAC9C,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;YAC9B,MAAM,eAAe,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;YAE7C,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,MAAM,UAAU,GAAa,EAAE,CAAC;YAEhC,MAAM,cAAc,GAClB,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YAE3D,IAAI,WAAW,EAAE,CAAC;gBAChB,cAAc,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;gBACpE,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;YAED,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/D,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC5B,cAAc,CAAC,IAAI,CAAC,YAAY,UAAU,WAAW,SAAS,IAAI,CAAC,CAAC;gBACtE,CAAC;qBAAM,CAAC;oBACN,cAAc,CAAC,IAAI,CACjB,aAAa,UAAU,aAAa,SAAS,KAAK,CACnD,CAAC;gBACJ,CAAC;gBACD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;oBAC/B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;YAED,IAAI,cAAc,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7C,MAAM,aAAa,GAAG,GAAG,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC;gBAC5D,MAAM,WAAW,GAAG,WAAW;qBAC5B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,yBAAyB,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,EAAE,CAC7E;qBACA,IAAI,CAAC,KAAK,CAAC,CAAC;gBACf,gBAAgB,CAAC,IAAI,CACnB,2DAA2D,aAAa,OAAO,WAAW,KAAK,CAChG,CAAC;gBACF,cAAc,CAAC,IAAI,CAAC,4BAA4B,aAAa,IAAI,CAAC,CAAC;gBACnE,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;oBAChC,UAAU,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YAED,IAAI,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC3B,IAAI,eAAe,EAAE,CAAC;oBACpB,cAAc,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;oBAChE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACN,MAAM,QAAQ,GAAG,sBAAsB,CACrC,MAAM,CAAC,IAAI,CAAC,IAAI,EAChB,OAAO,EACP,cAAc,CACf,CAAC;oBACF,cAAc,CAAC,IAAI,CAAC,2BAA2B,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;oBAClE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE5C,IAAI,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC9B,MAAM,gBAAgB,GAAG,WAAW;oBAClC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACnD,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC,CAAC;gBAC9B,MAAM,IAAI,GAAG,mBAAmB,CAAC;oBAC/B,aAAa;oBACb,UAAU;oBACV,cAAc;oBACd,aAAa,EAAE,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC1C,YAAY,EAAE,GAAG,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU;oBAC7D,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,cAAc;iBACf,CAAC,CAAC;gBACH,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpB,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC;gBACrC,MAAM,SAAS,GAAG,UAAU,SAAS,KAAK,MAAM,IAAI,aAAa,oBAAoB,CAAC;gBACtF,IAAI,WAAW,EAAE,CAAC;oBAChB,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAClC,CAAC;qBAAM,CAAC;oBACN,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC/B,CAAC;gBACD,SAAS;YACX,CAAC;YAED,MAAM,UAAU,GAAG,WAAW,WAAW,IAAI,aAAa,SAAS,CAAC;YAEpE,MAAM,gBAAgB,GAAG,MAAM,CAAC,YAAY;gBAC1C,CAAC,CAAC;;;;;wDAK8C,MAAM,CAAC,YAAY;;;;;;;;;MASrE;gBACE,CAAC,CAAC;;;;;;;MAOJ,CAAC;YAED,MAAM,UAAU,GAAG,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,MAAM,WAAW,GACf,YAAY,KAAK,MAAM;gBACrB,CAAC,CAAC,YAAY,aAAa;;eAEtB,aAAa;;EAE1B,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;2BAMA,WAAW,IAAI,aAAa;MACjD,gBAAgB;EACpB;gBACQ,CAAC,CAAC,gBAAgB,aAAa;2BACd,cAAc;EACvC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;;eAGZ,UAAU;;;mBAGN,UAAU;MACvB,gBAAgB;EACpB,CAAC;YAEG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE3B,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;gBAC5B,SAAS;YACX,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC;YACrC,IAAI,SAAS,GAAG,EAAE,CAAC;YACnB,IAAI,WAAW,EAAE,CAAC;gBAChB,SAAS,GAAG,UAAU,SAAS,KAAK,MAAM,IAAI,aAAa,iBAAiB,CAAC;gBAC7E,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,UAAU,SAAS,KAAK,MAAM,IAAI,aAAa,iBAAiB,CAAC;gBAC7E,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhE,MAAM,UAAU,GAAG,eAAe,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;IAElE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC;sBACS,aAAa;;;CAGlC,CAAC,CAAC;IACD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAElC,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC;;;;;;;;EAQb,UAAU,CAAC,OAAO,CAAC,eAAe,EAAE,iCAAiC,CAAC;EACtE,CAAC,CAAC;IACF,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC;;;;;;;EAOb,UAAU;EACV,CAAC,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,YAAsB,EACtB,eAAyB;IAEzB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAClD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC7C,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAClE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/generator/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,6 +91,54 @@ describe("@etagCache decorator", () => {
|
|
|
91
91
|
const server = results["server.rs"];
|
|
92
92
|
strictEqual(server.includes('let cache_key = format!("img:list:pub:{account_id}");'), true);
|
|
93
93
|
});
|
|
94
|
+
it("does not use mut binding as the call receiver with @rustMut", async () => {
|
|
95
|
+
const spec = `
|
|
96
|
+
import "@typespec/http";
|
|
97
|
+
import "typespec-rust-emitter";
|
|
98
|
+
using TypeSpec.Http;
|
|
99
|
+
|
|
100
|
+
@route("/accounts/{accountId}/groups")
|
|
101
|
+
namespace Groups {
|
|
102
|
+
@etagCache("groups:logs:{accountId}:last:{lastId}:limit:{limit}")
|
|
103
|
+
@rustMut
|
|
104
|
+
@get
|
|
105
|
+
op listLogs(
|
|
106
|
+
@path accountId: string,
|
|
107
|
+
@query lastId: string | null,
|
|
108
|
+
@query limit: int32,
|
|
109
|
+
): { @statusCode statusCode: 200; };
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
const results = await emit(spec);
|
|
113
|
+
const server = results["server.rs"];
|
|
114
|
+
strictEqual(server.includes("axum::extract::State(mut service): axum::extract::State<S>"), true);
|
|
115
|
+
strictEqual(server.includes("let result = mut service."), false);
|
|
116
|
+
strictEqual(server.includes("let result = service.groups_list_logs(&cache, account_id, params.last_id, params.limit).await;"), true);
|
|
117
|
+
});
|
|
118
|
+
it("interpolates query parameters in custom etag keys", async () => {
|
|
119
|
+
const spec = `
|
|
120
|
+
import "@typespec/http";
|
|
121
|
+
import "typespec-rust-emitter";
|
|
122
|
+
using TypeSpec.Http;
|
|
123
|
+
|
|
124
|
+
@route("/accounts/{accountId}/groups")
|
|
125
|
+
namespace Groups {
|
|
126
|
+
@etagCache("groups:list:{accountId}:tz:{userTimezone}:last:{lastId}:limit:{limit}")
|
|
127
|
+
@get
|
|
128
|
+
op list(
|
|
129
|
+
@path accountId: string,
|
|
130
|
+
@query userTimezone: string,
|
|
131
|
+
@query lastId: string | null,
|
|
132
|
+
@query limit: int32,
|
|
133
|
+
): { @statusCode statusCode: 200; };
|
|
134
|
+
}
|
|
135
|
+
`;
|
|
136
|
+
const results = await emit(spec);
|
|
137
|
+
const server = results["server.rs"];
|
|
138
|
+
strictEqual(server.includes('let cache_key = format!("groups:list:{account_id}:tz:{}:last:{:?}:limit:{}", params.user_timezone, params.last_id, params.limit);'), true);
|
|
139
|
+
strictEqual(server.includes("{userTimezone}"), false);
|
|
140
|
+
strictEqual(server.includes("{lastId}"), false);
|
|
141
|
+
});
|
|
94
142
|
it("orders cache after claims when combined with @useAuth", async () => {
|
|
95
143
|
const spec = `
|
|
96
144
|
import "@typespec/http";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"etag_cache.test.js","sourceRoot":"","sources":["../../test/etag_cache.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"etag_cache.test.js","sourceRoot":"","sources":["../../test/etag_cache.test.ts"],"names":[],"mappings":"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"}
|
package/example/main.tsp
CHANGED
|
@@ -86,6 +86,23 @@ namespace Images {
|
|
|
86
86
|
@statusCode statusCode: 304;
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
@etagCache("img:recent:{accountId}:tz:{userTimezone}:after:{lastId}:limit:{limit}")
|
|
90
|
+
@cacheControl("no-cache, max-age=2592000")
|
|
91
|
+
@rustMut
|
|
92
|
+
@get
|
|
93
|
+
@route("/recent")
|
|
94
|
+
op listRecent(
|
|
95
|
+
@path accountId: Uuid,
|
|
96
|
+
@query userTimezone: string,
|
|
97
|
+
@query lastId: Uuid | null,
|
|
98
|
+
@query limit: int32,
|
|
99
|
+
): {
|
|
100
|
+
@statusCode statusCode: 200;
|
|
101
|
+
@body images: Item[];
|
|
102
|
+
} | {
|
|
103
|
+
@statusCode statusCode: 304;
|
|
104
|
+
};
|
|
105
|
+
|
|
89
106
|
@etagCache("img:detail:pub")
|
|
90
107
|
@cacheControl("public, max-age=60")
|
|
91
108
|
@get
|
|
@@ -38,6 +38,9 @@ pub trait Server: Send + Sync {
|
|
|
38
38
|
async fn images_list_public<C: EtagCache + Send + Sync>(
|
|
39
39
|
&self, cache: &C, account_id: uuid::Uuid
|
|
40
40
|
) -> Result<ImagesListPublicResponse>;
|
|
41
|
+
async fn images_list_recent<C: EtagCache + Send + Sync>(
|
|
42
|
+
&mut self, cache: &C, account_id: uuid::Uuid, user_timezone: String, last_id: Option<uuid::Uuid>, limit: i32
|
|
43
|
+
) -> Result<ImagesListRecentResponse>;
|
|
41
44
|
async fn images_get_image<C: EtagCache + Send + Sync>(
|
|
42
45
|
&self, cache: &C, account_id: uuid::Uuid, image_id: String
|
|
43
46
|
) -> Result<ImagesGetImageResponse>;
|
|
@@ -147,6 +150,22 @@ impl IntoResponse for ImagesListPublicResponse {
|
|
|
147
150
|
}
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
#[allow(clippy::type_complexity)]
|
|
154
|
+
pub enum ImagesListRecentResponse {
|
|
155
|
+
Ok(Json<Vec<Item>>),
|
|
156
|
+
NotModified,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
impl IntoResponse for ImagesListRecentResponse {
|
|
160
|
+
fn into_response(self) -> axum::response::Response {
|
|
161
|
+
match self {
|
|
162
|
+
|
|
163
|
+
ImagesListRecentResponse::Ok(body) => (StatusCode::OK, body).into_response(),
|
|
164
|
+
ImagesListRecentResponse::NotModified => StatusCode::NOT_MODIFIED.into_response(),
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
150
169
|
#[allow(clippy::type_complexity)]
|
|
151
170
|
pub enum ImagesGetImageResponse {
|
|
152
171
|
Ok(Json<Item>),
|
|
@@ -230,6 +249,16 @@ pub struct ItemsUpdateItemQuery {
|
|
|
230
249
|
pub id: String
|
|
231
250
|
}
|
|
232
251
|
|
|
252
|
+
#[derive(Debug, Clone, serde::Deserialize)]
|
|
253
|
+
pub struct ImagesListRecentQuery {
|
|
254
|
+
#[serde(rename = "userTimezone")]
|
|
255
|
+
pub user_timezone: String,
|
|
256
|
+
#[serde(rename = "lastId")]
|
|
257
|
+
pub last_id: Option<uuid::Uuid>,
|
|
258
|
+
#[serde(rename = "limit")]
|
|
259
|
+
pub limit: i32
|
|
260
|
+
}
|
|
261
|
+
|
|
233
262
|
#[derive(Debug, Clone, serde::Deserialize)]
|
|
234
263
|
pub struct ConsumingConsumeAndDeleteQuery {
|
|
235
264
|
#[serde(rename = "id")]
|
|
@@ -426,6 +455,50 @@ where
|
|
|
426
455
|
}
|
|
427
456
|
}
|
|
428
457
|
|
|
458
|
+
pub async fn images_list_recent_handler<S, C>(
|
|
459
|
+
axum::extract::State(mut service): axum::extract::State<S>,
|
|
460
|
+
axum::extract::State(cache): axum::extract::State<C>,
|
|
461
|
+
if_none_match: Option<axum_extra::TypedHeader<axum_extra::headers::IfNoneMatch>>,
|
|
462
|
+
Path(account_id): Path<uuid::Uuid>,
|
|
463
|
+
Query(params): Query<ImagesListRecentQuery>,
|
|
464
|
+
) -> impl axum::response::IntoResponse
|
|
465
|
+
where
|
|
466
|
+
S: Server + Send + Sync + 'static,
|
|
467
|
+
S::Claims: Send + Sync + Clone + 'static,
|
|
468
|
+
C: EtagCache + Clone + Send + Sync + 'static,
|
|
469
|
+
{
|
|
470
|
+
// Check If-None-Match against the cache
|
|
471
|
+
let cache_key = format!("img:recent:{account_id}:tz:{}:after:{:?}:limit:{}", params.user_timezone, params.last_id, params.limit);
|
|
472
|
+
if let (Some(stored_etag), Some(axum_extra::TypedHeader(inm))) =
|
|
473
|
+
(cache.get(cache_key.as_ref()).await, if_none_match)
|
|
474
|
+
&& let Ok(etag) = stored_etag.parse::<axum_extra::headers::ETag>()
|
|
475
|
+
&& !inm.precondition_passes(&etag)
|
|
476
|
+
{
|
|
477
|
+
let mut res = axum::http::StatusCode::NOT_MODIFIED.into_response();
|
|
478
|
+
res.headers_mut().insert(axum::http::header::CACHE_CONTROL, axum::http::HeaderValue::from_static("no-cache, max-age=2592000"));
|
|
479
|
+
return res;
|
|
480
|
+
}
|
|
481
|
+
// Forward to business logic
|
|
482
|
+
let result = service.images_list_recent(&cache, account_id, params.user_timezone, params.last_id, params.limit).await;
|
|
483
|
+
match result {
|
|
484
|
+
Ok(response) => {
|
|
485
|
+
let mut res = response.into_response();
|
|
486
|
+
if let Some(stored_etag) = cache.get(cache_key.as_ref()).await
|
|
487
|
+
&& let Ok(etag) = axum::http::HeaderValue::from_str(&stored_etag)
|
|
488
|
+
{
|
|
489
|
+
res.headers_mut().insert(axum::http::header::ETAG, etag);
|
|
490
|
+
}
|
|
491
|
+
res.headers_mut().insert(axum::http::header::CACHE_CONTROL, axum::http::HeaderValue::from_static("no-cache, max-age=2592000"));
|
|
492
|
+
res
|
|
493
|
+
}
|
|
494
|
+
Err(e) => (
|
|
495
|
+
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
|
496
|
+
format!("Internal error: {e}"),
|
|
497
|
+
)
|
|
498
|
+
.into_response(),
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
429
502
|
pub async fn images_get_image_handler<S, C>(
|
|
430
503
|
axum::extract::State(service): axum::extract::State<S>,
|
|
431
504
|
axum::extract::State(cache): axum::extract::State<C>,
|
|
@@ -570,6 +643,7 @@ where
|
|
|
570
643
|
.route("/items", post(items_create_item_handler::<S>))
|
|
571
644
|
.route("/items", put(items_update_item_handler::<S>))
|
|
572
645
|
.route("/accounts/{accountId}/images", get(images_list_public_handler::<S, C>))
|
|
646
|
+
.route("/accounts/{accountId}/images/recent", get(images_list_recent_handler::<S, C>))
|
|
573
647
|
.route("/accounts/{accountId}/images/{imageId}", get(images_get_image_handler::<S, C>))
|
|
574
648
|
.route("/consuming", post(consuming_upload_handler::<S>))
|
|
575
649
|
;
|
|
@@ -8,8 +8,8 @@ use axum::response::sse::{Event, KeepAlive, Sse};
|
|
|
8
8
|
use generated::server::{
|
|
9
9
|
ArticlesGetArticleResponse, ConsumingConsumeAndDeleteResponse, ConsumingUploadResponse,
|
|
10
10
|
EtagCache, EventsAccountsEventsResponse, ImagesGetImageResponse, ImagesListPublicResponse,
|
|
11
|
-
ItemsCreateItemResponse, ItemsGetItemResponse, ItemsListResponse,
|
|
12
|
-
PetsListResponse, Server,
|
|
11
|
+
ImagesListRecentResponse, ItemsCreateItemResponse, ItemsGetItemResponse, ItemsListResponse,
|
|
12
|
+
ItemsUpdateItemResponse, PetsListResponse, Server,
|
|
13
13
|
};
|
|
14
14
|
use std::collections::HashMap;
|
|
15
15
|
use std::convert::Infallible;
|
|
@@ -131,6 +131,31 @@ impl Server for AppState {
|
|
|
131
131
|
])))
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
async fn images_list_recent<C: EtagCache + Send + Sync>(
|
|
135
|
+
&mut self,
|
|
136
|
+
cache: &C,
|
|
137
|
+
account_id: uuid::Uuid,
|
|
138
|
+
user_timezone: String,
|
|
139
|
+
last_id: Option<uuid::Uuid>,
|
|
140
|
+
limit: i32,
|
|
141
|
+
) -> eyre::Result<ImagesListRecentResponse> {
|
|
142
|
+
cache
|
|
143
|
+
.set(
|
|
144
|
+
&format!(
|
|
145
|
+
"img:recent:{}:tz:{}:after:{:?}:limit:{}",
|
|
146
|
+
account_id, user_timezone, last_id, limit
|
|
147
|
+
),
|
|
148
|
+
"\"recent-images-etag\"",
|
|
149
|
+
)
|
|
150
|
+
.await;
|
|
151
|
+
Ok(ImagesListRecentResponse::Ok(Json(vec![
|
|
152
|
+
generated::types::Item {
|
|
153
|
+
name: "recent-image-1".to_string(),
|
|
154
|
+
value: limit,
|
|
155
|
+
},
|
|
156
|
+
])))
|
|
157
|
+
}
|
|
158
|
+
|
|
134
159
|
async fn images_get_image<C: EtagCache + Send + Sync>(
|
|
135
160
|
&self,
|
|
136
161
|
cache: &C,
|
package/package.json
CHANGED
|
@@ -32,19 +32,34 @@ function buildCacheKeyExpression(opts: {
|
|
|
32
32
|
handlerFnName: string;
|
|
33
33
|
etagKey?: string;
|
|
34
34
|
pathParams: ParameterInfo[];
|
|
35
|
+
queryParams?: ParameterInfo[];
|
|
35
36
|
}): string {
|
|
36
|
-
const { handlerFnName, etagKey, pathParams } = opts;
|
|
37
|
+
const { handlerFnName, etagKey, pathParams, queryParams = [] } = opts;
|
|
37
38
|
const pathSuffix = pathParams.map((p) => `{${p.rustName}}`).join(":");
|
|
38
39
|
const paramNames = new Map<string, string>();
|
|
39
40
|
for (const param of pathParams) {
|
|
40
41
|
paramNames.set(param.name, param.rustName);
|
|
41
42
|
paramNames.set(param.rustName, param.rustName);
|
|
42
43
|
}
|
|
44
|
+
const queryParamNames = new Map<string, ParameterInfo>();
|
|
45
|
+
for (const param of queryParams) {
|
|
46
|
+
queryParamNames.set(param.name, param);
|
|
47
|
+
queryParamNames.set(param.rustName, param);
|
|
48
|
+
}
|
|
43
49
|
|
|
44
50
|
let template = etagKey ?? handlerFnName;
|
|
51
|
+
const formatArgs: string[] = [];
|
|
45
52
|
template = template.replace(/\{([^}]+)\}/g, (match, name: string) => {
|
|
46
53
|
const rustName = paramNames.get(name);
|
|
47
|
-
|
|
54
|
+
if (rustName) {
|
|
55
|
+
return `{${rustName}}`;
|
|
56
|
+
}
|
|
57
|
+
const queryParam = queryParamNames.get(name);
|
|
58
|
+
if (queryParam) {
|
|
59
|
+
formatArgs.push(`params.${queryParam.rustName}`);
|
|
60
|
+
return queryParam.rustType.startsWith("Option<") ? "{:?}" : "{}";
|
|
61
|
+
}
|
|
62
|
+
return match;
|
|
48
63
|
});
|
|
49
64
|
|
|
50
65
|
const hasExplicitPathParam = pathParams.some(
|
|
@@ -59,7 +74,8 @@ function buildCacheKeyExpression(opts: {
|
|
|
59
74
|
if (!template.includes("{")) {
|
|
60
75
|
return rustStringLiteral(template);
|
|
61
76
|
}
|
|
62
|
-
|
|
77
|
+
const args = formatArgs.length > 0 ? `, ${formatArgs.join(", ")}` : "";
|
|
78
|
+
return `format!(${rustStringLiteral(template)}${args})`;
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
/**
|
|
@@ -76,6 +92,7 @@ function buildCacheKeyExpression(opts: {
|
|
|
76
92
|
export function generateEtagHandler(opts: {
|
|
77
93
|
handlerFnName: string;
|
|
78
94
|
pathParams: ParameterInfo[];
|
|
95
|
+
queryParams?: ParameterInfo[];
|
|
79
96
|
extractorLines: string[];
|
|
80
97
|
serverArgsStr: string;
|
|
81
98
|
responseName: string;
|
|
@@ -86,6 +103,7 @@ export function generateEtagHandler(opts: {
|
|
|
86
103
|
const {
|
|
87
104
|
handlerFnName,
|
|
88
105
|
pathParams,
|
|
106
|
+
queryParams = [],
|
|
89
107
|
extractorLines,
|
|
90
108
|
serverArgsStr,
|
|
91
109
|
etagKey,
|
|
@@ -97,7 +115,9 @@ export function generateEtagHandler(opts: {
|
|
|
97
115
|
handlerFnName,
|
|
98
116
|
etagKey,
|
|
99
117
|
pathParams,
|
|
118
|
+
queryParams,
|
|
100
119
|
});
|
|
120
|
+
const serviceReceiver = serviceBinding.replace(/^mut\s+/, "");
|
|
101
121
|
const operationExtractors =
|
|
102
122
|
extractorLines.length > 0 ? `${extractorLines.join("\n")}\n` : "";
|
|
103
123
|
|
|
@@ -141,7 +161,7 @@ where
|
|
|
141
161
|
return res;
|
|
142
162
|
}
|
|
143
163
|
// Forward to business logic
|
|
144
|
-
let result = ${
|
|
164
|
+
let result = ${serviceReceiver}.${handlerFnName}(${serverArgsStr}).await;
|
|
145
165
|
${finalResponseLogic}
|
|
146
166
|
}`;
|
|
147
167
|
}
|
package/src/generator/router.ts
CHANGED
|
@@ -123,6 +123,7 @@ export function generateRouter(
|
|
|
123
123
|
const code = generateEtagHandler({
|
|
124
124
|
handlerFnName,
|
|
125
125
|
pathParams,
|
|
126
|
+
queryParams,
|
|
126
127
|
extractorLines,
|
|
127
128
|
serverArgsStr: cachedServerArgs.join(", "),
|
|
128
129
|
responseName: `${nsName}${toPascalCase(opInfo.name)}Response`,
|
package/test/etag_cache.test.ts
CHANGED
|
@@ -116,6 +116,71 @@ describe("@etagCache decorator", () => {
|
|
|
116
116
|
);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
+
it("does not use mut binding as the call receiver with @rustMut", async () => {
|
|
120
|
+
const spec = `
|
|
121
|
+
import "@typespec/http";
|
|
122
|
+
import "typespec-rust-emitter";
|
|
123
|
+
using TypeSpec.Http;
|
|
124
|
+
|
|
125
|
+
@route("/accounts/{accountId}/groups")
|
|
126
|
+
namespace Groups {
|
|
127
|
+
@etagCache("groups:logs:{accountId}:last:{lastId}:limit:{limit}")
|
|
128
|
+
@rustMut
|
|
129
|
+
@get
|
|
130
|
+
op listLogs(
|
|
131
|
+
@path accountId: string,
|
|
132
|
+
@query lastId: string | null,
|
|
133
|
+
@query limit: int32,
|
|
134
|
+
): { @statusCode statusCode: 200; };
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
const results = await emit(spec);
|
|
138
|
+
const server = results["server.rs"];
|
|
139
|
+
strictEqual(
|
|
140
|
+
server.includes(
|
|
141
|
+
"axum::extract::State(mut service): axum::extract::State<S>",
|
|
142
|
+
),
|
|
143
|
+
true,
|
|
144
|
+
);
|
|
145
|
+
strictEqual(server.includes("let result = mut service."), false);
|
|
146
|
+
strictEqual(
|
|
147
|
+
server.includes(
|
|
148
|
+
"let result = service.groups_list_logs(&cache, account_id, params.last_id, params.limit).await;",
|
|
149
|
+
),
|
|
150
|
+
true,
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("interpolates query parameters in custom etag keys", async () => {
|
|
155
|
+
const spec = `
|
|
156
|
+
import "@typespec/http";
|
|
157
|
+
import "typespec-rust-emitter";
|
|
158
|
+
using TypeSpec.Http;
|
|
159
|
+
|
|
160
|
+
@route("/accounts/{accountId}/groups")
|
|
161
|
+
namespace Groups {
|
|
162
|
+
@etagCache("groups:list:{accountId}:tz:{userTimezone}:last:{lastId}:limit:{limit}")
|
|
163
|
+
@get
|
|
164
|
+
op list(
|
|
165
|
+
@path accountId: string,
|
|
166
|
+
@query userTimezone: string,
|
|
167
|
+
@query lastId: string | null,
|
|
168
|
+
@query limit: int32,
|
|
169
|
+
): { @statusCode statusCode: 200; };
|
|
170
|
+
}
|
|
171
|
+
`;
|
|
172
|
+
const results = await emit(spec);
|
|
173
|
+
const server = results["server.rs"];
|
|
174
|
+
strictEqual(
|
|
175
|
+
server.includes(
|
|
176
|
+
'let cache_key = format!("groups:list:{account_id}:tz:{}:last:{:?}:limit:{}", params.user_timezone, params.last_id, params.limit);',
|
|
177
|
+
),
|
|
178
|
+
true,
|
|
179
|
+
);
|
|
180
|
+
strictEqual(server.includes("{userTimezone}"), false);
|
|
181
|
+
strictEqual(server.includes("{lastId}"), false);
|
|
182
|
+
});
|
|
183
|
+
|
|
119
184
|
it("orders cache after claims when combined with @useAuth", async () => {
|
|
120
185
|
const spec = `
|
|
121
186
|
import "@typespec/http";
|