diff --git a/sdks/ts/package.json b/sdks/ts/package.json index 4972ee50b..33ae2206f 100644 --- a/sdks/ts/package.json +++ b/sdks/ts/package.json @@ -1,6 +1,6 @@ { "name": "@julep/sdk", - "version": "0.3.7", + "version": "0.3.8", "description": "Julep is a platform for creating agents with long-term memory", "keywords": [ "julep-ai", diff --git a/sdks/ts/src/check.ts b/sdks/ts/src/check.ts deleted file mode 100644 index f123e12d7..000000000 --- a/sdks/ts/src/check.ts +++ /dev/null @@ -1,9 +0,0 @@ -import typia, { tags } from "typia"; - -export const check = typia.createIs(); - -interface IMember { - id: string & tags.Format<"uuid">; - email: string & tags.Format<"email">; - age: number & tags.ExclusiveMinimum<19> & tags.Maximum<100>; -} diff --git a/sdks/ts/src/client.ts b/sdks/ts/src/client.ts index 85cd4589b..81c14d969 100644 --- a/sdks/ts/src/client.ts +++ b/sdks/ts/src/client.ts @@ -1,5 +1,7 @@ import { OpenAI } from "openai"; import { Chat, Completions } from "openai/resources/index"; +import typia, { tags } from "typia"; + import { AgentsManager } from "./managers/agent"; import { UsersManager } from "./managers/user"; import { DocsManager } from "./managers/doc"; @@ -12,7 +14,7 @@ import { patchCreate } from "./utils/openaiPatch"; interface ClientOptions { apiKey?: string; - baseUrl?: string; + baseUrl?: string & tags.Format<"uri">; } /** @@ -30,10 +32,12 @@ export class Client { * @param {string} [options.baseUrl=JULEP_API_URL] - Base URL for the Julep API. Defaults to the JULEP_API_URL environment variable or "https://api-alpha.julep.ai/api" if not provided. * @throws {Error} Throws an error if both apiKey and baseUrl are not provided and not set as environment variables. */ - constructor({ - apiKey = JULEP_API_KEY, - baseUrl = JULEP_API_URL || "https://api-alpha.julep.ai/api", - }: ClientOptions = {}) { + constructor(options: ClientOptions = {}) { + const { + apiKey = JULEP_API_KEY, + baseUrl = JULEP_API_URL || "https://api-alpha.julep.ai/api", + } = typia.assert(options); + if (!apiKey || !baseUrl) { throw new Error( "apiKey and baseUrl must be provided or set as environment variables", diff --git a/sdks/ts/src/managers/agent.ts b/sdks/ts/src/managers/agent.ts index 5fd3e5db1..2c26f1dde 100644 --- a/sdks/ts/src/managers/agent.ts +++ b/sdks/ts/src/managers/agent.ts @@ -1,3 +1,5 @@ +import typia, { tags } from "typia"; + import type { Agent, CreateToolRequest, @@ -9,27 +11,16 @@ import type { PatchAgentRequest, } from "../api"; -import { invariant } from "../utils/invariant"; -import { isValidUuid4 } from "../utils/isValidUuid4"; - import { BaseManager } from "./base"; export class AgentsManager extends BaseManager { - async get(agentId: string): Promise { - invariant(isValidUuid4(agentId), "id must be a valid UUID v4"); + async get(agentId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(agentId); return await this.apiClient.default.getAgent({ agentId }); } - async create({ - name, - about, - instructions = [], - tools, - default_settings, - model = "julep-ai/samantha-1-turbo", - docs = [], - }: { + async create(options: { name: string; about: string; instructions: string[] | string; @@ -38,6 +29,24 @@ export class AgentsManager extends BaseManager { model?: string; docs?: Doc[]; }): Promise & { id: string }> { + const { + name, + about, + instructions = [], + tools, + default_settings, + model = "julep-ai/samantha-1-turbo", + docs = [], + } = typia.assert<{ + name: string; + about: string; + instructions: string[] | string; + tools?: CreateToolRequest[]; + default_settings?: AgentDefaultSettings; + model?: string; + docs?: Doc[]; + }>(options); + // Ensure the returned object includes an `id` property of type string, which is guaranteed not to be `undefined` const requestBody: CreateAgentRequest = { @@ -62,15 +71,29 @@ export class AgentsManager extends BaseManager { return agent; } - async list({ - limit = 100, - offset = 0, - metadataFilter = {}, - }: { - limit?: number; - offset?: number; - metadataFilter?: { [key: string]: any }; - } = {}): Promise> { + async list( + options: { + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + metadataFilter?: { [key: string]: any }; + } = {}, + ): Promise> { + const { + limit = 100, + offset = 0, + metadataFilter = {}, + } = typia.assert<{ + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + metadataFilter?: { [key: string]: any }; + }>(options); + const metadataFilterString: string = JSON.stringify(metadataFilter); const result = await this.apiClient.default.listAgents({ @@ -82,8 +105,8 @@ export class AgentsManager extends BaseManager { return result.items; } - async delete(agentId: string): Promise { - invariant(isValidUuid4(agentId), "id must be a valid UUID v4"); + async delete(agentId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(agentId); await this.apiClient.default.deleteAgent({ agentId }); } @@ -102,17 +125,15 @@ export class AgentsManager extends BaseManager { ): Promise & { id: string }>; async update( - agentId: string, - { - about, - instructions, - name, - model, - default_settings, - }: PatchAgentRequest | UpdateAgentRequest, + agentId: string & tags.Format<"uuid">, + options: PatchAgentRequest | UpdateAgentRequest, overwrite = false, ): Promise & { id: string }> { - invariant(isValidUuid4(agentId), "agentId must be a valid UUID v4"); + typia.assertGuard>(agentId); + + const { about, instructions, name, model, default_settings } = typia.assert< + PatchAgentRequest | UpdateAgentRequest + >(options); // Fails tests // const updateFn = overwrite ? this.apiClient.default.updateAgent : this.apiClient.default.patchAgent; diff --git a/sdks/ts/src/managers/base.ts b/sdks/ts/src/managers/base.ts index 7dee6540f..42ca4aea6 100644 --- a/sdks/ts/src/managers/base.ts +++ b/sdks/ts/src/managers/base.ts @@ -1,3 +1,5 @@ +import typia from "typia"; + import { JulepApiClient } from "../api/JulepApiClient"; /** @@ -9,5 +11,7 @@ export class BaseManager { * Constructs a new instance of BaseManager. * @param apiClient The JulepApiClient instance used for API interactions. */ - constructor(public apiClient: JulepApiClient) {} + constructor(public apiClient: JulepApiClient) { + typia.assertGuard(apiClient); + } } diff --git a/sdks/ts/src/managers/doc.ts b/sdks/ts/src/managers/doc.ts index 262e3bdf9..db0fd0239 100644 --- a/sdks/ts/src/managers/doc.ts +++ b/sdks/ts/src/managers/doc.ts @@ -1,7 +1,8 @@ -import type { Doc, ResourceCreatedResponse, CreateDoc } from "../api"; +import typia, { tags } from "typia"; + +import { type Doc, type ResourceCreatedResponse, type CreateDoc } from "../api"; import { invariant } from "../utils/invariant"; -import { isValidUuid4 } from "../utils/isValidUuid4"; import { xor } from "../utils/xor"; import { BaseManager } from "./base"; @@ -19,24 +20,39 @@ export class DocsManager extends BaseManager { * @returns {Promise} The retrieved documents. * @throws {Error} If neither agentId nor userId is provided. */ - async get({ - agentId, - userId, - limit = 100, - offset = 0, - }: { - userId?: string; - agentId?: string; - limit?: number; - offset?: number; - }) { + async get( + options: { + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + } = {}, + ): Promise< + | ReturnType + | ReturnType + > { + const { + agentId, + userId, + limit = 100, + offset = 0, + } = typia.assert<{ + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + }>(options); + invariant( xor(agentId, userId), "Only one of agentId or userId must be given", ); - agentId && - invariant(isValidUuid4(agentId), "agentId must be a valid UUID v4"); - userId && invariant(isValidUuid4(userId), "userId must be a valid UUID v4"); if (agentId) { return await this.apiClient.default.getAgentDocs({ @@ -71,28 +87,41 @@ export class DocsManager extends BaseManager { * @returns {Promise>} The list of filtered documents. * @throws {Error} If neither agentId nor userId is provided. */ - async list({ - agentId, - userId, - limit = 100, - offset = 0, - metadataFilter = {}, - }: { - agentId?: string; - userId?: string; - limit?: number; - offset?: number; - metadataFilter?: { [key: string]: any }; - } = {}): Promise> { + async list( + options: { + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + metadataFilter?: { [key: string]: any }; + } = {}, + ): Promise> { + const { + agentId, + userId, + limit = 100, + offset = 0, + metadataFilter = {}, + } = typia.assert<{ + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + metadataFilter?: { [key: string]: any }; + }>(options); + const metadataFilterString: string = JSON.stringify(metadataFilter); invariant( xor(agentId, userId), "Only one of agentId or userId must be given", ); - agentId && - invariant(isValidUuid4(agentId), "agentId must be a valid UUID v4"); - userId && invariant(isValidUuid4(userId), "userId must be a valid UUID v4"); if (agentId) { const result = await this.apiClient.default.getAgentDocs({ @@ -130,22 +159,21 @@ export class DocsManager extends BaseManager { * @returns {Promise} The created document. * @throws {Error} If neither agentId nor userId is provided. */ - async create({ - agentId, - userId, - doc, - }: { - agentId?: string; - userId?: string; + async create(options: { + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; doc: CreateDoc; }): Promise { + const { agentId, userId, doc } = typia.assert<{ + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; + doc: CreateDoc; + }>(options); + invariant( xor(agentId, userId), "Only one of agentId or userId must be given", ); - agentId && - invariant(isValidUuid4(agentId), "agentId must be a valid UUID v4"); - userId && invariant(isValidUuid4(userId), "userId must be a valid UUID v4"); if (agentId) { const result: ResourceCreatedResponse = @@ -183,22 +211,21 @@ export class DocsManager extends BaseManager { * @returns {Promise} A promise that resolves when the document is successfully deleted. * @throws {Error} If neither agentId nor userId is provided. */ - async delete({ - agentId, - userId, - docId, - }: { - agentId?: string; - userId?: string; + async delete(options: { + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; docId: string; }): Promise { + const { agentId, userId, docId } = typia.assert<{ + agentId?: string & tags.Format<"uuid">; + userId?: string & tags.Format<"uuid">; + docId: string; + }>(options); + invariant( xor(agentId, userId), "Only one of agentId or userId must be given", ); - agentId && - invariant(isValidUuid4(agentId), "agentId must be a valid UUID v4"); - userId && invariant(isValidUuid4(userId), "userId must be a valid UUID v4"); if (agentId) { await this.apiClient.default.deleteAgentDoc({ agentId, docId }); diff --git a/sdks/ts/src/managers/memory.ts b/sdks/ts/src/managers/memory.ts index acd473f61..b0ff7276c 100644 --- a/sdks/ts/src/managers/memory.ts +++ b/sdks/ts/src/managers/memory.ts @@ -1,8 +1,8 @@ +import typia, { tags } from "typia"; + import { Memory } from "../api"; import { BaseManager } from "./base"; -import { invariant } from "../utils/invariant"; -import { isValidUuid4 } from "../utils/isValidUuid4"; export class MemoriesManager extends BaseManager { /** @@ -18,23 +18,29 @@ export class MemoriesManager extends BaseManager { * @param {number} [offset=0] - The offset for pagination. Optional. * @returns {Promise} A promise that resolves to an array of Memory objects. */ - async list({ - agentId, - query, - userId, - limit = 100, - offset = 0, - }: { - agentId: string; + async list(options: { + agentId: string & tags.Format<"uuid">; query: string; - userId?: string; - limit?: number; - offset?: number; + userId?: string & tags.Format<"uuid">; + limit?: number & tags.Type<"uint32"> & tags.Minimum<1> & tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; }): Promise { - // Validates that the agentId is a valid UUID v4 format. - invariant(isValidUuid4(agentId), "agentId must be a valid UUID v4"); - // Validates that the userId, if provided, is a valid UUID v4 format. - userId && invariant(isValidUuid4(userId), "userId must be a valid UUID v4"); + const { + agentId, + query, + userId, + limit = 100, + offset = 0, + } = typia.assert<{ + agentId: string & tags.Format<"uuid">; + query: string; + userId?: string & tags.Format<"uuid">; + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + }>(options); const response = await this.apiClient.default.getAgentMemories({ agentId, diff --git a/sdks/ts/src/managers/session.ts b/sdks/ts/src/managers/session.ts index 9d0671272..10f52257c 100644 --- a/sdks/ts/src/managers/session.ts +++ b/sdks/ts/src/managers/session.ts @@ -1,3 +1,5 @@ +import typia, { tags } from "typia"; + import { isUndefined, omitBy } from "lodash"; import { ChatInput, @@ -8,8 +10,6 @@ import { Session, Suggestion, } from "../api"; -import { invariant } from "../utils/invariant"; -import { isValidUuid4 } from "../utils/isValidUuid4"; import { BaseManager } from "./base"; export interface CreateSessionPayload { @@ -30,29 +30,24 @@ export class SessionsManager extends BaseManager { * @param sessionId The unique identifier of the session. * @returns A promise that resolves with the session object. */ - async get(sessionId: string): Promise { + async get(sessionId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(sessionId); + return this.apiClient.default.getSession({ sessionId }); } - async create({ - userId, - agentId, - situation, - tokenBudget, - contextOverflow, - metadata = {}, - renderTemplates = false, - }: CreateSessionPayload): Promise { - userId && - invariant( - isValidUuid4(userId), - `userId must be a valid UUID v4. Got "${userId}"`, - ); - - invariant( - isValidUuid4(agentId), - `agentId must be a valid UUID v4. Got "${agentId}"`, - ); + async create( + payload: CreateSessionPayload, + ): Promise { + const { + userId, + agentId, + situation, + tokenBudget, + contextOverflow, + metadata = {}, + renderTemplates = false, + }: CreateSessionPayload = typia.assert(payload); const requestBody = { user_id: userId, @@ -77,15 +72,29 @@ export class SessionsManager extends BaseManager { .catch((error) => Promise.reject(error)); } - async list({ - limit = 100, - offset = 0, - metadataFilter = {}, - }: { - limit?: number; - offset?: number; - metadataFilter?: { [key: string]: any }; - } = {}): Promise> { + async list( + options: { + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Minimum<1> & tags.Maximum<1000>; + metadataFilter?: { [key: string]: any }; + } = {}, + ): Promise> { + const { + limit = 100, + offset = 0, + metadataFilter = {}, + } = typia.assert<{ + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Minimum<1> & tags.Maximum<1000>; + metadataFilter?: { [key: string]: any }; + }>(options); + const metadataFilterString: string = JSON.stringify(metadataFilter); const result = await this.apiClient.default.listSessions({ @@ -97,28 +106,36 @@ export class SessionsManager extends BaseManager { return result.items || []; } - async delete(sessionId: string): Promise { - invariant(isValidUuid4(sessionId), "sessionId must be a valid UUID v4"); + async delete(sessionId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(sessionId); await this.apiClient.default.deleteSession({ sessionId }); } async update( - sessionId: string, - { + sessionId: string & tags.Format<"uuid">, + options: { + situation: string; + tokenBudget?: number & tags.Minimum<1>; + contextOverflow?: "truncate" | "adaptive"; + metadata?: Record; + }, + overwrite = false, + ): Promise { + typia.assertGuard>(sessionId); + + const { situation, tokenBudget, contextOverflow, metadata = {}, - }: { + } = typia.assert<{ situation: string; - tokenBudget?: number; + tokenBudget?: number & tags.Minimum<1>; contextOverflow?: "truncate" | "adaptive"; - metadata?: any; - }, - overwrite = false, - ): Promise { - invariant(isValidUuid4(sessionId), "sessionId must be a valid UUID v4"); + metadata?: Record; + }>(options); + const requestBody = { situation, metadata, @@ -142,8 +159,12 @@ export class SessionsManager extends BaseManager { } async chat( - sessionId: string, - { + sessionId: string & tags.Format<"uuid">, + input: ChatInput, + ): Promise { + typia.assertGuard>(sessionId); + + const { messages, frequency_penalty, length_penalty, @@ -161,9 +182,7 @@ export class SessionsManager extends BaseManager { tool_choice, tools, top_p, - }: ChatInput, - ): Promise { - invariant(isValidUuid4(sessionId), "sessionId must be a valid UUID v4"); + } = typia.assert(input); const options = omitBy( { @@ -196,10 +215,18 @@ export class SessionsManager extends BaseManager { } async suggestions( - sessionId: string, - { limit = 100, offset = 0 }: { limit?: number; offset?: number } = {}, + sessionId: string & tags.Format<"uuid">, + options: { + limit?: number & tags.Minimum<1> & tags.Maximum<1000>; + offset?: number & tags.Minimum<0>; + } = {}, ): Promise> { - invariant(isValidUuid4(sessionId), "sessionId must be a valid UUID v4"); + typia.assertGuard>(sessionId); + + const { limit = 100, offset = 0 } = typia.assert<{ + limit?: number & tags.Minimum<1> & tags.Maximum<1000>; + offset?: number & tags.Minimum<0>; + }>(options); const result = await this.apiClient.default.getSuggestions({ sessionId, @@ -211,10 +238,18 @@ export class SessionsManager extends BaseManager { } async history( - sessionId: string, - { limit = 100, offset = 0 }: { limit?: number; offset?: number } = {}, + sessionId: string & tags.Format<"uuid">, + options: { + limit?: number & tags.Minimum<1> & tags.Maximum<1000>; + offset?: number & tags.Minimum<0>; + } = {}, ): Promise> { - invariant(isValidUuid4(sessionId), "sessionId must be a valid UUID v4"); + typia.assertGuard>(sessionId); + + const { limit = 100, offset = 0 } = typia.assert<{ + limit?: number & tags.Minimum<1> & tags.Maximum<1000>; + offset?: number & tags.Minimum<0>; + }>(options); const result = await this.apiClient.default.getHistory({ sessionId, @@ -225,8 +260,8 @@ export class SessionsManager extends BaseManager { return result.items || []; } - async deleteHistory(sessionId: string): Promise { - invariant(isValidUuid4(sessionId), "sessionId must be a valid UUID v4"); + async deleteHistory(sessionId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(sessionId); await this.apiClient.default.deleteSessionHistory({ sessionId }); } diff --git a/sdks/ts/src/managers/tool.ts b/sdks/ts/src/managers/tool.ts index 880399e35..356917a96 100644 --- a/sdks/ts/src/managers/tool.ts +++ b/sdks/ts/src/managers/tool.ts @@ -1,3 +1,5 @@ +import typia, { tags } from "typia"; + // ToolsManager class manages tool-related operations such as listing, creating, updating, and deleting tools. import { Tool, @@ -10,15 +12,25 @@ import { BaseManager } from "./base"; export class ToolsManager extends BaseManager { async list( - agentId: string, - { - limit = 10, - offset = 0, - }: { - limit?: number; - offset?: number; + agentId: string & tags.Format<"uuid">, + options: { + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; } = {}, ): Promise> { + typia.assertGuard>(agentId); + + const { limit = 10, offset = 0 } = typia.assert<{ + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + }>(options); + // Lists tools associated with a given agent. Allows pagination through `limit` and `offset` parameters. const result = await this.apiClient.default.getAgentTools({ agentId, @@ -29,16 +41,21 @@ export class ToolsManager extends BaseManager { return result.items || []; } - async create({ - agentId, - tool, - }: { - agentId: string; + async create(options: { + agentId: string & tags.Format<"uuid">; tool: { type: "function" | "webhook"; function: FunctionDef; }; }): Promise { + const { agentId, tool } = typia.assert<{ + agentId: string & tags.Format<"uuid">; + tool: { + type: "function" | "webhook"; + function: FunctionDef; + }; + }>(options); + // Creates a new tool for the specified agent. The `tool` parameter must include the tool type and function definition. const result: ResourceCreatedResponse = await this.apiClient.default.createAgentTool({ @@ -52,17 +69,19 @@ export class ToolsManager extends BaseManager { } async update( - { - agentId, - toolId, - tool, - }: { - agentId: string; - toolId: string; + options: { + agentId: string & tags.Format<"uuid">; + toolId: string & tags.Format<"uuid">; tool: UpdateToolRequest; }, overwrite = false, ): Promise { + const { agentId, toolId, tool } = typia.assert<{ + agentId: string & tags.Format<"uuid">; + toolId: string & tags.Format<"uuid">; + tool: UpdateToolRequest; + }>(options); + // Updates an existing tool. If `overwrite` is true, it replaces the existing tool with the new one; otherwise, it patches the tool with the provided changes. if (overwrite) { const result = await this.apiClient.default.updateAgentTool({ @@ -83,13 +102,15 @@ export class ToolsManager extends BaseManager { } } - async delete({ - agentId, - toolId, - }: { - agentId: string; - toolId: string; + async delete(options: { + agentId: string & tags.Format<"uuid">; + toolId: string & tags.Format<"uuid">; }): Promise { + const { agentId, toolId } = typia.assert<{ + agentId: string & tags.Format<"uuid">; + toolId: string & tags.Format<"uuid">; + }>(options); + // Deletes a specified tool from an agent. await this.apiClient.default.deleteAgentTool({ agentId, toolId }); } diff --git a/sdks/ts/src/managers/user.ts b/sdks/ts/src/managers/user.ts index d194a750d..21c29f326 100644 --- a/sdks/ts/src/managers/user.ts +++ b/sdks/ts/src/managers/user.ts @@ -1,3 +1,5 @@ +import typia, { tags } from "typia"; + import type { User, CreateUserRequest, @@ -6,50 +8,55 @@ import type { UpdateUserRequest, } from "../api"; -import { invariant } from "../utils/invariant"; -import { isValidUuid4 } from "../utils/isValidUuid4"; - import { BaseManager } from "./base"; export class UsersManager extends BaseManager { - async get(userId: string): Promise { - try { - invariant(isValidUuid4(userId), "id must be a valid UUID v4"); + async get(userId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(userId); - // Fetches a user by ID using the API client - const user = await this.apiClient.default.getUser({ userId }); - return user; - } catch (error) { - throw error; - } + // Fetches a user by ID using the API client + const user = await this.apiClient.default.getUser({ userId }); + return user; } - async create({ - name, - about, - docs = [], - }: CreateUserRequest = {}): Promise { - try { - const requestBody = { name, about, docs }; - const result: ResourceCreatedResponse = - await this.apiClient.default.createUser({ requestBody }); + async create(options: CreateUserRequest = {}): Promise { + const { + name, + about, + docs = [], + }: CreateUserRequest = typia.assert(options); - const user: User = { ...result, ...requestBody }; - return user; - } catch (error) { - throw error; - } + const requestBody = { name, about, docs }; + const result: ResourceCreatedResponse = + await this.apiClient.default.createUser({ requestBody }); + + const user: User = { ...result, ...requestBody }; + return user; } - async list({ - limit = 10, - offset = 0, - metadataFilter = {}, - }: { - limit?: number; - offset?: number; - metadataFilter?: { [key: string]: any }; - } = {}): Promise> { + async list( + options: { + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + metadataFilter?: { [key: string]: any }; + } = {}, + ): Promise> { + const { + limit = 10, + offset = 0, + metadataFilter = {}, + } = typia.assert<{ + limit?: number & + tags.Type<"uint32"> & + tags.Minimum<1> & + tags.Maximum<1000>; + offset?: number & tags.Type<"uint32"> & tags.Minimum<0>; + metadataFilter?: { [key: string]: any }; + }>(options); + const metadataFilterString: string = JSON.stringify(metadataFilter); const result = await this.apiClient.default.listUsers({ limit, @@ -60,14 +67,10 @@ export class UsersManager extends BaseManager { return result.items; } - async delete(userId: string): Promise { - try { - invariant(isValidUuid4(userId), "id must be a valid UUID v4"); + async delete(userId: string & tags.Format<"uuid">): Promise { + typia.assertGuard>(userId); - await this.apiClient.default.deleteUser({ userId }); - } catch (error) { - throw error; - } + await this.apiClient.default.deleteUser({ userId }); } async update( @@ -83,37 +86,37 @@ export class UsersManager extends BaseManager { ): Promise; async update( - userId: string, - { about, name }: PatchUserRequest | UpdateUserRequest, + userId: string & tags.Format<"uuid">, + options: PatchUserRequest | UpdateUserRequest, overwrite = false, ): Promise { - try { - invariant(isValidUuid4(userId), "id must be a valid UUID v4"); - - // Tests won't pass if ternary is used - // const updateFn = overwrite - // ? this.apiClient.default.updateUser - // : this.apiClient.default.patchUser; - - if (overwrite) { - const requestBody = { name: name!, about: about! }; - const result = await this.apiClient.default.updateUser({ - userId, - requestBody, - }); - const user: User = { ...result, ...requestBody }; - return user; - } else { - const requestBody = { name, about }; - const result = await this.apiClient.default.patchUser({ - userId, - requestBody, - }); - const user: User = { ...result, ...requestBody }; - return user; - } - } catch (error) { - throw error; + typia.assertGuard>(userId); + + const { about, name }: PatchUserRequest | UpdateUserRequest = typia.assert< + PatchUserRequest | UpdateUserRequest + >(options); + + // Tests won't pass if ternary is used + // const updateFn = overwrite + // ? this.apiClient.default.updateUser + // : this.apiClient.default.patchUser; + + if (overwrite) { + const requestBody = { name: name!, about: about! }; + const result = await this.apiClient.default.updateUser({ + userId, + requestBody, + }); + const user: User = { ...result, ...requestBody }; + return user; + } else { + const requestBody = { name, about }; + const result = await this.apiClient.default.patchUser({ + userId, + requestBody, + }); + const user: User = { ...result, ...requestBody }; + return user; } } } diff --git a/sdks/ts/src/utils/requestConstructor.ts b/sdks/ts/src/utils/requestConstructor.ts index f7033c858..ef36452f1 100644 --- a/sdks/ts/src/utils/requestConstructor.ts +++ b/sdks/ts/src/utils/requestConstructor.ts @@ -1,10 +1,9 @@ // Utility functions for constructing and handling API requests. -import type { OpenAPIConfig } from "../api"; - -import type { ApiRequestOptions } from "../api/core/ApiRequestOptions"; - import { isPlainObject, mapKeys, camelCase } from "lodash"; +import typia from "typia"; +import { type OpenAPIConfig } from "../api"; +import { type ApiRequestOptions } from "../api/core/ApiRequestOptions"; import { AxiosHttpRequest } from "../api/core/AxiosHttpRequest"; import { CancelablePromise } from "../api/core/CancelablePromise"; @@ -14,11 +13,14 @@ const camelCaseify = (responseBody: any) => export class CustomHttpRequest extends AxiosHttpRequest { constructor(config: OpenAPIConfig) { + typia.assertGuard(config); super(config); } // Overrides the base request method to apply additional processing on the response, such as camelCasing keys and handling collections. public override request(options: ApiRequestOptions): CancelablePromise { + typia.assertGuard(options); + const cancelableResponse = super.request(options); return new CancelablePromise((resolve, reject, onCancel) => {