feat(sdk-js): add auth types

This commit is contained in:
Tat Dat Duong
2025-04-07 20:29:14 +02:00
parent 4c89bb39d4
commit c757247858
4 changed files with 347 additions and 19 deletions
+1
View File
@@ -14,6 +14,7 @@ export const config = {
entrypoints: {
index: "index",
client: "client",
auth: "auth/index",
react: "react/index",
"react-ui": "react-ui/index",
"react-ui/server": "react-ui/server/index",
+74
View File
@@ -0,0 +1,74 @@
const HTTP_STATUS_MAPPING: { [key: number]: string } = {
100: "Continue",
101: "Switching Protocols",
102: "Processing",
103: "Early Hints",
200: "OK",
201: "Created",
202: "Accepted",
203: "Non-Authoritative Information",
204: "No Content",
205: "Reset Content",
206: "Partial Content",
207: "Multi-Status",
208: "Already Reported",
226: "IM Used",
300: "Multiple Choices",
301: "Moved Permanently",
302: "Found",
303: "See Other",
304: "Not Modified",
305: "Use Proxy",
307: "Temporary Redirect",
308: "Permanent Redirect",
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Request Entity Too Large",
414: "Request-URI Too Long",
415: "Unsupported Media Type",
416: "Requested Range Not Satisfiable",
417: "Expectation Failed",
418: "I'm a Teapot",
421: "Misdirected Request",
422: "Unprocessable Entity",
423: "Locked",
424: "Failed Dependency",
425: "Too Early",
426: "Upgrade Required",
428: "Precondition Required",
429: "Too Many Requests",
431: "Request Header Fields Too Large",
451: "Unavailable For Legal Reasons",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
506: "Variant Also Negotiates",
507: "Insufficient Storage",
508: "Loop Detected",
510: "Not Extended",
511: "Network Authentication Required",
};
export class HTTPException extends Error {
status: number;
constructor(status: number, options?: { message?: string; cause?: Error }) {
super(options?.message ?? HTTP_STATUS_MAPPING[status] ?? "Unknown error", {
cause: options?.cause,
});
this.status = status;
}
}
+267
View File
@@ -0,0 +1,267 @@
type Maybe<T> = T | null | undefined;
interface AssistantConfig {
tags?: Maybe<string[]>;
recursion_limit?: Maybe<number>;
configurable?: Maybe<{
thread_id?: Maybe<string>;
thread_ts?: Maybe<number>;
[key: string]: unknown;
}>;
[key: string]: unknown;
}
interface AssistantCreate {
assistant_id?: Maybe<string>;
metadata?: Maybe<Record<string, unknown>>;
config?: Maybe<AssistantConfig>;
if_exists?: Maybe<"raise" | "do_nothing">;
name?: Maybe<string>;
graph_id: string;
}
interface AssistantRead {
assistant_id: string;
metadata?: Maybe<Record<string, unknown>>;
}
interface AssistantUpdate {
assistant_id: string;
metadata?: Maybe<Record<string, unknown>>;
config?: Maybe<AssistantConfig>;
graph_id?: Maybe<string>;
name?: Maybe<string>;
version?: Maybe<number>;
}
interface AssistantDelete {
assistant_id: string;
}
interface AssistantSearch {
graph_id?: Maybe<string>;
metadata?: Maybe<Record<string, unknown>>;
limit?: Maybe<number>;
offset?: Maybe<number>;
}
// TODO: add missing types
interface ThreadCreate {}
interface ThreadRead {}
interface ThreadUpdate {}
interface ThreadDelete {}
interface ThreadSearch {}
interface CronCreate {}
interface CronRead {}
interface CronUpdate {}
interface CronDelete {}
interface CronSearch {}
interface StorePut {}
interface StoreGet {}
interface StoreSearch {}
interface StoreListNamespaces {}
interface StoreDelete {}
interface RunsCreate {}
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 };
type Filters<TKey extends string | number | symbol = string> = {
[key in TKey]: string | { [op in "$contains" | "$eq"]?: string };
};
interface AuthenticateCallback<AuthContext extends Record<string, unknown>> {
(request: Request): AuthContext;
}
export class Auth<
Metadata extends Record<string, unknown> = {},
AuthContext extends Record<string, unknown> = {},
> {
protected __lg_type = Symbol.for("lg:auth");
"~handlerCache": {
authenticate?: AuthenticateCallback<AuthContext>;
callbacks?: Record<
string,
(request: any) => void | boolean | Filters<keyof Metadata>
>;
} = {};
authenticate(cb: AuthenticateCallback<AuthContext>): this {
this["~handlerCache"].authenticate = cb;
return this;
}
/**
* Global handler for all requests
*/
on(
event: "*",
callback: (
data: AuthCallbackParameter<keyof ResourceActionType>,
) => void | boolean | Filters<keyof Metadata>,
): this;
/**
* Resource-specific handler
*/
on<T extends keyof ResourceType>(
event: T,
callback: (
data: ResourceCallbackParameter<T, AuthContext>,
) => void | boolean | Filters<keyof Metadata>,
): this;
/**
* Action-specific handler
*/
on<T extends keyof ActionType>(
event: T,
callback: (
data: ActionCallbackParameter<T, AuthContext>,
) => void | boolean | Filters<keyof Metadata>,
): this;
/**
* Resource-action specific handler
*/
on<T extends keyof ResourceActionType>(
event: T,
callback: (
data: AuthCallbackParameter<T, AuthContext>,
) => void | boolean | Filters<keyof Metadata>,
): this;
on(
event: string,
callback: (
data: AuthCallbackParameter<keyof ResourceActionType, AuthContext>,
) => void | boolean | Filters<keyof Metadata>,
): this {
this["~handlerCache"].callbacks ??= {};
this["~handlerCache"].callbacks[event] = callback;
return this;
}
}
+5 -19
View File
@@ -2,11 +2,7 @@
"extends": "@tsconfig/recommended",
"compilerOptions": {
"target": "ES2021",
"lib": [
"ES2021",
"ES2022.Object",
"DOM"
],
"lib": ["ES2021", "ES2022.Object", "ES2022.Error", "DOM"],
"module": "NodeNext",
"moduleResolution": "nodenext",
"esModuleInterop": true,
@@ -22,24 +18,14 @@
"jsx": "react-jsx",
"outDir": "dist"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"coverage"
],
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "coverage"],
"includeVersion": true,
"typedocOptions": {
"entryPoints": [
"src/client.ts"
],
"entryPoints": ["src/client.ts"],
"readme": "none",
"out": "docs",
"plugin": [
"typedoc-plugin-markdown"
],
"plugin": ["typedoc-plugin-markdown"],
"excludePrivate": true,
"excludeProtected": true,
"excludeExternals": false