From 3c12dc5b56249d7d8a75cff7205c2ad1d9cefede Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sat, 8 Nov 2025 19:27:54 +0100 Subject: [PATCH 01/16] TDD: adjusting the test that should pass. --- express-zod-api/tests/routing.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/express-zod-api/tests/routing.spec.ts b/express-zod-api/tests/routing.spec.ts index ad0f3c684..ab2b5a0f6 100644 --- a/express-zod-api/tests/routing.spec.ts +++ b/express-zod-api/tests/routing.spec.ts @@ -128,8 +128,8 @@ describe("Routing", () => { user: { "get /": getEndpoint, "post /": postEndpoint, - "put /": putAndPatchEndpoint, - "patch /": putAndPatchEndpoint, + put: putAndPatchEndpoint, + patch: putAndPatchEndpoint, }, }, }; From 8c459c13ce819633948aaca5123bc31bb6f1ddc0 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sat, 8 Nov 2025 20:09:18 +0100 Subject: [PATCH 02/16] Draft implementation. --- express-zod-api/src/routing-walker.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/express-zod-api/src/routing-walker.ts b/express-zod-api/src/routing-walker.ts index e8348a4df..28c1517cb 100644 --- a/express-zod-api/src/routing-walker.ts +++ b/express-zod-api/src/routing-walker.ts @@ -24,6 +24,10 @@ interface RoutingWalkerParams { onStatic?: (path: string, handler: StaticHandler) => void; } +/** Checks that the given object has at least 2 keys that do exactly match Method */ +const hasMultipleMethodOnlyEntries = (subject: Routing) => + Object.keys(subject).filter(isMethod).length > 1; + /** @example delete /v1/user/retrieve —> [/v1/user/retrieve, delete] */ const detachMethod = (subject: string): [string, Method?] => { const [method, rest] = subject.trim().split(/ (.+)/, 2); @@ -35,14 +39,17 @@ const detachMethod = (subject: string): [string, Method?] => { const trimPath = (path: string) => path.trim().split("/").filter(Boolean).join("/"); -const processEntries = (subject: Routing, parent?: string) => - Object.entries(subject).map<[string, Routing[string], Method?]>( +const processEntries = (subject: Routing, parent?: string) => { + const preferMethod = hasMultipleMethodOnlyEntries(subject); + return Object.entries(subject).map<[string, Routing[string], Method?]>( ([_key, item]) => { - const [segment, method] = detachMethod(_key); + const [segment, method] = + isMethod(_key) && preferMethod ? ["/", _key] : detachMethod(_key); const path = [parent || ""].concat(trimPath(segment) || []).join("/"); return [path, item, method]; }, ); +}; const prohibit = (method: Method, path: string) => { throw new RoutingError( From 2e132da41b6a098d8fe26575431d9d0b36700662 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sat, 8 Nov 2025 20:14:03 +0100 Subject: [PATCH 03/16] Devoting the test entirely to the feature. --- express-zod-api/tests/routing.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/express-zod-api/tests/routing.spec.ts b/express-zod-api/tests/routing.spec.ts index ab2b5a0f6..a7b119dad 100644 --- a/express-zod-api/tests/routing.spec.ts +++ b/express-zod-api/tests/routing.spec.ts @@ -126,8 +126,8 @@ describe("Routing", () => { const routing: Routing = { v1: { user: { - "get /": getEndpoint, - "post /": postEndpoint, + get: getEndpoint, + post: postEndpoint, put: putAndPatchEndpoint, patch: putAndPatchEndpoint, }, From ce81764efcf750b96943a03bd75a177b2fb776ac Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 07:43:24 +0100 Subject: [PATCH 04/16] Only do that when assigned with endpoint. --- express-zod-api/src/routing-walker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/express-zod-api/src/routing-walker.ts b/express-zod-api/src/routing-walker.ts index 28c1517cb..da5e566e5 100644 --- a/express-zod-api/src/routing-walker.ts +++ b/express-zod-api/src/routing-walker.ts @@ -44,7 +44,9 @@ const processEntries = (subject: Routing, parent?: string) => { return Object.entries(subject).map<[string, Routing[string], Method?]>( ([_key, item]) => { const [segment, method] = - isMethod(_key) && preferMethod ? ["/", _key] : detachMethod(_key); + isMethod(_key) && preferMethod && item instanceof AbstractEndpoint + ? ["/", _key] + : detachMethod(_key); const path = [parent || ""].concat(trimPath(segment) || []).join("/"); return [path, item, method]; }, From 65a62f2e6c467b197123f067962d1d865b4dff38 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 08:47:24 +0100 Subject: [PATCH 05/16] Introducing methodLikeRouteBehavior config. Breaking: require config for Integration. --- example/generate-client.ts | 1 + example/routing.ts | 2 +- express-zod-api/src/config-type.ts | 8 ++++++++ express-zod-api/src/documentation.ts | 2 ++ express-zod-api/src/integration.ts | 5 +++++ express-zod-api/src/routing-walker.ts | 19 +++++++++++-------- express-zod-api/src/routing.ts | 2 +- express-zod-api/tests/integration.spec.ts | 6 ++++++ express-zod-api/tests/routing.spec.ts | 1 + 9 files changed, 36 insertions(+), 10 deletions(-) diff --git a/example/generate-client.ts b/example/generate-client.ts index d96aec4d6..326c87072 100644 --- a/example/generate-client.ts +++ b/example/generate-client.ts @@ -7,6 +7,7 @@ await writeFile( "example.client.ts", await new Integration({ routing, + config, serverUrl: `http://localhost:${config.http!.listen}`, }).printFormatted(), // or just .print(), "utf-8", diff --git a/example/routing.ts b/example/routing.ts index a6691fab3..789cab350 100644 --- a/example/routing.ts +++ b/example/routing.ts @@ -20,7 +20,7 @@ export const routing: Routing = { ":id": { remove: deleteUserEndpoint, // nested path: /v1/user/:id/remove // syntax 2: methods are defined within the route - "patch /": updateUserEndpoint, // demonstrates authentication + patch: updateUserEndpoint, // demonstrates authentication }, // demonstrates different response schemas depending on status code create: createUserEndpoint, diff --git a/express-zod-api/src/config-type.ts b/express-zod-api/src/config-type.ts index 959e3541e..6e5d4683f 100644 --- a/express-zod-api/src/config-type.ts +++ b/express-zod-api/src/config-type.ts @@ -46,6 +46,14 @@ export interface CommonConfig { * @default 405 * */ wrongMethodBehavior?: 404 | 405; + /** + * @desc How to treat Routing keys that look like methods (when assigned with an Endpoint) + * @see Method + * @example "method" — the key is treated as method of its parent path + * @example "route" — the key is treated as a nested route segment + * @default "method" + * */ + methodLikeRouteBehavior?: "method" | "route"; /** * @desc The ResultHandler to use for handling routing, parsing and upload errors * @default defaultResultHandler diff --git a/express-zod-api/src/documentation.ts b/express-zod-api/src/documentation.ts index 4454bdfcc..c695d41e9 100644 --- a/express-zod-api/src/documentation.ts +++ b/express-zod-api/src/documentation.ts @@ -62,6 +62,7 @@ interface DocumentationParams { /** * @desc Depict the HEAD method for each Endpoint supporting the GET method (feature of Express) * @default true + * @todo move to config * */ hasHeadMethod?: boolean; /** @default inline */ @@ -262,6 +263,7 @@ export class Documentation extends OpenApiBuilder { }; walkRouting({ routing, + config, onEndpoint: hasHeadMethod ? withHead(onEndpoint) : onEndpoint, }); if (tags) this.rootDoc.tags = depictTags(tags); diff --git a/express-zod-api/src/integration.ts b/express-zod-api/src/integration.ts index 98fe3cb54..51a533b83 100644 --- a/express-zod-api/src/integration.ts +++ b/express-zod-api/src/integration.ts @@ -23,9 +23,11 @@ import { zodToTs } from "./zts.ts"; import { ZTSContext } from "./zts-helpers.ts"; import type Prettier from "prettier"; import { ClientMethod } from "./method.ts"; +import { CommonConfig } from "./config-type.ts"; interface IntegrationParams { routing: Routing; + config: CommonConfig; /** * @desc What should be generated * @example "types" — types of your endpoint requests and responses (for a DIY solution) @@ -50,6 +52,7 @@ interface IntegrationParams { /** * @desc Depict the HEAD method for each Endpoint supporting the GET method (feature of Express) * @default true + * @todo move to config * */ hasHeadMethod?: boolean; /** @@ -89,6 +92,7 @@ export class Integration extends IntegrationBase { public constructor({ routing, + config, brandHandling, variant = "client", clientClassName = "Client", @@ -154,6 +158,7 @@ export class Integration extends IntegrationBase { }; walkRouting({ routing, + config, onEndpoint: hasHeadMethod ? withHead(onEndpoint) : onEndpoint, }); this.#program.unshift(...this.#aliases.values()); diff --git a/express-zod-api/src/routing-walker.ts b/express-zod-api/src/routing-walker.ts index da5e566e5..95728fdbf 100644 --- a/express-zod-api/src/routing-walker.ts +++ b/express-zod-api/src/routing-walker.ts @@ -3,6 +3,7 @@ import { RoutingError } from "./errors.ts"; import { ClientMethod, isMethod, Method } from "./method.ts"; import { Routing } from "./routing.ts"; import { ServeStatic, StaticHandler } from "./serve-static.ts"; +import { CommonConfig } from "./config-type.ts"; export type OnEndpoint = ( method: M, @@ -20,14 +21,11 @@ export const withHead = interface RoutingWalkerParams { routing: Routing; + config: CommonConfig; onEndpoint: OnEndpoint; onStatic?: (path: string, handler: StaticHandler) => void; } -/** Checks that the given object has at least 2 keys that do exactly match Method */ -const hasMultipleMethodOnlyEntries = (subject: Routing) => - Object.keys(subject).filter(isMethod).length > 1; - /** @example delete /v1/user/retrieve —> [/v1/user/retrieve, delete] */ const detachMethod = (subject: string): [string, Method?] => { const [method, rest] = subject.trim().split(/ (.+)/, 2); @@ -39,8 +37,12 @@ const detachMethod = (subject: string): [string, Method?] => { const trimPath = (path: string) => path.trim().split("/").filter(Boolean).join("/"); -const processEntries = (subject: Routing, parent?: string) => { - const preferMethod = hasMultipleMethodOnlyEntries(subject); +const processEntries = ( + { methodLikeRouteBehavior = "method" }: CommonConfig, + subject: Routing, + parent?: string, +) => { + const preferMethod = methodLikeRouteBehavior === "method"; return Object.entries(subject).map<[string, Routing[string], Method?]>( ([_key, item]) => { const [segment, method] = @@ -83,10 +85,11 @@ const checkDuplicate = (method: Method, path: string, visited: Set) => { export const walkRouting = ({ routing, + config, onEndpoint, onStatic, }: RoutingWalkerParams) => { - const stack = processEntries(routing); + const stack = processEntries(config, routing); const visited = new Set(); while (stack.length) { const [path, element, explicitMethod] = stack.shift()!; @@ -107,7 +110,7 @@ export const walkRouting = ({ if (element instanceof ServeStatic) { if (onStatic) element.apply(path, onStatic); } else { - stack.unshift(...processEntries(element, path)); + stack.unshift(...processEntries(config, element, path)); } } } diff --git a/express-zod-api/src/routing.ts b/express-zod-api/src/routing.ts index d0d5a1dcf..8203eefa2 100644 --- a/express-zod-api/src/routing.ts +++ b/express-zod-api/src/routing.ts @@ -77,7 +77,7 @@ const collectSiblings = ({ familiar.set(path, new Map(config.cors ? [["options", value]] : [])); familiar.get(path)?.set(method, value); }; - walkRouting({ routing, onEndpoint, onStatic: app.use.bind(app) }); + walkRouting({ routing, config, onEndpoint, onStatic: app.use.bind(app) }); return familiar; }; diff --git a/express-zod-api/tests/integration.spec.ts b/express-zod-api/tests/integration.spec.ts index dcc267e8e..e166ad9c4 100644 --- a/express-zod-api/tests/integration.spec.ts +++ b/express-zod-api/tests/integration.spec.ts @@ -21,12 +21,14 @@ describe("Integration", () => { return recursive2; }, }); + const configMock = { cors: false }; test.each([recursive1, recursive2])( "Should support types variant and handle recursive schemas %#", (recursiveSchema) => { const client = new Integration({ variant: "types", + config: configMock, routing: { v1: { test: defaultEndpointsFactory @@ -48,6 +50,7 @@ describe("Integration", () => { test("Should treat optionals the same way as z.infer() by default", async () => { const client = new Integration({ + config: configMock, routing: { v1: { "test-with-dashes": defaultEndpointsFactory.build({ @@ -70,6 +73,7 @@ describe("Integration", () => { "Should support HEAD method by default %#", async (hasHeadMethod) => { const client = new Integration({ + config: configMock, hasHeadMethod, variant: "types", routing: { @@ -106,6 +110,7 @@ describe("Integration", () => { }), ); const client = new Integration({ + config: configMock, variant: "types", routing: { v1: { @@ -131,6 +136,7 @@ describe("Integration", () => { return next(schema); }; const client = new Integration({ + config: configMock, variant: "types", brandHandling: { CUSTOM: () => diff --git a/express-zod-api/tests/routing.spec.ts b/express-zod-api/tests/routing.spec.ts index a7b119dad..125f526c9 100644 --- a/express-zod-api/tests/routing.spec.ts +++ b/express-zod-api/tests/routing.spec.ts @@ -39,6 +39,7 @@ describe("Routing", () => { cors: true, startupLogo: false, wrongMethodBehavior, + methodLikeRouteBehavior: "route" as const, }; const factory = new EndpointsFactory(defaultResultHandler); const getEndpoint = factory.build({ From 5ba4cf07a18ed5f04ee483de1af92d0188d885cf Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 08:51:17 +0100 Subject: [PATCH 06/16] jsdoc: Add reference from Routing to CommonConfig.methodLikeRouteBehavior. --- express-zod-api/src/routing.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/express-zod-api/src/routing.ts b/express-zod-api/src/routing.ts index 8203eefa2..4e0f91ef4 100644 --- a/express-zod-api/src/routing.ts +++ b/express-zod-api/src/routing.ts @@ -16,7 +16,8 @@ import * as R from "ramda"; * @example { "v1/books/:bookId": getBookEndpoint } * @example { "get /v1/books/:bookId": getBookEndpoint } * @example { v1: { "patch /books/:bookId": changeBookEndpoint } } - * @example { dependsOnMethod: { "get /": retrieveEndpoint, "post /": createEndpoint } } + * @example { dependsOnMethod: { get: retrieveEndpoint, post: createEndpoint } } + * @see CommonConfig.methodLikeRouteBehavior * */ export interface Routing { [K: string]: Routing | AbstractEndpoint | ServeStatic; From 220ba5ae9412c5075caf93b12140c17ed511da65 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 08:54:40 +0100 Subject: [PATCH 07/16] Adjusting last routing tests. --- express-zod-api/tests/routing.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/express-zod-api/tests/routing.spec.ts b/express-zod-api/tests/routing.spec.ts index 125f526c9..da4b9a0d7 100644 --- a/express-zod-api/tests/routing.spec.ts +++ b/express-zod-api/tests/routing.spec.ts @@ -59,7 +59,7 @@ describe("Routing", () => { const routing: Routing = { v1: { user: { - get: getEndpoint, + get: getEndpoint, // should be treated as a route (methodLikeRouteBehavior: "route") set: postEndpoint, universal: getAndPostEndpoint, }, @@ -164,9 +164,9 @@ describe("Routing", () => { const routing: Routing = { v1: { user: { - "put /": putAndPatchEndpoint, - "patch /": putAndPatchEndpoint, - "post /": putAndPatchEndpoint, // intentional + put: putAndPatchEndpoint, + patch: putAndPatchEndpoint, + post: putAndPatchEndpoint, // intentional }, }, }; @@ -209,10 +209,10 @@ describe("Routing", () => { }); const routing: Routing = { hello: { - "get /": getEndpoint, - "post /": postEndpoint, - "put /": putAndPatchEndpoint, - "patch /": putAndPatchEndpoint, + get: getEndpoint, + post: postEndpoint, + put: putAndPatchEndpoint, + patch: putAndPatchEndpoint, }, }; const logger = makeLoggerMock(); From 599d06343eb53108b92ccc376038bc6231ed85f7 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 08:58:06 +0100 Subject: [PATCH 08/16] Changelog: preserve method only keys nested. --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7a46dae4..d99d28e48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### v26.0.0 -- `DependsOnMethod` removed: use flat syntax with explicit method and a slash; +- `DependsOnMethod` removed: use the nested methods instead; - `options` property renamed to `ctx` in argument of: - `Middleware::handler()`, - `ResultHandler::handler()`, @@ -16,8 +16,7 @@ const routing: Routing = { - "/v1/users": new DependsOnMethod({ + "/v1/users": { -- get: getUserEndpoint, -+ "get /": getUserEndpoint, + get: getUserEndpoint, - }).nest({ create: makeUserEndpoint - }), From 6e93e7216065c2b85a60911c130636c23248964b Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:29:09 +0100 Subject: [PATCH 09/16] Fix: calling another variant - path. --- express-zod-api/src/config-type.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/express-zod-api/src/config-type.ts b/express-zod-api/src/config-type.ts index 6e5d4683f..cd3d1c23c 100644 --- a/express-zod-api/src/config-type.ts +++ b/express-zod-api/src/config-type.ts @@ -50,10 +50,10 @@ export interface CommonConfig { * @desc How to treat Routing keys that look like methods (when assigned with an Endpoint) * @see Method * @example "method" — the key is treated as method of its parent path - * @example "route" — the key is treated as a nested route segment + * @example "path" — the key is treated as a nested path segment * @default "method" * */ - methodLikeRouteBehavior?: "method" | "route"; + methodLikeRouteBehavior?: "method" | "path"; /** * @desc The ResultHandler to use for handling routing, parsing and upload errors * @default defaultResultHandler From 6496de5d1413b9c10d7da3eb4ec0efc8aa8988ca Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:34:53 +0100 Subject: [PATCH 10/16] Changelog: describing methodLikeRouteBehavior. --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d99d28e48..db6ca19de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,12 @@ ### v26.0.0 -- `DependsOnMethod` removed: use the nested methods instead; +- `DependsOnMethod` removed: + - You can now specify methods as direct keys of an assigned object in `Routing`; + - That object can still contain nested paths as before; + - The keys matching lowercase HTTP methods are treated according to the new config setting `methodLikeRouteBehavior`: + - `method` — when assigned with an Endpoint the key is treated as method of its parent path (default); + - `path` — the key is always treated as a nested path segment; - `options` property renamed to `ctx` in argument of: - `Middleware::handler()`, - `ResultHandler::handler()`, From a494c798d5c44a58d4c749a7b0caf71cf25827e3 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:35:39 +0100 Subject: [PATCH 11/16] Readme: adjusting Routing article. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d41d8bca6..f5527eb63 100644 --- a/README.md +++ b/README.md @@ -307,10 +307,10 @@ const routing: Routing = { "delete /user/:id": deleteUserEndpoint, // method-based routing — /v1/account account: { - "get /": endpointA, - "delete /": endpointA, - "post /": endpointB, - "patch /": endpointB, + get: endpointA, + delete: endpointA, + post: endpointB, + patch: endpointB, }, }, // static file serving — /public serves files from ./assets From 7f5c6c4fae8e67f4441909ceba7048c6f0757cab Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:36:28 +0100 Subject: [PATCH 12/16] Readme: add config to Integration. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f5527eb63..5bc0de97b 100644 --- a/README.md +++ b/README.md @@ -1087,6 +1087,7 @@ import { Integration } from "express-zod-api"; const client = new Integration({ routing, + config, variant: "client", // <— optional, see also "types" for a DIY solution }); From 8dc0d0b0911646b5b8989091c7374c1e65ffeef5 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:37:38 +0100 Subject: [PATCH 13/16] Changelog: describing Integration requirements. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db6ca19de..0950096f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - `handler` of `EndpointsFactory::build()` argument, - `testMiddleware()`; - `EndpointsFactory::addOptions()` renamed to `addContext()`; +- The `Integration::contstructor()` argument object now requires `config` property, similar to `Documentation`; ```patch const routing: Routing = { From d4049cc0e265c795c13feec026d7435f255be488 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:38:43 +0100 Subject: [PATCH 14/16] Fix test. --- express-zod-api/tests/routing.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/express-zod-api/tests/routing.spec.ts b/express-zod-api/tests/routing.spec.ts index da4b9a0d7..91c99eb5a 100644 --- a/express-zod-api/tests/routing.spec.ts +++ b/express-zod-api/tests/routing.spec.ts @@ -39,7 +39,7 @@ describe("Routing", () => { cors: true, startupLogo: false, wrongMethodBehavior, - methodLikeRouteBehavior: "route" as const, + methodLikeRouteBehavior: "path" as const, }; const factory = new EndpointsFactory(defaultResultHandler); const getEndpoint = factory.build({ @@ -59,7 +59,7 @@ describe("Routing", () => { const routing: Routing = { v1: { user: { - get: getEndpoint, // should be treated as a route (methodLikeRouteBehavior: "route") + get: getEndpoint, // should be treated as a path set: postEndpoint, universal: getAndPostEndpoint, }, From 6825c71350118c170a95bd16970a4c6ce78ef5af Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:55:17 +0100 Subject: [PATCH 15/16] Adjusting migration and compat test. --- compat-test/migration.spec.ts | 2 +- migration/index.spec.ts | 14 +++++++------- migration/index.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compat-test/migration.spec.ts b/compat-test/migration.spec.ts index bcc9cc5f2..5a3844f28 100644 --- a/compat-test/migration.spec.ts +++ b/compat-test/migration.spec.ts @@ -4,6 +4,6 @@ import { describe, test, expect } from "vitest"; describe("Migration", () => { test("should fix the import", async () => { const fixed = await readFile("./sample.ts", "utf-8"); - expect(fixed).toBe(`const route = {\n"get /": someEndpoint,\n}\n`); + expect(fixed).toBe(`const route = {\nget: someEndpoint,\n}\n`); }); }); diff --git a/migration/index.spec.ts b/migration/index.spec.ts index d07020383..0f3f5fa24 100644 --- a/migration/index.spec.ts +++ b/migration/index.spec.ts @@ -23,7 +23,7 @@ describe("Migration", async () => { tester.run(ruleName, theRule, { valid: [ - `const routing = { "get /": someEndpoint };`, + `const routing = { get: someEndpoint };`, `factory.build({ handler: async ({ ctx }) => {} });`, `factory.addContext();`, `new Middleware({ handler: async ({ ctx }) => {} });`, @@ -34,7 +34,7 @@ describe("Migration", async () => { { name: "basic DependsOnMethod", code: `const routing = new DependsOnMethod({ get: someEndpoint });`, - output: `const routing = {\n"get /": someEndpoint,\n};`, + output: `const routing = {\nget: someEndpoint,\n};`, errors: [ { messageId: "change", @@ -49,7 +49,7 @@ describe("Migration", async () => { { name: "DependsOnMethod with literals", code: `const routing = new DependsOnMethod({ "get": someEndpoint });`, - output: `const routing = {\n"get /": someEndpoint,\n};`, + output: `const routing = {\nget: someEndpoint,\n};`, errors: [ { messageId: "change", @@ -64,7 +64,7 @@ describe("Migration", async () => { { name: "deprecated DependsOnMethod", code: `const routing = new DependsOnMethod({ get: someEndpoint }).deprecated();`, - output: `const routing = {\n"get /": someEndpoint.deprecated(),\n};`, + output: `const routing = {\nget: someEndpoint.deprecated(),\n};`, errors: [ { messageId: "change", @@ -79,7 +79,7 @@ describe("Migration", async () => { { name: "DependsOnMethod with nesting", code: `const routing = new DependsOnMethod({ get: someEndpoint }).nest({ some: otherEndpoint });`, - output: `const routing = {\n"get /": someEndpoint,\n"some": otherEndpoint,\n};`, + output: `const routing = {\nget: someEndpoint,\nsome: otherEndpoint,\n};`, errors: [ { messageId: "change", @@ -93,8 +93,8 @@ describe("Migration", async () => { }, { name: "DependsOnMethod both deprecated and with nesting", - code: `const routing = new DependsOnMethod({ get: someEndpoint }).deprecated().nest({ some: otherEndpoint });`, - output: `const routing = {\n"get /": someEndpoint.deprecated(),\n"some": otherEndpoint,\n};`, + code: `const routing = new DependsOnMethod({ get: someEndpoint }).deprecated().nest({ "get some": otherEndpoint });`, + output: `const routing = {\nget: someEndpoint.deprecated(),\n"get some": otherEndpoint,\n};`, errors: [ { messageId: "change", diff --git a/migration/index.ts b/migration/index.ts index acc88fa56..680b99c08 100644 --- a/migration/index.ts +++ b/migration/index.ts @@ -110,7 +110,7 @@ const theRule = ESLintUtils.RuleCreator.withoutDocs({ (feat?: "deprecated" | "nest") => (prop: TSESTree.ObjectLiteralElement) => isNamedProp(prop) - ? `"${getPropName(prop)}${feat === "nest" ? "" : " /"}": ${ctx.sourceCode.getText(prop.value)}${feat === "deprecated" ? ".deprecated()" : ""},` + ? `${feat === "nest" ? ctx.sourceCode.getText(prop.key) : getPropName(prop)}: ${ctx.sourceCode.getText(prop.value)}${feat === "deprecated" ? ".deprecated()" : ""},` : `${ctx.sourceCode.getText(prop)}, /** @todo migrate manually */`; const nextProps = argument.properties .map(makeMapper(isDeprecated ? "deprecated" : undefined)) From b3b74f1d023fb7b0ddb14d718873aa8c694dd7f4 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Sun, 9 Nov 2025 09:59:11 +0100 Subject: [PATCH 16/16] Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0950096f8..e68f3dcb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ - `handler` of `EndpointsFactory::build()` argument, - `testMiddleware()`; - `EndpointsFactory::addOptions()` renamed to `addContext()`; -- The `Integration::contstructor()` argument object now requires `config` property, similar to `Documentation`; +- The `Integration::constructor()` argument object now requires `config` property, similar to `Documentation`; ```patch const routing: Routing = {