@purrkit/rest 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -2,5 +2,6 @@ import type { DiscordRestClient } from "./types";
2
2
  export interface ClientOptions {
3
3
  token: string;
4
4
  baseUrl?: string;
5
+ fetch?: (input: RequestInfo | URL | string, init?: RequestInit) => Promise<Response>;
5
6
  }
6
7
  export declare function RESTClient(options: ClientOptions): DiscordRestClient;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- function g(c){let m=c.baseUrl||"https://discord.com/api/v10",y=async(i,l,a,d)=>{let o=`${m}/${i.join("/")}`;if(d){let e=new URLSearchParams;for(let[s,t]of Object.entries(d))if(t!==void 0&&t!==null)e.append(s,String(t));let n=e.toString();if(n)o+=`?${n}`}try{let e=await fetch(o,{method:l,headers:{Authorization:`Bot ${c.token}`,"Content-Type":"application/json"},body:a?JSON.stringify(a):void 0}),n=e.ok,s=e.status,t=null;if(s!==204)t=await e.json().catch(()=>null);if(n)return{ok:!0,data:t,status:s};return{ok:!1,data:t&&typeof t==="object"&&"message"in t?t:{message:"Unknown API Error"},status:s}}catch(e){return{ok:!1,data:{message:e instanceof Error?e.message:"Network Error"},status:0}}},p=(i=[])=>{return new Proxy(()=>{},{apply(d,o,e){let n=[...i,...e.map(String)];return p(n)},get(d,o){let e=String(o);if(o==="then"){let r=y(i,"GET");return r.then.bind(r)}let n=e.toLowerCase(),s={create:"POST",post:"POST",delete:"DELETE",update:"PATCH",patch:"PATCH",put:"PUT",get:"GET"};if(n in s){let r=s[n];if(!r)throw Error(`unsupported HTTP method: ${n}`);return async(x,T)=>{let f,u;if(r==="GET"||r==="DELETE")u=x?.query;else f=x,u=T?.query;return y(i,r,f,u)}}let t=o==="me"?"@me":e;return p([...i,t])}})};return p([])}export{g as RESTClient};
