Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-actors-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bearstudio/lunalink": patch
---

feat: make params able to be number of boolean (stringable)
18 changes: 14 additions & 4 deletions packages/lunalink/src/index.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,34 @@ const multipleParamsWithDot = "/contacts/:contactId/address/:addressId.html.md";

// Tests OK
type TestSimpleParamOK = Expect<
Equal<ExtractParams<typeof simpleParam>, { id: string }>
Equal<
ExtractParams<typeof simpleParam>,
{ id: string | number | boolean }
>
>;

type TestMultipleParamsOK = Expect<
Equal<
ExtractParams<typeof multipleParams>,
{ contactId: string } & { addressId: string }
{ contactId: string | number | boolean } & {
addressId: string | number | boolean;
}
>
>;

type TestWithDotOK = Expect<
Equal<ExtractParams<typeof simpleParamWithDot>, { id: string }>
Equal<
ExtractParams<typeof simpleParamWithDot>,
{ id: string | number | boolean }
>
>;

type TestMultipleParamsWithDotOK = Expect<
Equal<
ExtractParams<typeof multipleParamsWithDot>,
{ contactId: string } & { addressId: string }
{ contactId: string | number | boolean } & {
addressId: string | number | boolean;
}
>
>;

Expand Down
14 changes: 14 additions & 0 deletions packages/lunalink/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ describe("lunalink", () => {
expect(actual).toBe(expected);
});

it("should accept number params without explicit casting", () => {
const actual = lunalink("/users/:id", { id: 42 });
const expected = "/users/42";

expect(actual).toBe(expected);
});

it("should accept boolean params without explicit casting", () => {
const actual = lunalink("/feature/:flag", { flag: true });
const expected = "/feature/true";

expect(actual).toBe(expected);
});

it("should handle params that are followed by a dot (.)", () => {
const actual = lunalink("/podcasts/:id/episodes/:episodes.html.md", {
id: "fork-it-community-tech-podcast-fr",
Expand Down
11 changes: 7 additions & 4 deletions packages/lunalink/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ import queryString from "query-string";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ExplicitAny = any;

/** Accepted types for path parameters */
type ParamValue = string | number | boolean;

/** Type to extract params from a path */
export type ExtractParams<Path extends string> =
// 1) Handle path params with `?`
Path extends `${string}:${infer Param}?`
? { [K in Param]: string }
? { [K in Param]: ParamValue }
: // 2) Handle path splitting
Path extends `${string}:${infer Param}/${infer Rest}`
? { [K in Param]: string } & ExtractParams<`/${Rest}`>
? { [K in Param]: ParamValue } & ExtractParams<`/${Rest}`>
: // 3) Handle params with dot separator
Path extends `${string}:${infer Param}.${infer Rest}`
? { [K in Param]: string } & ExtractParams<`${Rest}`>
? { [K in Param]: ParamValue } & ExtractParams<`${Rest}`>
: // 4) Handle params
Path extends `${string}:${infer Param}`
? { [K in Param]: string }
? { [K in Param]: ParamValue }
: // Nothing to extract
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
{};
Expand Down
Loading