diff --git a/packages/uuid.rocks/src/hash/hash.types.ts b/packages/uuid.rocks/src/hash/hash.types.ts new file mode 100644 index 0000000..3457e5b --- /dev/null +++ b/packages/uuid.rocks/src/hash/hash.types.ts @@ -0,0 +1,7 @@ +import type { z } from "zod"; + +import type { HashParamsSchema, HashSchema } from "./hash.validators"; + +export type HashParams = z.infer; + +export type Hash = z.infer; diff --git a/packages/uuid.rocks/src/hash/hash.validators.ts b/packages/uuid.rocks/src/hash/hash.validators.ts new file mode 100644 index 0000000..c16b630 --- /dev/null +++ b/packages/uuid.rocks/src/hash/hash.validators.ts @@ -0,0 +1,8 @@ +import { z } from "zod"; + +export const HashParamsSchema = z.object({ + algo: z.union([z.literal("md5"), z.literal("sha1"), z.literal("sha256")]), + data: z.string().min(1), +}); + +export const HashSchema = z.string(); diff --git a/packages/uuid.rocks/src/index.ts b/packages/uuid.rocks/src/index.ts index 568d0c9..584ac71 100644 --- a/packages/uuid.rocks/src/index.ts +++ b/packages/uuid.rocks/src/index.ts @@ -2,6 +2,7 @@ import { initUntypeable } from "untypeable"; import type { GlobalParams } from "./types"; import type { Emoji, EmojiJson } from "./emoji/emoji.types"; +import type { Hash, HashParams } from "./hash/hash.types"; import type { Json, JsonBulk, @@ -31,6 +32,9 @@ const router = u.router({ /** Gets single uuid with JSON output */ "/api/uuid/emoji?json": u.output(), + /** This api will hash data in the url or the body. */ + "/api/hash/:algo/:data": u.input().output(), + /** Responds with ‘pong’ or ‘ping’ */ "/api/ping": u.output(), diff --git a/packages/uuid.rocks/src/runtimeSafe.ts b/packages/uuid.rocks/src/runtimeSafe.ts index 5fd3adc..908567b 100644 --- a/packages/uuid.rocks/src/runtimeSafe.ts +++ b/packages/uuid.rocks/src/runtimeSafe.ts @@ -2,6 +2,7 @@ import { initUntypeable } from "untypeable"; import { GlobalParamsSchema } from "./_shared/_shared.validators"; import { EmojiSchema, EmojiJsonSchema } from "./emoji/emoji.validators"; +import { HashParamsSchema, HashSchema } from "./hash/hash.validators"; import { JsonBulkParamsSchema, JsonBulkSchema, @@ -34,6 +35,9 @@ export const uuidRocksSafeRouter = u.router({ /** Gets single uuid with JSON output */ "/api/uuid/emoji?json": u.output(EmojiJsonSchema), + /** This api will hash data in the url or the body. */ + "/api/hash/:algo/:data": u.input(HashParamsSchema).output(HashSchema), + /** Responds with ‘pong’ or ‘ping’ */ "/api/ping": u.output(PingPongSchema), diff --git a/packages/uuid.rocks/src/types.ts b/packages/uuid.rocks/src/types.ts index c6e4a99..5ab843b 100644 --- a/packages/uuid.rocks/src/types.ts +++ b/packages/uuid.rocks/src/types.ts @@ -1,5 +1,6 @@ export * from "./_shared/_shared.types"; export * from "./emoji/emoji.types"; +export * from "./hash/hash.types"; export * from "./json/json.types"; export * from "./nanoid/nanoid.types"; export * from "./ping-pong/ping-pong.types"; diff --git a/packages/uuid.rocks/src/zod.ts b/packages/uuid.rocks/src/zod.ts index 01a7eac..1748c43 100644 --- a/packages/uuid.rocks/src/zod.ts +++ b/packages/uuid.rocks/src/zod.ts @@ -1,5 +1,6 @@ export * from "./_shared/_shared.validators"; export * from "./emoji/emoji.validators"; +export * from "./hash/hash.validators"; export * from "./json/json.validators"; export * from "./nanoid/nanoid.validators"; export * from "./ping-pong/ping-pong.validators"; diff --git a/packages/uuid.rocks/tests/hash.test.ts b/packages/uuid.rocks/tests/hash.test.ts new file mode 100644 index 0000000..c311236 --- /dev/null +++ b/packages/uuid.rocks/tests/hash.test.ts @@ -0,0 +1,48 @@ +import { describe, it, expect } from "vitest"; + +import { HashSchema } from "../src/zod"; +import { useTestClient } from "./_client"; + +describe.concurrent("uuid.rocks - hash", () => { + it("GET - /api/hash/md5/Hello World", async () => { + const client = useTestClient({ json: false }); + + const hash = await client("/api/hash/:algo/:data", { + algo: "md5", + data: "Hello World", + }); + + expect(hash).toBeDefined(); + expect(hash).toBeTypeOf("string"); + + expect(HashSchema.safeParse(hash).success).toBe(true); + }); + + it("GET - /api/hash/sha1/Hello World", async () => { + const client = useTestClient({ json: false }); + + const hash = await client("/api/hash/:algo/:data", { + algo: "sha1", + data: "Hello World", + }); + + expect(hash).toBeDefined(); + expect(hash).toBeTypeOf("string"); + + expect(HashSchema.safeParse(hash).success).toBe(true); + }); + + it("GET - /api/hash/sha256/Hello World", async () => { + const client = useTestClient({ json: false }); + + const hash = await client("/api/hash/:algo/:data", { + algo: "sha256", + data: "Hello World", + }); + + expect(hash).toBeDefined(); + expect(hash).toBeTypeOf("string"); + + expect(HashSchema.safeParse(hash).success).toBe(true); + }); +});