2
+ function h(u){let R=u.baseUrl||"https://discord.com/api/v10",k=u.fetch??globalThis.fetch,x=async(d,m,a,c,p)=>{let i=`${R}/${d.join("/")}`;if(c){let e=new URLSearchParams;for(let[r,t]of Object.entries(c))if(t!==void 0&&t!==null)if(Array.isArray(t))for(let o of t)e.append(r,String(o));else e.append(r,String(t));let n=e.toString();if(n)i+=`?${n}`}try{let e=typeof FormData<"u"&&a instanceof FormData,n={Authorization:`Bot ${u.token}`,...p};if(!e&&!n["Content-Type"]&&a!==void 0)n["Content-Type"]="application/json";let r=await k(i,{method:m,headers:n,body:e?a:a!==void 0?JSON.stringify(a):void 0}),t=r.ok,o=r.status,s=null;if(o!==204)s=await r.json().catch(()=>null);if(t)return{ok:!0,data:s,status:o};return{ok:!1,data:s&&typeof s==="object"&&"message"in s?s:{message:"Unknown API Error"},status:o}}catch(e){return{ok:!1,data:{message:e instanceof Error?e.message:"Network Error"},status:0}}},y=(d=[])=>{return new Proxy(()=>{},{apply(c,p,i){let e=[...d,...i.map(String)];return y(e)},get(c,p){let i=String(p);if(p==="then"){let t=x(d,"GET");return t.then.bind(t)}let e=i.toLowerCase(),n={create:"POST",post:"POST",delete:"DELETE",update:"PATCH",patch:"PATCH",put:"PUT",get:"GET"};if(e in n){let t=n[e];if(!t)throw Error(`unsupported HTTP method: ${e}`);return async(o,s)=>{let l,f,g;if(t==="GET"||t==="DELETE"){let T=o;f=T?.query,g=T?.headers}else l=o,f=s?.query,g=s?.headers;return x(d,t,l,f,g)}}let r=p==="me"?"@me":i;return y([...d,r])}})};return y([])}export{h as RESTClient};
package/dist/types.d.ts CHANGED
@@ -45,10 +45,13 @@ export type ResolveResponse<Op> = Op extends {
45
45
  type MapVerb<M> = M extends "post" ? "create" | "post" : M extends "patch" ? "update" | "patch" : M extends "delete" ? "delete" : M;
46
46
  type MethodFunc<Op, Method> = Method extends "get" ? (options?: {
47
47
  query?: GetQuery<Op>;
48
+ headers?: Record<string, string>;
48
49
  }) => Promise<ResolveResponse<Op>> : [GetBody<Op>] extends [never] ? (body?: undefined, options?: {
49
50
  query?: GetQuery<Op>;
50
- }) => Promise<ResolveResponse<Op>> : (body: GetBody<Op>, options?: {
51
+ headers?: Record<string, string>;
52
+ }) => Promise<ResolveResponse<Op>> : (body: GetBody<Op> | FormData, options?: {
51
53
  query?: GetQuery<Op>;
54
+ headers?: Record<string, string>;
52
55
  }) => Promise<ResolveResponse<Op>>;
53
56
  type MapOperations<Operations> = {
54
57
  [Method in keyof Operations as MapVerb<Method>]: MethodFunc<Operations[Method], Method>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purrkit/rest",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "license": "EUPL-1.2",
5
5
  "files": [
6
6
  "dist",
@@ -20,10 +20,10 @@
20
20
  "prepublishOnly": "bun run build"
21
21
  },
22
22
  "dependencies": {
23
- "@purrkit/types": "1.1.0"
23
+ "@purrkit/types": "1.1.1"
24
24
  },
25
25
  "devDependencies": {
26
- "@types/bun": "latest"
26
+ "@types/node": "latest"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "typescript": "^5"
@@ -1 +0,0 @@
1
- export {};
@@ -1,6 +0,0 @@
1
- import type { DiscordRestClient } from "./types";
2
- export interface ClientOptions {
3
- token: string;
4
- baseUrl?: string;
5
- }
6
- export declare function RESTClient(options: ClientOptions): DiscordRestClient;
@@ -1,2 +0,0 @@
1
- export { type ClientOptions, RESTClient } from "./client";
2
- export * from "./types";
@@ -1,77 +0,0 @@
1
- import type { DiscordApiEndpoints } from "@purrkit/types";
2
- type Split<S extends string, Delimiter extends string> = S extends `${infer Head}${Delimiter}${infer Tail}` ? [Head, ...Split<Tail, Delimiter>] : S extends "" ? [] : [S];
3
- type CleanPath<S extends string> = S extends `/${infer Rest}` ? Rest : S;
4
- type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
5
- type GetQuery<Op> = Op extends {
6
- parameters: {
7
- query: infer Q;
8
- };
9
- } ? Q : never;
10
- type GetBody<Op> = Op extends {
11
- requestBody: infer B;
12
- } ? B : never;
13
- export interface DiscordError {
14
- message: string;
15
- code?: number;
16
- errors?: Record<string, unknown>;
17
- }
18
- export type ApiResponse<TSuccess, TError = DiscordError> = {
19
- ok: true;
20
- data: TSuccess;
21
- status: number & {};
22
- } | {
23
- ok: false;
24
- data: TError;
25
- status: number & {};
26
- };
27
- type IsSuccessStatus<K> = K extends number | string ? `${K}` extends `2${string}` ? true : false : false;
28
- type Discord2XX = 200 | 201 | 204;
29
- type Discord3XX = 304;
30
- type Discord4XX = 400 | 401 | 403 | 404 | 405 | 410 | 429;
31
- type Discord5XX = 500 | 502 | 503 | 504;
32
- type GetExplicitKeys<Responses> = {
33
- [K in keyof Responses]: K extends number ? K : K extends `${infer N extends number}` ? N : never;
34
- }[keyof Responses];
35
- type MapStatusType<K, ExplicitKeys> = K extends number ? K : K extends `${infer N extends number}` ? N : K extends "2XX" ? Exclude<Discord2XX, ExplicitKeys> : K extends "3XX" ? Exclude<Discord3XX, ExplicitKeys> : K extends "4XX" ? Exclude<Discord4XX, ExplicitKeys> : K extends "5XX" ? Exclude<Discord5XX, ExplicitKeys> : K extends "default" ? Exclude<Discord4XX | Discord5XX, ExplicitKeys> : number & {};
36
- export type ResolveResponse<Op> = Op extends {
37
- responses: infer Responses;
38
- } ? keyof Responses extends never ? ApiResponse<unknown> : {
39
- [K in keyof Responses]: {
40
- ok: IsSuccessStatus<K>;
41
- status: MapStatusType<K, GetExplicitKeys<Responses>>;
42
- data: Responses[K];
43
- };
44
- }[keyof Responses] : ApiResponse<unknown>;
45
- type MapVerb<M> = M extends "post" ? "create" | "post" : M extends "patch" ? "update" | "patch" : M extends "delete" ? "delete" : M;
46
- type MethodFunc<Op, Method> = Method extends "get" ? (options?: {
47
- query?: GetQuery<Op>;
48
- }) => Promise<ResolveResponse<Op>> : [GetBody<Op>] extends [never] ? (body?: undefined, options?: {
49
- query?: GetQuery<Op>;
50
- }) => Promise<ResolveResponse<Op>> : (body: GetBody<Op>, options?: {
51
- query?: GetQuery<Op>;
52
- }) => Promise<ResolveResponse<Op>>;
53
- type MapOperations<Operations> = {
54
- [Method in keyof Operations as MapVerb<Method>]: MethodFunc<Operations[Method], Method>;
55
- } & (Operations extends {
56
- get: unknown;
57
- } ? PromiseLike<ResolveResponse<Operations["get"]>> : unknown);
58
- type MapSegment<S extends string> = S extends `@${infer Rest}` ? Rest : S;
59
- type ParamKey = "$param";
60
- type BuildNested<Segments extends string[], Operations> = Segments extends [
61
- infer Head extends string,
62
- ...infer Tail extends string[]
63
- ] ? Head extends `{${string}}` ? {
64
- [K in ParamKey]: BuildNested<Tail, Operations>;
65
- } : {
66
- [K in MapSegment<Head>]: BuildNested<Tail, Operations>;
67
- } : MapOperations<Operations>;
68
- type TransformTree<T> = T extends (...args: never) => unknown ? T : T extends object ? ParamKey extends keyof T ? ((id: string) => TransformTree<T[ParamKey]>) & OmitTransform<T, ParamKey> : {
69
- [K in keyof T]: TransformTree<T[K]>;
70
- } : T;
71
- type OmitTransform<T, Key extends PropertyKey> = {
72
- [K in Exclude<keyof T, Key>]: TransformTree<T[K]>;
73
- };
74
- export type DiscordRestClient = TransformTree<UnionToIntersection<{
75
- [Path in keyof DiscordApiEndpoints]: BuildNested<Split<CleanPath<Path & string>, "/">, DiscordApiEndpoints[Path]>;
76
- }[keyof DiscordApiEndpoints]>>;
77
- export {};