Skip to content

Commit b5024bf

Browse files
Merge pull request #188 from li-yechao/main
feat: expose variableNames to retrieve all parameters from UriTemplate
2 parents cb6d7dd + 7c115ed commit b5024bf

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/shared/uriTemplate.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ describe("UriTemplate", () => {
2424
expect(template.expand({ username: "fred" })).toBe(
2525
"http://example.com/users/fred",
2626
);
27+
expect(template.variableNames).toEqual(['username'])
2728
});
2829

2930
it("should handle multiple variables", () => {
3031
const template = new UriTemplate("{x,y}");
3132
expect(template.expand({ x: "1024", y: "768" })).toBe("1024,768");
33+
expect(template.variableNames).toEqual(['x', 'y'])
3234
});
3335

3436
it("should encode reserved characters", () => {
@@ -43,41 +45,47 @@ describe("UriTemplate", () => {
4345
it("should not encode reserved characters with + operator", () => {
4446
const template = new UriTemplate("{+path}/here");
4547
expect(template.expand({ path: "/foo/bar" })).toBe("/foo/bar/here");
48+
expect(template.variableNames).toEqual(['path'])
4649
});
4750
});
4851

4952
describe("fragment expansion", () => {
5053
it("should add # prefix and not encode reserved chars", () => {
5154
const template = new UriTemplate("X{#var}");
5255
expect(template.expand({ var: "/test" })).toBe("X#/test");
56+
expect(template.variableNames).toEqual(['var'])
5357
});
5458
});
5559

5660
describe("label expansion", () => {
5761
it("should add . prefix", () => {
5862
const template = new UriTemplate("X{.var}");
5963
expect(template.expand({ var: "test" })).toBe("X.test");
64+
expect(template.variableNames).toEqual(['var'])
6065
});
6166
});
6267

6368
describe("path expansion", () => {
6469
it("should add / prefix", () => {
6570
const template = new UriTemplate("X{/var}");
6671
expect(template.expand({ var: "test" })).toBe("X/test");
72+
expect(template.variableNames).toEqual(['var'])
6773
});
6874
});
6975

7076
describe("query expansion", () => {
7177
it("should add ? prefix and name=value format", () => {
7278
const template = new UriTemplate("X{?var}");
7379
expect(template.expand({ var: "test" })).toBe("X?var=test");
80+
expect(template.variableNames).toEqual(['var'])
7481
});
7582
});
7683

7784
describe("form continuation expansion", () => {
7885
it("should add & prefix and name=value format", () => {
7986
const template = new UriTemplate("X{&var}");
8087
expect(template.expand({ var: "test" })).toBe("X&var=test");
88+
expect(template.variableNames).toEqual(['var'])
8189
});
8290
});
8391

@@ -133,13 +141,15 @@ describe("UriTemplate", () => {
133141
resource: "users",
134142
id: "123"
135143
})).toBe("/api/v1/users/123");
144+
expect(template.variableNames).toEqual(['version', 'resource', 'id'])
136145
});
137146

138147
it("should handle query parameters with arrays", () => {
139148
const template = new UriTemplate("/search{?tags*}");
140149
expect(template.expand({
141150
tags: ["nodejs", "typescript", "testing"]
142151
})).toBe("/search?tags=nodejs,typescript,testing");
152+
expect(template.variableNames).toEqual(['tags'])
143153
});
144154

145155
it("should handle multiple query parameters", () => {
@@ -149,6 +159,7 @@ describe("UriTemplate", () => {
149159
page: "1",
150160
limit: "10"
151161
})).toBe("/search?q=test&page=1&limit=10");
162+
expect(template.variableNames).toEqual(['q', 'page', 'limit'])
152163
});
153164
});
154165

@@ -161,18 +172,21 @@ describe("UriTemplate", () => {
161172
resource: "users",
162173
id: "123"
163174
});
175+
expect(template.variableNames).toEqual(['version', 'resource', 'id'])
164176
});
165177

166178
it("should match query parameters", () => {
167179
const template = new UriTemplate("/search{?q}");
168180
const match = template.match("/search?q=test");
169181
expect(match).toEqual({ q: "test" });
182+
expect(template.variableNames).toEqual(['q'])
170183
});
171184

172185
it("should match multiple query parameters", () => {
173186
const template = new UriTemplate("/search{?q,page}");
174187
const match = template.match("/search?q=test&page=1");
175188
expect(match).toEqual({ q: "test", page: "1" });
189+
expect(template.variableNames).toEqual(['q', 'page'])
176190
});
177191

178192
it("should handle partial matches correctly", () => {
@@ -229,17 +243,20 @@ describe("UriTemplate", () => {
229243
it("should handle repeated operators", () => {
230244
const template = new UriTemplate("{?a}{?b}{?c}");
231245
expect(template.expand({ a: "1", b: "2", c: "3" })).toBe("?a=1&b=2&c=3");
246+
expect(template.variableNames).toEqual(['a', 'b', 'c'])
232247
});
233248

234249
it("should handle overlapping variable names", () => {
235250
const template = new UriTemplate("{var}{vara}");
236251
expect(template.expand({ var: "1", vara: "2" })).toBe("12");
252+
expect(template.variableNames).toEqual(['var', 'vara'])
237253
});
238254

239255
it("should handle empty segments", () => {
240256
const template = new UriTemplate("///{a}////{b}////");
241257
expect(template.expand({ a: "1", b: "2" })).toBe("///1////2////");
242258
expect(template.match("///1////2////")).toEqual({ a: "1", b: "2" });
259+
expect(template.variableNames).toEqual(['a', 'b'])
243260
});
244261

245262
it("should handle maximum template expression limit", () => {

src/shared/uriTemplate.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export class UriTemplate {
3636
| { name: string; operator: string; names: string[]; exploded: boolean }
3737
>;
3838

39+
get variableNames(): string[] {
40+
return this.parts.flatMap((part) => typeof part === 'string' ? [] : part.names);
41+
}
42+
3943
constructor(template: string) {
4044
UriTemplate.validateLength(template, MAX_TEMPLATE_LENGTH, "Template");
4145
this.template = template;

0 commit comments

Comments
 (0)