From a98f9542fa3d2cb864017cfa5c5e82c885f2bd44 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Tue, 8 Apr 2025 17:06:51 +0200 Subject: [PATCH] Add unused extra generic for future typing of metadata --- libs/sdk-js/src/auth/error.ts | 8 +- libs/sdk-js/src/auth/index.ts | 384 +++------------------------------- libs/sdk-js/src/auth/types.ts | 345 ++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+), 360 deletions(-) create mode 100644 libs/sdk-js/src/auth/types.ts diff --git a/libs/sdk-js/src/auth/error.ts b/libs/sdk-js/src/auth/error.ts index bd26c8912..ace6df54c 100644 --- a/libs/sdk-js/src/auth/error.ts +++ b/libs/sdk-js/src/auth/error.ts @@ -65,10 +65,16 @@ const HTTP_STATUS_MAPPING: { [key: number]: string } = { export class HTTPException extends Error { status: number; - constructor(status: number, options?: { message?: string; cause?: Error }) { + headers: HeadersInit; + + constructor( + status: number, + options?: { message?: string; headers?: HeadersInit; cause?: unknown }, + ) { super(options?.message ?? HTTP_STATUS_MAPPING[status] ?? "Unknown error", { cause: options?.cause, }); this.status = status; + this.headers = options?.headers ?? {}; } } diff --git a/libs/sdk-js/src/auth/index.ts b/libs/sdk-js/src/auth/index.ts index 04a84d06b..726e638d4 100644 --- a/libs/sdk-js/src/auth/index.ts +++ b/libs/sdk-js/src/auth/index.ts @@ -1,372 +1,38 @@ -type Maybe = T | null | undefined; - -interface AssistantConfig { - tags?: Maybe; - recursion_limit?: Maybe; - configurable?: Maybe<{ - thread_id?: Maybe; - thread_ts?: Maybe; - [key: string]: unknown; - }>; -} - -interface AssistantCreate { - assistant_id?: Maybe; - metadata?: Maybe>; - config?: Maybe; - if_exists?: Maybe<"raise" | "do_nothing">; - name?: Maybe; - graph_id: string; -} - -interface AssistantRead { - assistant_id: string; - metadata?: Maybe>; -} -interface AssistantUpdate { - assistant_id: string; - metadata?: Maybe>; - config?: Maybe; - graph_id?: Maybe; - name?: Maybe; - version?: Maybe; -} -interface AssistantDelete { - assistant_id: string; -} -interface AssistantSearch { - graph_id?: Maybe; - metadata?: Maybe>; - limit?: Maybe; - offset?: Maybe; -} - -interface ThreadCreate { - thread_id?: Maybe; - metadata?: Maybe>; - if_exists?: Maybe<"raise" | "do_nothing">; -} - -interface ThreadRead { - thread_id?: Maybe; -} - -interface ThreadUpdate { - thread_id?: Maybe; - metadata?: Maybe>; - action?: Maybe<"interrupt" | "rollback">; -} - -interface ThreadDelete { - thread_id?: Maybe; - run_id?: Maybe; -} - -interface ThreadSearch { - thread_id?: Maybe; - status?: Maybe<"idle" | "busy" | "interrupted" | "error" | (string & {})>; - metadata?: Maybe>; - values?: Maybe>; - limit?: Maybe; - offset?: Maybe; -} - -interface CronCreate { - payload?: Maybe>; - schedule: string; - cron_id?: Maybe; - thread_id?: Maybe; - user_id?: Maybe; - end_time?: Maybe; -} - -interface CronRead { - cron_id: string; -} - -interface CronUpdate { - cron_id: string; - payload?: Maybe>; - schedule?: Maybe; -} - -interface CronDelete { - cron_id: string; -} - -interface CronSearch { - assistant_id?: Maybe; - thread_id?: Maybe; - limit?: Maybe; - offset?: Maybe; -} - -interface StorePut { - namespace: string[]; - key: string; - value: Record; -} - -interface StoreGet { - namespace: Maybe; - key: string; -} - -interface StoreSearch { - namespace?: Maybe; - filter?: Maybe>; - limit?: Maybe; - offset?: Maybe; - query?: Maybe; -} - -interface StoreListNamespaces { - namespace?: Maybe; - suffix?: Maybe; - max_depth?: Maybe; - limit?: Maybe; - offset?: Maybe; -} - -interface StoreDelete { - namespace?: Maybe; - key: string; -} - -interface RunsCreate { - thread_id?: Maybe; - assistant_id: string; - run_id: string; - status: Maybe< - "pending" | "running" | "error" | "success" | "timeout" | "interrupted" - >; - metadata?: Maybe>; - prevent_insert_if_inflight?: Maybe; - multitask_strategy?: Maybe<"interrupt" | "rollback" | "reject" | "enqueue">; - if_not_exists?: Maybe<"reject" | "create">; - after_seconds?: Maybe; - kwargs: Record; -} - -export interface ResourceActionType { - ["threads:create"]: ThreadCreate; - ["threads:read"]: ThreadRead; - ["threads:update"]: ThreadUpdate; - ["threads:delete"]: ThreadDelete; - ["threads:search"]: ThreadSearch; - ["threads:create_run"]: RunsCreate; - - ["assistants:create"]: AssistantCreate; - ["assistants:read"]: AssistantRead; - ["assistants:update"]: AssistantUpdate; - ["assistants:delete"]: AssistantDelete; - ["assistants:search"]: AssistantSearch; - - ["crons:create"]: CronCreate; - ["crons:read"]: CronRead; - ["crons:update"]: CronUpdate; - ["crons:delete"]: CronDelete; - ["crons:search"]: CronSearch; - - ["store:put"]: StorePut; - ["store:get"]: StoreGet; - ["store:search"]: StoreSearch; - ["store:list_namespaces"]: StoreListNamespaces; - ["store:delete"]: StoreDelete; -} - -interface ResourceType { - threads: - | "threads:create" - | "threads:read" - | "threads:update" - | "threads:delete" - | "threads:search" - | "threads:create_run"; - - assistants: - | "assistants:create" - | "assistants:read" - | "assistants:update" - | "assistants:delete" - | "assistants:search"; - crons: - | "crons:create" - | "crons:read" - | "crons:update" - | "crons:delete" - | "crons:search"; - - store: - | "store:put" - | "store:get" - | "store:search" - | "store:list_namespaces" - | "store:delete"; -} - -interface ActionType { - "*:create": "threads:create" | "assistants:create" | "crons:create"; - - "*:read": "threads:read" | "assistants:read" | "crons:read"; - - "*:update": "threads:update" | "assistants:update" | "crons:update"; - - "*:delete": - | "threads:delete" - | "assistants:delete" - | "crons:delete" - | "store:delete"; - - "*:search": - | "threads:search" - | "assistants:search" - | "crons:search" - | "store:search"; - - "*:create_run": "threads:create_run"; - - "*:put": "store:put"; - - "*:get": "store:get"; - - "*:list_namespaces": "store:list_namespaces"; -} - -interface BaseAuthContext { - permissions?: string[]; - user?: { - is_authenticated: boolean; - display_name: string; - identity: string; - permissions: string[]; - }; -} - -type ContextMap = { - [ActionType in keyof ResourceActionType]: { - resource: ActionType extends `${infer Resource}:${string}` - ? Resource - : never; - action: ActionType; - data: ResourceActionType[ActionType]; - context: BaseAuthContext; - }; -}; - -type ActionCallbackParameter< - T extends keyof ActionType, - AuthContext = {}, -> = ContextMap[ActionType[T]] & { context: AuthContext }; - -type AuthCallbackParameter< - T extends keyof ResourceActionType, - AuthContext = {}, -> = ContextMap[T] & { context: AuthContext }; - -type ResourceCallbackParameter< - T extends keyof ResourceType, - AuthContext = {}, -> = ContextMap[ResourceType[T]] & { context: AuthContext }; - -export type Filters = { - [key in TKey]: string | { [op in "$contains" | "$eq"]?: string }; -}; - -interface AuthenticateCallback> { - (request: Request): AuthContext; -} - -interface GlobalCallback< - Metadata extends Record = {}, - AuthContext extends Record = {}, -> { - ( - data: AuthCallbackParameter, - ): void | boolean | Filters; -} - -interface ResourceCallback< - Metadata extends Record = {}, - AuthContext extends Record = {}, -> { - ( - data: ResourceCallbackParameter, - ): void | boolean | Filters; -} - -interface ActionCallback< - Metadata extends Record = {}, - AuthContext extends Record = {}, -> { - ( - data: ActionCallbackParameter, - ): void | boolean | Filters; -} - -interface ResourceActionCallback< - Metadata extends Record = {}, - AuthContext extends Record = {}, -> { - ( - data: AuthCallbackParameter, - ): void | boolean | Filters; -} +import type { + AuthenticateCallback, + AnyCallback, + CallbackEvent, + OnCallback, + BaseAuthReturn, + ToUserLike, + BaseUser, +} from "./types.js"; export class Auth< - Metadata extends Record = {}, - AuthContext extends Record = {}, + TExtra, + TAuthReturn extends BaseAuthReturn = BaseAuthReturn, + TUser extends BaseUser = ToUserLike, > { + extra: TExtra; + "~handlerCache": { - authenticate?: AuthenticateCallback; - callbacks?: Record< - string, - (request: any) => void | boolean | Filters - >; + authenticate?: AuthenticateCallback; + callbacks?: Record; } = {}; - authenticate(cb: AuthenticateCallback): this { + authenticate( + cb: AuthenticateCallback, + ): Auth { this["~handlerCache"].authenticate = cb; - return this; + return this as unknown as Auth; } - /** - * Global handler for all requests - */ - on(event: "*", callback: GlobalCallback): this; - - /** - * Resource-specific handler - */ - on( - event: T, - callback: ResourceCallback, - ): this; - - /** - * Action-specific handler - */ - on( - event: T, - callback: ActionCallback, - ): this; - - /** - * Resource-action specific handler - */ - on( - event: T, - callback: ResourceActionCallback, - ): this; - - on( - event: string, - callback: ( - data: AuthCallbackParameter, - ) => void | boolean | Filters, - ): this { + on(event: T, callback: OnCallback): this { this["~handlerCache"].callbacks ??= {}; - this["~handlerCache"].callbacks[event] = callback; + this["~handlerCache"].callbacks[event as string] = callback as AnyCallback; return this; } } + +export type { Filters, ResourceActionType } from "./types.js"; +export { HTTPException } from "./error.js"; diff --git a/libs/sdk-js/src/auth/types.ts b/libs/sdk-js/src/auth/types.ts new file mode 100644 index 000000000..d2a39e05b --- /dev/null +++ b/libs/sdk-js/src/auth/types.ts @@ -0,0 +1,345 @@ +type Maybe = T | null | undefined; +type PromiseMaybe = Promise | T; + +interface AssistantConfig { + tags?: Maybe; + recursion_limit?: Maybe; + configurable?: Maybe<{ + thread_id?: Maybe; + thread_ts?: Maybe; + [key: string]: unknown; + }>; +} + +interface AssistantCreate { + assistant_id?: Maybe; + metadata?: Maybe>; + config?: Maybe; + if_exists?: Maybe<"raise" | "do_nothing">; + name?: Maybe; + graph_id: string; +} + +interface AssistantRead { + assistant_id: string; + metadata?: Maybe>; +} + +interface AssistantUpdate { + assistant_id: string; + metadata?: Maybe>; + config?: Maybe; + graph_id?: Maybe; + name?: Maybe; + version?: Maybe; +} + +interface AssistantDelete { + assistant_id: string; +} + +interface AssistantSearch { + graph_id?: Maybe; + metadata?: Maybe>; + limit?: Maybe; + offset?: Maybe; +} + +interface ThreadCreate { + thread_id?: Maybe; + metadata?: Maybe>; + if_exists?: Maybe<"raise" | "do_nothing">; +} + +interface ThreadRead { + thread_id?: Maybe; +} + +interface ThreadUpdate { + thread_id?: Maybe; + metadata?: Maybe>; + action?: Maybe<"interrupt" | "rollback">; +} + +interface ThreadDelete { + thread_id?: Maybe; + run_id?: Maybe; +} + +interface ThreadSearch { + thread_id?: Maybe; + status?: Maybe<"idle" | "busy" | "interrupted" | "error" | (string & {})>; + metadata?: Maybe>; + values?: Maybe>; + limit?: Maybe; + offset?: Maybe; +} + +interface CronCreate { + payload?: Maybe>; + schedule: string; + cron_id?: Maybe; + thread_id?: Maybe; + user_id?: Maybe; + end_time?: Maybe; +} + +interface CronRead { + cron_id: string; +} + +interface CronUpdate { + cron_id: string; + payload?: Maybe>; + schedule?: Maybe; +} + +interface CronDelete { + cron_id: string; +} + +interface CronSearch { + assistant_id?: Maybe; + thread_id?: Maybe; + limit?: Maybe; + offset?: Maybe; +} + +interface StorePut { + namespace: string[]; + key: string; + value: Record; +} + +interface StoreGet { + namespace: Maybe; + key: string; +} + +interface StoreSearch { + namespace?: Maybe; + filter?: Maybe>; + limit?: Maybe; + offset?: Maybe; + query?: Maybe; +} + +interface StoreListNamespaces { + namespace?: Maybe; + suffix?: Maybe; + max_depth?: Maybe; + limit?: Maybe; + offset?: Maybe; +} + +interface StoreDelete { + namespace?: Maybe; + key: string; +} + +interface RunsCreate { + thread_id?: Maybe; + assistant_id: string; + run_id: string; + status: Maybe< + "pending" | "running" | "error" | "success" | "timeout" | "interrupted" + >; + metadata?: Maybe>; + prevent_insert_if_inflight?: Maybe; + multitask_strategy?: Maybe<"interrupt" | "rollback" | "reject" | "enqueue">; + if_not_exists?: Maybe<"reject" | "create">; + after_seconds?: Maybe; + kwargs: Record; +} + +export interface ResourceActionType { + ["threads:create"]: ThreadCreate; + ["threads:read"]: ThreadRead; + ["threads:update"]: ThreadUpdate; + ["threads:delete"]: ThreadDelete; + ["threads:search"]: ThreadSearch; + ["threads:create_run"]: RunsCreate; + + ["assistants:create"]: AssistantCreate; + ["assistants:read"]: AssistantRead; + ["assistants:update"]: AssistantUpdate; + ["assistants:delete"]: AssistantDelete; + ["assistants:search"]: AssistantSearch; + + ["crons:create"]: CronCreate; + ["crons:read"]: CronRead; + ["crons:update"]: CronUpdate; + ["crons:delete"]: CronDelete; + ["crons:search"]: CronSearch; + + ["store:put"]: StorePut; + ["store:get"]: StoreGet; + ["store:search"]: StoreSearch; + ["store:list_namespaces"]: StoreListNamespaces; + ["store:delete"]: StoreDelete; +} +interface ResourceType { + threads: + | "threads:create" + | "threads:read" + | "threads:update" + | "threads:delete" + | "threads:search" + | "threads:create_run"; + + assistants: + | "assistants:create" + | "assistants:read" + | "assistants:update" + | "assistants:delete" + | "assistants:search"; + crons: + | "crons:create" + | "crons:read" + | "crons:update" + | "crons:delete" + | "crons:search"; + + store: + | "store:put" + | "store:get" + | "store:search" + | "store:list_namespaces" + | "store:delete"; +} +interface ActionType { + "*:create": "threads:create" | "assistants:create" | "crons:create"; + + "*:read": "threads:read" | "assistants:read" | "crons:read"; + + "*:update": "threads:update" | "assistants:update" | "crons:update"; + + "*:delete": + | "threads:delete" + | "assistants:delete" + | "crons:delete" + | "store:delete"; + + "*:search": + | "threads:search" + | "assistants:search" + | "crons:search" + | "store:search"; + + "*:create_run": "threads:create_run"; + + "*:put": "store:put"; + + "*:get": "store:get"; + + "*:list_namespaces": "store:list_namespaces"; +} + +export type BaseAuthReturn = + | { + is_authenticated?: boolean; + display_name?: string; + identity: string; + permissions: string[]; + } + | string; + +export interface BaseUser { + is_authenticated: boolean; + display_name: string; + identity: string; + permissions: string[]; +} + +export type ToUserLike = T extends string + ? { + is_authenticated: boolean; + display_name: string; + identity: string; + permissions: string[]; + } + : Omit & { + is_authenticated: boolean; + display_name: string; + }; + +type CallbackParameter< + Resource extends string = string, + Action extends string = string, + Value extends unknown = unknown, + TUser extends BaseUser = BaseUser, +> = { + resource: Resource; + action: Action; + value: Value; + user: TUser; + permissions: string[]; +}; + +type ContextMap = { + [ActionType in keyof ResourceActionType]: CallbackParameter< + ActionType extends `${infer Resource}:${string}` ? Resource : never, + ActionType, + ResourceActionType[ActionType], + BaseUser + >; +}; + +type ActionCallbackParameter< + T extends keyof ActionType, + TUser extends BaseUser = BaseUser, +> = ContextMap[ActionType[T]] & { user: TUser }; +type AuthCallbackParameter< + T extends keyof ResourceActionType, + TUser extends BaseUser = BaseUser, +> = ContextMap[T] & { user: TUser }; +type ResourceCallbackParameter< + T extends keyof ResourceType, + TUser extends BaseUser = BaseUser, +> = ContextMap[ResourceType[T]] & { user: TUser }; + +export type Filters = { + [key in TKey]: string | { [op in "$contains" | "$eq"]?: string }; +}; + +export interface AuthenticateCallback { + (request: Request): PromiseMaybe; +} + +type OnKey = keyof ResourceType | keyof ActionType | keyof ResourceActionType; + +type OnSingleParameter< + T extends OnKey, + TUser extends BaseUser = BaseUser, +> = T extends keyof ResourceType + ? ResourceCallbackParameter + : T extends keyof ActionType + ? ActionCallbackParameter + : T extends keyof ResourceActionType + ? AuthCallbackParameter + : never; + +type OnParameter< + T extends "*" | OnKey | OnKey[], + TUser extends BaseUser = BaseUser, +> = T extends OnKey[] + ? OnSingleParameter + : T extends "*" + ? AuthCallbackParameter + : T extends OnKey + ? OnSingleParameter + : never; + +export type AnyCallback = ( + request: CallbackParameter, +) => void | boolean | Filters; + +export type CallbackEvent = "*" | OnKey | OnKey[]; + +export type OnCallback< + T extends CallbackEvent, + TUser extends BaseUser = BaseUser, + TMetadata extends Record = Record, +> = ( + request: OnParameter, +) => void | boolean | Filters;