Skip to content

Commit 8131b65

Browse files
authored
Merge pull request #79 from stainless-api/mcasey/ignore-base-path-case
Do not format base paths
2 parents 33871c4 + b2627ff commit 8131b65

7 files changed

Lines changed: 149 additions & 49 deletions

File tree

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"pkg-up": "~3.1.0",
3333
"resolve": "^1.22.8",
3434
"ts-morph": "^19.0.0",
35-
"ts-to-zod": "github:stainless-api/stl-api#ts-to-zod-0.0.5"
35+
"ts-to-zod": "github:stainless-api/stl-api#ts-to-zod-0.0.4"
3636
},
3737
"devDependencies": {
3838
"@swc/core": "^1.3.100",

packages/client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"dedent-js": "^1.0.1",
3030
"lodash": "^4.17.21",
3131
"prettier": "^3.3.3",
32-
"stainless": "github:stainless-api/stl-api#stainless-0.1.3",
32+
"stainless": "github:stainless-api/stl-api#stainless-0.1.4",
3333
"typescript": "^5.3.2",
3434
"zod-to-ts": "^1.2.0"
3535
},

packages/client/src/core/api-client.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
22
import { makeClientWithInferredTypes } from "./api-client";
33
import { Client } from "./api-client-types";
44
import * as MockAPI from "../test-util/api-server";
5+
import { complicatedBasePath } from "../test-util/long-base-path-api";
56

67
describe("API Client", () => {
78
describe("configuration options", () => {
@@ -31,6 +32,42 @@ describe("API Client", () => {
3132
});
3233
});
3334

35+
describe("long base paths", () => {
36+
let client: Client<
37+
MockAPI.APIWithCustomBasePathAPI,
38+
MockAPI.APIWithCustomBasePathConfig
39+
>;
40+
let mockFetch: typeof fetch;
41+
42+
beforeEach(() => {
43+
mockFetch = vi.fn(MockAPI.mockFetchImplementation);
44+
const config = {
45+
fetch: mockFetch,
46+
basePath: complicatedBasePath,
47+
urlCase: "camel",
48+
};
49+
client = makeClientWithInferredTypes<
50+
MockAPI.APIWithCustomBasePathAPI,
51+
MockAPI.APIWithCustomBasePathConfig
52+
>(config);
53+
});
54+
55+
afterEach(() => {
56+
vi.restoreAllMocks();
57+
});
58+
59+
it("preserves base path, including casing", async () => {
60+
const dogs = await client.dogs.list();
61+
expect(mockFetch).toHaveBeenCalledWith(
62+
"/api/camelCase/kebab-case/v2/dogs",
63+
{
64+
method: "GET",
65+
}
66+
);
67+
expect(dogs).toStrictEqual([{ name: "Fido", color: "red" }]);
68+
});
69+
});
70+
3471
describe("fetch calls", () => {
3572
let client: Client<MockAPI.API, MockAPI.Config>;
3673
let mockFetch: typeof fetch;

packages/client/src/core/api-client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ function makeUrl(callPath: string[], outputCase: "camel" | "kebab" = "kebab") {
6565
async function makeRequest(
6666
config: ClientConfig<string>,
6767
action: string,
68-
callPath: string[],
68+
[basePath, ...callPath]: string[],
6969
body?: unknown
7070
) {
7171
const method = inferHTTPMethod(action, body);
72-
const url = makeUrl(callPath, config.urlCase);
72+
const url = `${basePath}/${makeUrl(callPath, config.urlCase)}`;
7373
const fetchFn = config.fetch ?? fetch;
7474
const options: RequestInit =
7575
method !== "GET" && body !== undefined

packages/client/src/test-util/api-server.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Stl } from "stainless";
22
import { cats } from "../test-util/cat-api";
33
import { dogs } from "../test-util/dog-api";
4+
import * as LongBasePath from "../test-util/long-base-path-api";
45
import { users } from "../test-util/user-api";
56
import { dogTreats } from "../test-util/dog-treat-api";
67

@@ -27,6 +28,9 @@ export async function mockFetchImplementation(
2728
case "GET /api/dogs/fido/dog-treats":
2829
payload = [{ yummy: true }];
2930
break;
31+
case "GET /api/camelCase/kebab-case/v2/dogs":
32+
payload = [{ name: "Fido", color: "red" }];
33+
break;
3034
case "GET /api/dogs":
3135
throw new Error("Expected to throw");
3236
case "PATCH /api/dogs/fido/dog-treats/treatId":
@@ -69,6 +73,18 @@ export const nestedApi = stl.api({
6973
},
7074
});
7175

76+
export const customBasePathApi = stl.api({
77+
basePath: LongBasePath.complicatedBasePath,
78+
resources: {
79+
dogs: LongBasePath.dogs,
80+
},
81+
});
82+
83+
export type APIWithCustomBasePathAPI = typeof customBasePathApi;
84+
export type APIWithCustomBasePathConfig = {
85+
basePath: APIWithCustomBasePathAPI["basePath"];
86+
};
87+
7288
export type API = typeof api;
7389
export const config = { basePath: "/api" } as const;
7490
export type Config = typeof config;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Stl, z } from "stainless";
2+
3+
export const complicatedBasePath = "/api/camelCase/kebab-case/v2" as const;
4+
5+
const stl = new Stl({ plugins: {} });
6+
7+
const dog = z.object({
8+
name: z.string(),
9+
color: z.string(),
10+
});
11+
12+
const listDogs = stl.endpoint({
13+
endpoint: `GET ${complicatedBasePath}/dogs`,
14+
response: dog.array(),
15+
handler: async (_params, _context) => {
16+
return [
17+
{ name: "Shiro", color: "black" },
18+
{ name: "baby!", color: "black" },
19+
];
20+
},
21+
});
22+
23+
export const dogs = stl.resource({
24+
summary: "Dogs",
25+
actions: {
26+
list: listDogs,
27+
},
28+
});

0 commit comments

Comments
 (0)