From 64fd349eadcd7693635912d3bf042b7f4c2d6506 Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 15:27:36 +0000 Subject: [PATCH 1/7] feat(37): suggest params path --- scripts/core/builders/route/checker.ts | 1 - scripts/core/builders/route/extract.ts | 22 ++++++++++++++++++- scripts/core/steps/extract.ts | 2 ++ .../core/types/extractParamsKeyFromPath.ts | 5 +++++ scripts/core/types/index.ts | 1 + .../route/default/index.test.ts | 10 ++++----- .../steps/defaults/checkerStep.test.ts | 14 ++++++------ .../steps/defaults/cutStep.test.ts | 2 +- .../steps/defaults/extractStep.test.ts | 4 ++-- .../steps/defaults/handlerStep.test.ts | 2 +- .../aggregateStepContract.test.ts | 2 +- .../aggregateStepContract.test.ts | 2 +- 12 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 scripts/core/types/extractParamsKeyFromPath.ts diff --git a/scripts/core/builders/route/checker.ts b/scripts/core/builders/route/checker.ts index e050cd6..6d694d1 100644 --- a/scripts/core/builders/route/checker.ts +++ b/scripts/core/builders/route/checker.ts @@ -5,7 +5,6 @@ import { type O, type MaybeArray, type NeverCoalescing, type FixDeepFunctionInfe import { routeBuilderHandler } from "./builder"; import { type GetCheckerInput, type Checker, type GetCheckerResult, type GetCheckerOptions } from "@core/checker"; import { type ClientErrorResponseCode, type ResponseContract } from "@core/response"; -import { type Request } from "@core/request"; import { type Metadata } from "@core/metadata"; declare module "./builder" { diff --git a/scripts/core/builders/route/extract.ts b/scripts/core/builders/route/extract.ts index 6fb31f3..400e49b 100644 --- a/scripts/core/builders/route/extract.ts +++ b/scripts/core/builders/route/extract.ts @@ -6,6 +6,23 @@ import { routeBuilderHandler } from "./builder"; import { type ClientErrorResponseCode, type ResponseContract } from "@core/response"; import { type Request } from "@core/request"; import { type Metadata } from "@core/metadata"; +import { type ExtractParamsKeyFromPath } from "@core/types"; + +type HandleParamsInference< + GenericShape extends ExtractShape, + GenericPath extends string, +> = ( + & GenericShape + & { + params?: ExtractParamsKeyFromPath extends infer InferredKey extends string + ? ( + & Partial> + & Record + & Record, never> + ) + : {}; + } +); declare module "./builder" { interface RouteBuilder< @@ -20,7 +37,10 @@ declare module "./builder" { ) = never, const GenericMetadata extends readonly Metadata[] = readonly [], >( - shape: GenericShape, + shape: HandleParamsInference< + GenericShape, + GenericDefinition["paths"][number] + >, responseContract?: GenericResponseContract, ...metadata: GenericMetadata, ): RouteBuilder< diff --git a/scripts/core/steps/extract.ts b/scripts/core/steps/extract.ts index 741e8cb..7ea86bb 100644 --- a/scripts/core/steps/extract.ts +++ b/scripts/core/steps/extract.ts @@ -28,6 +28,7 @@ export type ExtractShape< | DisabledExtractKeys | "body" | "bodyReader" + | "params" | symbol >, | DP.DataParser @@ -38,6 +39,7 @@ export type ExtractShape< | DP.DataParser | Record ); + params: Record; } >; diff --git a/scripts/core/types/extractParamsKeyFromPath.ts b/scripts/core/types/extractParamsKeyFromPath.ts new file mode 100644 index 0000000..5276a33 --- /dev/null +++ b/scripts/core/types/extractParamsKeyFromPath.ts @@ -0,0 +1,5 @@ +export type ExtractParamsKeyFromPath< + GenericPath extends string = string, +> = GenericPath extends `${string}{${infer InferredParams}}${infer InferredRest}` + ? InferredParams | ExtractParamsKeyFromPath + : never; diff --git a/scripts/core/types/index.ts b/scripts/core/types/index.ts index 3220226..63c64ea 100644 --- a/scripts/core/types/index.ts +++ b/scripts/core/types/index.ts @@ -2,3 +2,4 @@ export * from "./environment"; export * from "./forbiddenBigintDataParser"; export * from "./httpServerParams"; export * from "./hosts"; +export * from "./extractParamsKeyFromPath"; diff --git a/tests/core/functionsBuilders/route/default/index.test.ts b/tests/core/functionsBuilders/route/default/index.test.ts index e3021b7..3eaf399 100644 --- a/tests/core/functionsBuilders/route/default/index.test.ts +++ b/tests/core/functionsBuilders/route/default/index.test.ts @@ -11,7 +11,7 @@ describe("route function builder", () => { }); it("failed build step", async() => { - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), @@ -28,7 +28,7 @@ describe("route function builder", () => { const route = usePreflightBuilder() .exec(process) - .useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + .useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), @@ -49,7 +49,7 @@ describe("route function builder", () => { const route = usePreflightBuilder() .exec(process) - .useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + .useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), @@ -90,7 +90,7 @@ describe("route function builder", () => { const route = usePreflightBuilder() .exec(process) - .useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + .useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), @@ -122,7 +122,7 @@ describe("route function builder", () => { }); it("route default response", async() => { - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.empty()), diff --git a/tests/core/functionsBuilders/steps/defaults/checkerStep.test.ts b/tests/core/functionsBuilders/steps/defaults/checkerStep.test.ts index 8acd9c8..91cd71b 100644 --- a/tests/core/functionsBuilders/steps/defaults/checkerStep.test.ts +++ b/tests/core/functionsBuilders/steps/defaults/checkerStep.test.ts @@ -18,7 +18,7 @@ describe("checker step function builder", () => { : output("wrongResult", null), ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .check( checker, @@ -65,7 +65,7 @@ describe("checker step function builder", () => { : output("wrongResult", null), ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .check( checker, @@ -113,7 +113,7 @@ describe("checker step function builder", () => { : output("wrongResult", null), ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .check( checker, @@ -161,7 +161,7 @@ describe("checker step function builder", () => { : output("wrongResult", null), ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .check( checker, @@ -212,7 +212,7 @@ describe("checker step function builder", () => { : output("wrongResult", null), ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .check( checker, @@ -263,7 +263,7 @@ describe("checker step function builder", () => { ), ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .check( checker, @@ -318,7 +318,7 @@ describe("checker step function builder", () => { }, ); - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .presetCheck( presetChecker, diff --git a/tests/core/functionsBuilders/steps/defaults/cutStep.test.ts b/tests/core/functionsBuilders/steps/defaults/cutStep.test.ts index 54ae2bd..f4b2d1f 100644 --- a/tests/core/functionsBuilders/steps/defaults/cutStep.test.ts +++ b/tests/core/functionsBuilders/steps/defaults/cutStep.test.ts @@ -11,7 +11,7 @@ describe("cut step function builder", () => { }); it("response from cut", async() => { - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .cut( [ResponseContract.ok("goodCut", DPE.string().transform(async(value) => Promise.resolve(value)))], diff --git a/tests/core/functionsBuilders/steps/defaults/extractStep.test.ts b/tests/core/functionsBuilders/steps/defaults/extractStep.test.ts index bac814b..7813919 100644 --- a/tests/core/functionsBuilders/steps/defaults/extractStep.test.ts +++ b/tests/core/functionsBuilders/steps/defaults/extractStep.test.ts @@ -11,7 +11,7 @@ describe("extract step function builder", () => { }); it("sub extract value from params", async() => { - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), @@ -112,7 +112,7 @@ describe("extract step function builder", () => { }); it("error sub extract", async() => { - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), diff --git a/tests/core/functionsBuilders/steps/defaults/handlerStep.test.ts b/tests/core/functionsBuilders/steps/defaults/handlerStep.test.ts index e13e7e5..7c386ad 100644 --- a/tests/core/functionsBuilders/steps/defaults/handlerStep.test.ts +++ b/tests/core/functionsBuilders/steps/defaults/handlerStep.test.ts @@ -11,7 +11,7 @@ describe("handler step function builder", () => { }); it("response from handler", async() => { - const route = useRouteBuilder("GET", "/test", { hooks: [{ afterSendResponse: spyResponse }] }) + const route = useRouteBuilder("GET", "/test/{value}", { hooks: [{ afterSendResponse: spyResponse }] }) .extract({ params: { value: DPE.string() } }) .handler( ResponseContract.ok("good", DPE.string()), diff --git a/tests/plugins/codeGenerator/aggregateStepContract.test.ts b/tests/plugins/codeGenerator/aggregateStepContract.test.ts index a763c4e..d25f477 100644 --- a/tests/plugins/codeGenerator/aggregateStepContract.test.ts +++ b/tests/plugins/codeGenerator/aggregateStepContract.test.ts @@ -25,7 +25,7 @@ describe("stepsToDataParser", () => { .extract({ query: { ignoredQuery: DPE.string() } }) .exports(); - const route = useRouteBuilder("GET", "/test") + const route = useRouteBuilder("GET", "/test/{ignoredParams}") .extract({ headers: DPE.object({ header3: DPE.string(), diff --git a/tests/plugins/openApiGenerator/aggregateStepContract.test.ts b/tests/plugins/openApiGenerator/aggregateStepContract.test.ts index 867c61f..30014e6 100644 --- a/tests/plugins/openApiGenerator/aggregateStepContract.test.ts +++ b/tests/plugins/openApiGenerator/aggregateStepContract.test.ts @@ -25,7 +25,7 @@ describe("aggregateStepContract", () => { .extract({ query: { ignoredQuery: DPE.string() } }) .exports(); - const route = useRouteBuilder("GET", "/test") + const route = useRouteBuilder("GET", "/test/{ignoredParams}") .extract({ headers: DPE.object({ header3: DPE.string(), From ef278e327863ec9c4091fb4305f53a96846d4252 Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 16:05:32 +0000 Subject: [PATCH 2/7] feat(37): test buffer size in pipeline --- scripts/interfaces/node/bodyReaders/formData/error.ts | 2 +- .../node/bodyReaders/formData/readRequestFormData.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/interfaces/node/bodyReaders/formData/error.ts b/scripts/interfaces/node/bodyReaders/formData/error.ts index dc3590c..396b40f 100644 --- a/scripts/interfaces/node/bodyReaders/formData/error.ts +++ b/scripts/interfaces/node/bodyReaders/formData/error.ts @@ -9,6 +9,6 @@ export class BodyParseFormDataError extends kindHeritage( public constructor( public information: string, ) { - super({}, [`Body parse form date error: ${information}`]); + super({}, [`Body parse form data error: ${information}`]); } } diff --git a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts index 6cd43f2..baf9cf9 100644 --- a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts +++ b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts @@ -191,9 +191,9 @@ export async function readRequestFormData< if (!(chunk instanceof Buffer)) { return await treatError(new BodyParseWrongChunkReceived("Buffer.", chunk)); } - + console.log("chunk.length", chunk.length); currentBuffer = Buffer.concat([currentBuffer, chunk]); - + console.log("currentBuffer.length", currentBuffer.length); if (currentBuffer.length > params.maxBufferSize) { return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); } From ca707765fe9890293624b065069186f6e04fce2f Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 16:21:47 +0000 Subject: [PATCH 3/7] feat(37): remove console log --- .../node/bodyReaders/formData/readRequestFormData.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts index baf9cf9..6cd43f2 100644 --- a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts +++ b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts @@ -191,9 +191,9 @@ export async function readRequestFormData< if (!(chunk instanceof Buffer)) { return await treatError(new BodyParseWrongChunkReceived("Buffer.", chunk)); } - console.log("chunk.length", chunk.length); + currentBuffer = Buffer.concat([currentBuffer, chunk]); - console.log("currentBuffer.length", currentBuffer.length); + if (currentBuffer.length > params.maxBufferSize) { return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); } From a2071f7690a4ccdc99753ac60b07993b537568bd Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 16:29:50 +0000 Subject: [PATCH 4/7] feat(37): deplace buffer size condition --- .../node/bodyReaders/formData/readRequestFormData.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts index 6cd43f2..a92adb3 100644 --- a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts +++ b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts @@ -192,12 +192,12 @@ export async function readRequestFormData< return await treatError(new BodyParseWrongChunkReceived("Buffer.", chunk)); } - currentBuffer = Buffer.concat([currentBuffer, chunk]); - if (currentBuffer.length > params.maxBufferSize) { return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); } + currentBuffer = Buffer.concat([currentBuffer, chunk]); + while (true) { const startPartIndex = currentBuffer.indexOf(startPart); const endHeaderPartIndex = currentBuffer.indexOf(endHeaderPart); From 05439922022b0421fbf57a15c63d0f5d4f8a9a74 Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 16:50:25 +0000 Subject: [PATCH 5/7] feat(37): fix test buffer size --- .../node/bodyReaders/formData/readRequestFormData.ts | 8 ++++---- .../node/bodyReader/formData/readRequestFormData.test.ts | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts index a92adb3..1b8194e 100644 --- a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts +++ b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts @@ -192,10 +192,6 @@ export async function readRequestFormData< return await treatError(new BodyParseWrongChunkReceived("Buffer.", chunk)); } - if (currentBuffer.length > params.maxBufferSize) { - return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); - } - currentBuffer = Buffer.concat([currentBuffer, chunk]); while (true) { @@ -244,6 +240,10 @@ export async function readRequestFormData< // check if buffer contain only end of header part return await treatError(new BodyParseFormDataError("Wrong content.")); } + + if (currentBuffer.length > params.maxBufferSize) { + return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); + } } } diff --git a/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts b/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts index 96341c8..7944164 100644 --- a/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts +++ b/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts @@ -334,7 +334,12 @@ describe("readRequestFormData", () => { headers: { "content-type": contentType, }, - bodyChunks: [Buffer.from("A".repeat(20))], + bodyChunks: [ + Buffer.from(`--${boundary}\r\n`), + Buffer.from("Content-Disposition:"), + Buffer.from(" form-data; name=\"field\"\r\n\r\n"), + + ], }, }, }); From b570228011c143bd2e95b565cd902a0c37f176dc Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 17:27:28 +0000 Subject: [PATCH 6/7] feat(37): fix test buffer size --- .../node/bodyReaders/formData/readRequestFormData.ts | 8 ++++---- .../node/bodyReader/formData/readRequestFormData.test.ts | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts index 1b8194e..a92adb3 100644 --- a/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts +++ b/scripts/interfaces/node/bodyReaders/formData/readRequestFormData.ts @@ -192,6 +192,10 @@ export async function readRequestFormData< return await treatError(new BodyParseWrongChunkReceived("Buffer.", chunk)); } + if (currentBuffer.length > params.maxBufferSize) { + return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); + } + currentBuffer = Buffer.concat([currentBuffer, chunk]); while (true) { @@ -240,10 +244,6 @@ export async function readRequestFormData< // check if buffer contain only end of header part return await treatError(new BodyParseFormDataError("Wrong content.")); } - - if (currentBuffer.length > params.maxBufferSize) { - return await treatError(new BodyParseFormDataError("Buffer size exceeds limit.")); - } } } diff --git a/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts b/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts index 7944164..aba1943 100644 --- a/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts +++ b/tests/interfaces/node/bodyReader/formData/readRequestFormData.test.ts @@ -335,10 +335,9 @@ describe("readRequestFormData", () => { "content-type": contentType, }, bodyChunks: [ - Buffer.from(`--${boundary}\r\n`), - Buffer.from("Content-Disposition:"), - Buffer.from(" form-data; name=\"field\"\r\n\r\n"), - + Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="field"`), + Buffer.from("A".repeat(20)), + Buffer.from("\r\n\r\n"), ], }, }, @@ -363,7 +362,7 @@ describe("readRequestFormData", () => { ); expect(E.hasInformation(result, "error")).toBe(true); - expect(unwrap(result)).toBeInstanceOf(BodyParseFormDataError); + expect(unwrap(result)).toStrictEqual(new BodyParseFormDataError("Buffer size exceeds limit.")); }); it("returns error for invalid header part", async() => { From 6e80dc8309aba2067ea14eb76f909b903d7f31e2 Mon Sep 17 00:00:00 2001 From: mathcovax Date: Tue, 5 May 2026 18:23:30 +0000 Subject: [PATCH 7/7] fix(37): update utils --- package-lock.json | 8 ++-- package.json | 2 +- scripts/core/clean/constraint.ts | 52 +++++++++------------ scripts/core/clean/constraintsSet.ts | 70 +++++++++------------------- scripts/core/clean/entity.ts | 13 ++++-- scripts/core/clean/newType.ts | 53 ++++++++++----------- scripts/core/clean/primitive.ts | 42 ++++++++++------- 7 files changed, 107 insertions(+), 133 deletions(-) diff --git a/package-lock.json b/package-lock.json index 244aa46..fa69da4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "peerDependencies": { "@duplojs/data-parser-tools": ">=0.2.9 <1.0.0", "@duplojs/server-utils": ">=0.2.2 <1.0.0", - "@duplojs/utils": ">=1.5.15 <2.0.0" + "@duplojs/utils": ">=1.7.0 <2.0.0" } }, "docs": { @@ -1619,9 +1619,9 @@ } }, "node_modules/@duplojs/utils": { - "version": "1.5.15", - "resolved": "https://registry.npmjs.org/@duplojs/utils/-/utils-1.5.15.tgz", - "integrity": "sha512-bhM//4vTj8NkSD8iuNskH2XJny648jAfh1uXf/Wqy3R5uzAkVcEGpXbVQa5Z6AJzmqWpXckFaMHsZHM4+2e2YA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@duplojs/utils/-/utils-1.7.0.tgz", + "integrity": "sha512-LBb/ZpBh7OGJbGYKx6cvq6dmPXTt8EH6FOpPZUBgEcerb2P4boW6gMX/MkGnJ4maR921V3KGZNiIeBA+uK5mWw==", "license": "MIT", "peer": true, "workspaces": [ diff --git a/package.json b/package.json index 611f984..7d29380 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "peerDependencies": { "@duplojs/data-parser-tools": ">=0.2.9 <1.0.0", "@duplojs/server-utils": ">=0.2.2 <1.0.0", - "@duplojs/utils": ">=1.5.15 <2.0.0" + "@duplojs/utils": ">=1.7.0 <2.0.0" }, "devDependencies": { "@commitlint/cli": "19.8.1", diff --git a/scripts/core/clean/constraint.ts b/scripts/core/clean/constraint.ts index e6b2fc6..8ad7130 100644 --- a/scripts/core/clean/constraint.ts +++ b/scripts/core/clean/constraint.ts @@ -1,14 +1,18 @@ -import { type DP, DPE, keyWrappedValue } from "@duplojs/utils"; -import { type ConstrainedType, constrainedTypeKind, createConstraint, type EligiblePrimitive } from "@duplojs/utils/clean"; +import { type DP, DPE, C } from "@duplojs/utils"; +import "@duplojs/utils/clean"; + +interface ToExtractParserParams { + coerce?: boolean; +} declare module "@duplojs/utils/clean" { interface ConstraintHandler< GenericName extends string = string, - GenericPrimitiveValue extends EligiblePrimitive = EligiblePrimitive, + GenericPrimitiveValue extends C.EligiblePrimitive = C.EligiblePrimitive, GenericCheckers extends readonly DP.DataParserChecker[] = readonly DP.DataParserChecker[], > { - toExtractParser(): DPE.ContractExtended< - ConstrainedType< + toExtractParser(params?: ToExtractParserParams): DPE.ContractExtended< + C.ConstrainedType< GenericName, GenericPrimitiveValue >, @@ -19,39 +23,27 @@ declare module "@duplojs/utils/clean" { } } -createConstraint.overrideHandler.setMethod( +C.createConstraint.overrideHandler.setMethod( "toExtractParser", - (self) => { - const dataParserWithCheckers = self - .primitiveHandler - .dataParser - .addChecker(...self.checkers as never); - - const valueContainer = constrainedTypeKind.setTo( - {}, - { [self.name]: null }, - ); - - const dataParser = DPE.transform( - dataParserWithCheckers, - (input) => ({ - ...valueContainer, - [keyWrappedValue]: input, - }) as never, + (self, params) => { + const innerDataParser = C.toMapDataParser( + self, + params, ); - return dataParser; + return DPE.lazy( + () => innerDataParser, + ) as never; }, ); -createConstraint.overrideHandler.setMethod( +C.createConstraint.overrideHandler.setMethod( "toEndpointSchema", (self) => { - const dataParser = self - .primitiveHandler - .dataParser - .addChecker(...self.checkers as never) as never; + const innerDataParser = self.internal.dataParser; - return DPE.lazy(() => dataParser); + return DPE.lazy( + () => innerDataParser, + ) as never; }, ); diff --git a/scripts/core/clean/constraintsSet.ts b/scripts/core/clean/constraintsSet.ts index 73354cf..ec18977 100644 --- a/scripts/core/clean/constraintsSet.ts +++ b/scripts/core/clean/constraintsSet.ts @@ -1,18 +1,22 @@ -import { A, DPE, keyWrappedValue, O, pipe, type UnionToIntersection } from "@duplojs/utils"; -import { constrainedTypeKind, createConstraintsSet, type EligiblePrimitive, type GetConstraint, type Primitive } from "@duplojs/utils/clean"; +import { DPE, type UnionToIntersection, C } from "@duplojs/utils"; +import "@duplojs/utils/clean"; + +interface ToExtractParserParams { + coerce?: boolean; +} declare module "@duplojs/utils/clean" { interface ConstraintsSetHandler< - GenericPrimitiveValue extends EligiblePrimitive = EligiblePrimitive, + GenericPrimitiveValue extends C.EligiblePrimitive = C.EligiblePrimitive, GenericConstraintsHandler extends readonly ConstraintHandler[] = readonly [], > { - toExtractParser(): DPE.ContractExtended< + toExtractParser(params?: ToExtractParserParams): DPE.ContractExtended< ( - & Primitive + & C.Primitive & UnionToIntersection< GenericConstraintsHandler[number] extends infer InferredConstraint ? InferredConstraint extends ConstraintHandler - ? GetConstraint + ? C.GetConstraint : never : never > @@ -24,57 +28,27 @@ declare module "@duplojs/utils/clean" { } } -createConstraintsSet.overrideHandler.setMethod( +C.createConstraintsSet.overrideHandler.setMethod( "toExtractParser", - (self) => { - const checkers = A.flatMap( - self.constraints, - ({ checkers }) => checkers, - ); - - const dataParserWithCheckers = self - .primitiveHandler - .dataParser - .addChecker(...checkers as never); - - const constraintsKindValue = pipe( - self.constraints, - A.map(({ name }) => O.entry(name, null)), - O.fromEntries, - ); - - const valueContainer = constrainedTypeKind.setTo( - {}, - constraintsKindValue, - ); - - const dataParser = DPE.transform( - dataParserWithCheckers, - (input) => ({ - ...valueContainer, - [keyWrappedValue]: input, - }) as never, + (self, params) => { + const innerDataParser = C.toMapDataParser( + self, + params, ); - return dataParser; + return DPE.lazy( + () => innerDataParser, + ) as never; }, ); -createConstraintsSet.overrideHandler.setMethod( +C.createConstraintsSet.overrideHandler.setMethod( "toEndpointSchema", (self) => { - const checkers = A.flatMap( - self.constraints, - ({ checkers }) => checkers, - ); - - const dataParserWithCheckers = self - .primitiveHandler - .dataParser - .addChecker(...checkers as never) as never; + const innerDataParser = self.internal.dataParser; return DPE.lazy( - () => dataParserWithCheckers, - ); + () => innerDataParser, + ) as never; }, ); diff --git a/scripts/core/clean/entity.ts b/scripts/core/clean/entity.ts index a8ee41a..9bb2537 100644 --- a/scripts/core/clean/entity.ts +++ b/scripts/core/clean/entity.ts @@ -1,6 +1,10 @@ import { DP, DPE, type IsEqual, type SimplifyTopLevel, type IsExtends, pipe, O, A, C, type MaybeArray } from "@duplojs/utils"; import "@duplojs/utils/clean"; +interface ToExtractParserParams { + coerce?: boolean; +} + interface ToEndpointSchemaParams { addEntityName?: boolean | string; } @@ -16,7 +20,8 @@ declare module "@duplojs/utils/clean" { const GenericKey extends MaybeArray = readonly (keyof GenericEntityProperties)[], >( - keys?: GenericKey + keys?: GenericKey, + params?: ToExtractParserParams ): GenericKey extends readonly any[] ? ReturnType< typeof DPE.object< @@ -67,11 +72,11 @@ declare module "@duplojs/utils/clean" { C.createEntity.overrideHandler.setMethod( "toExtractParser", - (self, keys) => { + (self, keys, params) => { if (typeof keys === "string") { return C.entityPropertyDefinitionToDataParser( self.propertiesDefinition[keys]!, - (newTypeHandler) => newTypeHandler.toExtractParser(), + (newTypeHandler) => newTypeHandler.toExtractParser(params), ); } @@ -84,7 +89,7 @@ C.createEntity.overrideHandler.setMethod( key, C.entityPropertyDefinitionToDataParser( value, - (newTypeHandler) => newTypeHandler.toExtractParser(), + (newTypeHandler) => newTypeHandler.toExtractParser(params), ), ), ), diff --git a/scripts/core/clean/newType.ts b/scripts/core/clean/newType.ts index a776d36..3e8dd30 100644 --- a/scripts/core/clean/newType.ts +++ b/scripts/core/clean/newType.ts @@ -1,5 +1,9 @@ -import { A, DPE, keyWrappedValue, O, pipe } from "@duplojs/utils"; -import { constrainedTypeKind, createNewType, type NewType, newTypeKind } from "@duplojs/utils/clean"; +import { C, DPE } from "@duplojs/utils"; +import "@duplojs/utils/clean"; + +interface ToExtractParserParams { + coerce?: boolean; +} declare module "@duplojs/utils/clean" { interface NewTypeHandler< @@ -8,8 +12,8 @@ declare module "@duplojs/utils/clean" { GenericConstraintsHandler extends readonly ConstraintHandler[] = readonly ConstraintHandler[], GenericInput extends unknown = unknown, > { - toExtractParser(): DPE.ContractExtended< - NewType< + toExtractParser(params?: ToExtractParserParams): DPE.ContractExtended< + C.NewType< GenericName, GenericValue, GenericConstraintsHandler[number]["name"] @@ -21,36 +25,27 @@ declare module "@duplojs/utils/clean" { } } -createNewType.overrideHandler.setMethod( +C.createNewType.overrideHandler.setMethod( "toExtractParser", - (self) => { - const constraintsKindValue = pipe( - self.constraints, - A.map(({ name }) => O.entry(name, null)), - O.fromEntries, - ); - - const valueContainer = newTypeKind.setTo( - constrainedTypeKind.setTo( - {}, - constraintsKindValue, - ), - self.name, + (self, params) => { + const innerDataParser = C.toMapDataParser( + self, + params, ); - const dataParser = DPE.transform( - self.dataParser, - (input) => ({ - ...valueContainer, - [keyWrappedValue]: input, - }) as never, - ); - - return dataParser; + return DPE.lazy( + () => innerDataParser, + ) as never; }, ); -createNewType.overrideHandler.setMethod( +C.createNewType.overrideHandler.setMethod( "toEndpointSchema", - (self) => DPE.lazy(() => self.dataParser), + (self) => { + const innerDataParser = self.internal.dataParser; + + return DPE.lazy( + () => innerDataParser, + ) as never; + }, ); diff --git a/scripts/core/clean/primitive.ts b/scripts/core/clean/primitive.ts index c31b18c..a28e7e4 100644 --- a/scripts/core/clean/primitive.ts +++ b/scripts/core/clean/primitive.ts @@ -1,12 +1,16 @@ -import { DPE, keyWrappedValue } from "@duplojs/utils"; -import { createPrimitive, type EligiblePrimitive, type Primitive } from "@duplojs/utils/clean"; +import { DPE, C } from "@duplojs/utils"; +import "@duplojs/utils/clean"; + +interface ToExtractParserParams { + coerce?: boolean; +} declare module "@duplojs/utils/clean" { interface PrimitiveHandler< - GenericValue extends EligiblePrimitive = EligiblePrimitive, + GenericValue extends C.EligiblePrimitive = C.EligiblePrimitive, > { - toExtractParser(): DPE.ContractExtended< - Primitive, + toExtractParser(params?: ToExtractParserParams): DPE.ContractExtended< + C.Primitive, unknown >; @@ -17,23 +21,27 @@ declare module "@duplojs/utils/clean" { } } -createPrimitive.overrideHandler.setMethod( +C.createPrimitive.overrideHandler.setMethod( "toExtractParser", - (self) => { - const dataParser = DPE.transform( - self.dataParser, - (input) => ({ - [keyWrappedValue]: input, - }) as never, + (self, params) => { + const innerDataParser = C.toMapDataParser( + self, + params, ); - return dataParser; + return DPE.lazy( + () => innerDataParser, + ) as never; }, ); -createPrimitive.overrideHandler.setMethod( +C.createPrimitive.overrideHandler.setMethod( "toEndpointSchema", - (self) => DPE.lazy( - () => self.dataParser, - ), + (self) => { + const innerDataParser = self.dataParser; + + return DPE.lazy( + () => innerDataParser, + ) as never; + }, );