diff --git a/packages/uuid.rocks/src/index.ts b/packages/uuid.rocks/src/index.ts index 584ac71..6a93802 100644 --- a/packages/uuid.rocks/src/index.ts +++ b/packages/uuid.rocks/src/index.ts @@ -3,6 +3,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 { Ip, IpJson } from "./ip/ip.types"; import type { Json, JsonBulk, @@ -35,6 +36,12 @@ const router = u.router({ /** This api will hash data in the url or the body. */ "/api/hash/:algo/:data": u.input().output(), + /** This api will return what IP you’re connecting from */ + "/api/ip": u.output(), + + /** This api will return what IP you’re connecting from in JSON format with additional information */ + "/api/ip?json": u.output(), + /** Responds with ‘pong’ or ‘ping’ */ "/api/ping": u.output(), diff --git a/packages/uuid.rocks/src/ip/ip.types.ts b/packages/uuid.rocks/src/ip/ip.types.ts new file mode 100644 index 0000000..272d58a --- /dev/null +++ b/packages/uuid.rocks/src/ip/ip.types.ts @@ -0,0 +1,7 @@ +import type { z } from "zod"; + +import type { IpJsonSchema, IpSchema } from "./ip.validators"; + +export type Ip = z.infer; + +export type IpJson = z.infer; diff --git a/packages/uuid.rocks/src/ip/ip.validators.ts b/packages/uuid.rocks/src/ip/ip.validators.ts new file mode 100644 index 0000000..b695421 --- /dev/null +++ b/packages/uuid.rocks/src/ip/ip.validators.ts @@ -0,0 +1,8 @@ +import { z } from "zod"; + +export const IpSchema = z.string().ip(); + +export const IpJsonSchema = z.object({ + country: z.string(), + ip: IpSchema, +}); diff --git a/packages/uuid.rocks/src/runtimeSafe.ts b/packages/uuid.rocks/src/runtimeSafe.ts index 908567b..17200af 100644 --- a/packages/uuid.rocks/src/runtimeSafe.ts +++ b/packages/uuid.rocks/src/runtimeSafe.ts @@ -3,6 +3,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 { IpSchema, IpJsonSchema } from "./ip/ip.validators"; import { JsonBulkParamsSchema, JsonBulkSchema, @@ -35,9 +36,15 @@ 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. */ + /** This api will hash data in the url or the body */ "/api/hash/:algo/:data": u.input(HashParamsSchema).output(HashSchema), + /** This api will return what IP you’re connecting from */ + "/api/ip": u.output(IpSchema), + + /** This api will return what IP you’re connecting from in JSON format with additional information */ + "/api/ip?json": u.output(IpJsonSchema), + /** 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 5ab843b..a8e1f16 100644 --- a/packages/uuid.rocks/src/types.ts +++ b/packages/uuid.rocks/src/types.ts @@ -1,6 +1,7 @@ export * from "./_shared/_shared.types"; export * from "./emoji/emoji.types"; export * from "./hash/hash.types"; +export * from "./ip/ip.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 1748c43..4657078 100644 --- a/packages/uuid.rocks/src/zod.ts +++ b/packages/uuid.rocks/src/zod.ts @@ -1,6 +1,7 @@ export * from "./_shared/_shared.validators"; export * from "./emoji/emoji.validators"; export * from "./hash/hash.validators"; +export * from "./ip/ip.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/ip.test.ts b/packages/uuid.rocks/tests/ip.test.ts new file mode 100644 index 0000000..157e482 --- /dev/null +++ b/packages/uuid.rocks/tests/ip.test.ts @@ -0,0 +1,31 @@ +import { describe, it, expect } from "vitest"; + +import { IpJsonSchema, IpSchema } from "../src/zod"; +import { useTestClient } from "./_client"; + +describe.concurrent("uuid.rocks - ip address", () => { + it("GET - /api/ip", async () => { + const client = useTestClient({ json: false }); + + const ipAddress = await client("/api/ip"); + + expect(ipAddress).toBeDefined(); + expect(ipAddress).toBeTypeOf("string"); + + expect(IpSchema.safeParse(ipAddress).success).toBe(true); + }); + + it("GET - /api/ip?json", async () => { + const client = useTestClient({ json: true }); + + const ipAddressJson = await client("/api/ip?json"); + + expect(ipAddressJson).toBeDefined(); + expect(ipAddressJson.country).toBeDefined(); + expect(ipAddressJson.country).toBeTypeOf("string"); + expect(ipAddressJson.ip).toBeDefined(); + expect(ipAddressJson.ip).toBeTypeOf("string"); + + expect(IpJsonSchema.safeParse(ipAddressJson).success).toBe(true); + }); +});