entity-server-client 0.2.5 → 0.2.6

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.
Files changed (44) hide show
  1. package/README.md +0 -1
  2. package/build.mjs +4 -1
  3. package/dist/EntityServerClient.d.ts +705 -199
  4. package/dist/client/base.d.ts +59 -0
  5. package/dist/client/packet.d.ts +8 -6
  6. package/dist/client/request.d.ts +0 -1
  7. package/dist/client/utils.d.ts +5 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +4 -4
  10. package/dist/mixins/alimtalk.d.ts +56 -0
  11. package/dist/mixins/auth.d.ts +167 -0
  12. package/dist/mixins/email.d.ts +51 -0
  13. package/dist/mixins/entity.d.ts +119 -0
  14. package/dist/mixins/file.d.ts +78 -0
  15. package/dist/mixins/identity.d.ts +52 -0
  16. package/dist/mixins/pg.d.ts +63 -0
  17. package/dist/mixins/push.d.ts +110 -0
  18. package/dist/mixins/sms.d.ts +55 -0
  19. package/dist/mixins/smtp.d.ts +44 -0
  20. package/dist/mixins/utils.d.ts +70 -0
  21. package/dist/react.js +1 -1
  22. package/dist/react.js.map +4 -4
  23. package/dist/types.d.ts +165 -1
  24. package/docs/apis.md +5 -12
  25. package/docs/react.md +6 -7
  26. package/package.json +2 -1
  27. package/src/EntityServerClient.ts +54 -546
  28. package/src/client/base.ts +246 -0
  29. package/src/client/packet.ts +14 -27
  30. package/src/client/request.ts +2 -11
  31. package/src/client/utils.ts +18 -2
  32. package/src/hooks/useEntityServer.ts +3 -4
  33. package/src/mixins/alimtalk.ts +35 -0
  34. package/src/mixins/auth.ts +287 -0
  35. package/src/mixins/email.ts +46 -0
  36. package/src/mixins/entity.ts +205 -0
  37. package/src/mixins/file.ts +99 -0
  38. package/src/mixins/identity.ts +35 -0
  39. package/src/mixins/pg.ts +58 -0
  40. package/src/mixins/push.ts +132 -0
  41. package/src/mixins/sms.ts +46 -0
  42. package/src/mixins/smtp.ts +20 -0
  43. package/src/mixins/utils.ts +75 -0
  44. package/src/types.ts +203 -1
@@ -0,0 +1,55 @@
1
+ import type { SmsSendRequest } from "../types";
2
+ import type { GConstructor, EntityServerClientBase } from "../client/base";
3
+ export declare function SmsMixin<TBase extends GConstructor<EntityServerClientBase>>(Base: TBase): {
4
+ new (...args: any[]): {
5
+ /** SMS를 발송합니다. */
6
+ smsSend(req: SmsSendRequest): Promise<{
7
+ ok: boolean;
8
+ seq: number;
9
+ }>;
10
+ /** SMS 발송 상태를 조회합니다. */
11
+ smsStatus(seq: number): Promise<{
12
+ ok: boolean;
13
+ status: string;
14
+ }>;
15
+ /** SMS 인증 코드를 발송합니다. */
16
+ smsVerificationSend(phone: string, opts?: {
17
+ purpose?: string;
18
+ }): Promise<{
19
+ ok: boolean;
20
+ }>;
21
+ /** SMS 인증 코드를 검증합니다. */
22
+ smsVerificationVerify(phone: string, code: string): Promise<{
23
+ ok: boolean;
24
+ verified: boolean;
25
+ }>;
26
+ baseUrl: string;
27
+ token: string;
28
+ apiKey: string;
29
+ hmacSecret: string;
30
+ encryptRequests: boolean;
31
+ activeTxId: string | null;
32
+ keepSession: boolean;
33
+ refreshBuffer: number;
34
+ onTokenRefreshed?: (accessToken: string, expiresIn: number) => void;
35
+ onSessionExpired?: (error: Error) => void;
36
+ _sessionRefreshToken: string | null;
37
+ _refreshTimer: ReturnType<typeof setTimeout> | null;
38
+ configure(options: Partial<import("..").EntityServerClientOptions>): void;
39
+ setToken(token: string): void;
40
+ setApiKey(apiKey: string): void;
41
+ setHmacSecret(secret: string): void;
42
+ setEncryptRequests(value: boolean): void;
43
+ _scheduleKeepSession(refreshToken: string, expiresIn: number, refreshFn: (rt: string) => Promise<{
44
+ access_token: string;
45
+ expires_in: number;
46
+ }>): void;
47
+ _clearRefreshTimer(): void;
48
+ stopKeepSession(): void;
49
+ readRequestBody<T = Record<string, unknown>>(body: ArrayBuffer | Uint8Array | string | T | null | undefined, contentType?: string, requireEncrypted?: boolean): T;
50
+ get _reqOpts(): import("../client/request").RequestOptions;
51
+ _request<T>(method: string, path: string, body?: unknown, withAuth?: boolean, extraHeaders?: Record<string, string>): Promise<T>;
52
+ _requestBinary(method: string, path: string, body?: unknown, withAuth?: boolean): Promise<ArrayBuffer>;
53
+ _requestForm<T>(method: string, path: string, form: FormData, withAuth?: boolean): Promise<T>;
54
+ };
55
+ } & TBase;
@@ -0,0 +1,44 @@
1
+ import type { SmtpSendRequest } from "../types";
2
+ import type { GConstructor, EntityServerClientBase } from "../client/base";
3
+ export declare function SmtpMixin<TBase extends GConstructor<EntityServerClientBase>>(Base: TBase): {
4
+ new (...args: any[]): {
5
+ /** SMTP로 메일을 발송합니다. */
6
+ smtpSend(req: SmtpSendRequest): Promise<{
7
+ ok: boolean;
8
+ seq: number;
9
+ }>;
10
+ /** SMTP 발송 상태를 조회합니다. */
11
+ smtpStatus(seq: number): Promise<{
12
+ ok: boolean;
13
+ status: string;
14
+ }>;
15
+ baseUrl: string;
16
+ token: string;
17
+ apiKey: string;
18
+ hmacSecret: string;
19
+ encryptRequests: boolean;
20
+ activeTxId: string | null;
21
+ keepSession: boolean;
22
+ refreshBuffer: number;
23
+ onTokenRefreshed?: (accessToken: string, expiresIn: number) => void;
24
+ onSessionExpired?: (error: Error) => void;
25
+ _sessionRefreshToken: string | null;
26
+ _refreshTimer: ReturnType<typeof setTimeout> | null;
27
+ configure(options: Partial<import("..").EntityServerClientOptions>): void;
28
+ setToken(token: string): void;
29
+ setApiKey(apiKey: string): void;
30
+ setHmacSecret(secret: string): void;
31
+ setEncryptRequests(value: boolean): void;
32
+ _scheduleKeepSession(refreshToken: string, expiresIn: number, refreshFn: (rt: string) => Promise<{
33
+ access_token: string;
34
+ expires_in: number;
35
+ }>): void;
36
+ _clearRefreshTimer(): void;
37
+ stopKeepSession(): void;
38
+ readRequestBody<T = Record<string, unknown>>(body: ArrayBuffer | Uint8Array | string | T | null | undefined, contentType?: string, requireEncrypted?: boolean): T;
39
+ get _reqOpts(): import("../client/request").RequestOptions;
40
+ _request<T>(method: string, path: string, body?: unknown, withAuth?: boolean, extraHeaders?: Record<string, string>): Promise<T>;
41
+ _requestBinary(method: string, path: string, body?: unknown, withAuth?: boolean): Promise<ArrayBuffer>;
42
+ _requestForm<T>(method: string, path: string, form: FormData, withAuth?: boolean): Promise<T>;
43
+ };
44
+ } & TBase;
@@ -0,0 +1,70 @@
1
+ import type { QRCodeOptions, BarcodeOptions } from "../types";
2
+ import type { GConstructor, EntityServerClientBase } from "../client/base";
3
+ export declare function UtilsMixin<TBase extends GConstructor<EntityServerClientBase>>(Base: TBase): {
4
+ new (...args: any[]): {
5
+ /**
6
+ * QR 코드 PNG를 생성합니다. `ArrayBuffer`를 반환합니다.
7
+ *
8
+ * ```ts
9
+ * const buf = await client.qrcode("https://example.com");
10
+ * const blob = new Blob([buf], { type: "image/png" });
11
+ * img.src = URL.createObjectURL(blob);
12
+ * ```
13
+ */
14
+ qrcode(content: string, opts?: QRCodeOptions): Promise<ArrayBuffer>;
15
+ /**
16
+ * QR 코드를 base64/data URI JSON으로 반환합니다.
17
+ *
18
+ * ```ts
19
+ * const { data_uri } = await client.qrcodeBase64("https://example.com");
20
+ * img.src = data_uri;
21
+ * ```
22
+ */
23
+ qrcodeBase64(content: string, opts?: QRCodeOptions): Promise<{
24
+ ok: boolean;
25
+ data: string;
26
+ data_uri: string;
27
+ }>;
28
+ /** QR 코드를 ASCII 아트 텍스트로 반환합니다. */
29
+ qrcodeText(content: string, opts?: QRCodeOptions): Promise<{
30
+ ok: boolean;
31
+ text: string;
32
+ }>;
33
+ /**
34
+ * 바코드 PNG를 생성합니다. `ArrayBuffer`를 반환합니다.
35
+ *
36
+ * ```ts
37
+ * const buf = await client.barcode("1234567890128", { type: "ean13" });
38
+ * ```
39
+ */
40
+ barcode(content: string, opts?: BarcodeOptions): Promise<ArrayBuffer>;
41
+ baseUrl: string;
42
+ token: string;
43
+ apiKey: string;
44
+ hmacSecret: string;
45
+ encryptRequests: boolean;
46
+ activeTxId: string | null;
47
+ keepSession: boolean;
48
+ refreshBuffer: number;
49
+ onTokenRefreshed?: (accessToken: string, expiresIn: number) => void;
50
+ onSessionExpired?: (error: Error) => void;
51
+ _sessionRefreshToken: string | null;
52
+ _refreshTimer: ReturnType<typeof setTimeout> | null;
53
+ configure(options: Partial<import("..").EntityServerClientOptions>): void;
54
+ setToken(token: string): void;
55
+ setApiKey(apiKey: string): void;
56
+ setHmacSecret(secret: string): void;
57
+ setEncryptRequests(value: boolean): void;
58
+ _scheduleKeepSession(refreshToken: string, expiresIn: number, refreshFn: (rt: string) => Promise<{
59
+ access_token: string;
60
+ expires_in: number;
61
+ }>): void;
62
+ _clearRefreshTimer(): void;
63
+ stopKeepSession(): void;
64
+ readRequestBody<T = Record<string, unknown>>(body: ArrayBuffer | Uint8Array | string | T | null | undefined, contentType?: string, requireEncrypted?: boolean): T;
65
+ get _reqOpts(): import("../client/request").RequestOptions;
66
+ _request<T>(method: string, path: string, body?: unknown, withAuth?: boolean, extraHeaders?: Record<string, string>): Promise<T>;
67
+ _requestBinary(method: string, path: string, body?: unknown, withAuth?: boolean): Promise<ArrayBuffer>;
68
+ _requestForm<T>(method: string, path: string, form: FormData, withAuth?: boolean): Promise<T>;
69
+ };
70
+ } & TBase;
package/dist/react.js CHANGED
@@ -1,2 +1,2 @@
1
- import{useCallback as S,useEffect as H,useMemo as D,useRef as L,useState as B}from"react";function P(s){return import.meta?.env?.[s]}function q(s){return Object.entries(s).filter(([,e])=>e!=null).map(([e,t])=>`${encodeURIComponent(e==="orderBy"?"order_by":e)}=${encodeURIComponent(String(t))}`).join("&")}import{xchacha20poly1305 as x}from"@noble/ciphers/chacha";import{sha256 as w}from"@noble/hashes/sha2";import{hkdf as K}from"@noble/hashes/hkdf";function E(s,e){if(s){let t=new TextEncoder().encode("entity-server:hkdf:v1"),r=new TextEncoder().encode("entity-server:packet-encryption");return K(w,new TextEncoder().encode(s),t,r,32)}return w(new TextEncoder().encode(e))}function U(s,e,t){let r=new Uint8Array(t),n=new Uint8Array(24);crypto.getRandomValues(r),crypto.getRandomValues(n);let a=x(e,n).encrypt(s),o=new Uint8Array(t+24+a.length);return o.set(r,0),o.set(n,t),o.set(a,t+24),o}function R(s,e,t){let r=new Uint8Array(s);if(r.length<t+24+16)throw new Error("Encrypted packet too short");let n=r.slice(t,t+24),i=r.slice(t+24),o=x(e,n).decrypt(i);return JSON.parse(new TextDecoder().decode(o))}function I(s,e,t,r,n){let i=e.toLowerCase().includes("application/octet-stream");if(t&&!i)throw new Error("Encrypted request required: Content-Type must be application/octet-stream");if(i){if(s==null)throw new Error("Encrypted request body is empty");if(s instanceof ArrayBuffer)return R(s,r,n);if(s instanceof Uint8Array){let a=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);return R(a,r,n)}throw new Error("Encrypted request body must be ArrayBuffer or Uint8Array")}return s==null||s===""?{}:typeof s=="string"?JSON.parse(s):s}import{sha256 as M}from"@noble/hashes/sha2";import{hmac as C}from"@noble/hashes/hmac";function O(s,e,t,r,n){let i=String(Math.floor(Date.now()/1e3)),a=crypto.randomUUID(),o=new TextEncoder().encode(`${s}|${e}|${i}|${a}|`),c=new Uint8Array(o.length+t.length);c.set(o,0),c.set(t,o.length);let h=[...C(M,new TextEncoder().encode(n),c)].map(y=>y.toString(16).padStart(2,"0")).join("");return{"X-API-Key":r,"X-Timestamp":i,"X-Nonce":a,"X-Signature":h}}async function $(s,e,t,r,n=!0,i={}){let{baseUrl:a,token:o,apiKey:c,hmacSecret:f,packetMagicLen:h,encryptRequests:y}=s,b=n&&!!(c&&f),p={"Content-Type":"application/json",...i};!b&&n&&o&&(p.Authorization=`Bearer ${o}`);let l=null;if(r!=null)if(y&&n&&(o||b)&&e!=="GET"&&e!=="HEAD"){let u=E(f,o);l=U(new TextEncoder().encode(JSON.stringify(r)),u,h),p["Content-Type"]="application/octet-stream"}else l=JSON.stringify(r);if(b){let m=l instanceof Uint8Array?l:typeof l=="string"?new TextEncoder().encode(l):new Uint8Array(0);Object.assign(p,O(e,t,m,c,f))}let k=await fetch(a+t,{method:e,headers:p,...l!=null?{body:l}:{}});if((k.headers.get("Content-Type")??"").includes("application/octet-stream")){let m=E(f,o);return R(await k.arrayBuffer(),m,h)}let v=await k.json();if(!v.ok){let m=new Error(v.message??`EntityServer error (HTTP ${k.status})`);throw m.status=k.status,m}return v}var T=class{baseUrl;token;apiKey;hmacSecret;packetMagicLen;encryptRequests;activeTxId=null;keepSession;refreshBuffer;onTokenRefreshed;onSessionExpired;_sessionRefreshToken=null;_refreshTimer=null;constructor(e={}){let t=P("VITE_ENTITY_SERVER_URL"),r=P("VITE_ENTITY_SERVER_PACKET_MAGIC_LEN");this.baseUrl=(e.baseUrl??t??"http://localhost:47200").replace(/\/$/,""),this.token=e.token??"",this.apiKey=e.apiKey??"",this.hmacSecret=e.hmacSecret??"",this.packetMagicLen=e.packetMagicLen??(r?Number(r):4),this.encryptRequests=e.encryptRequests??!1,this.keepSession=e.keepSession??!1,this.refreshBuffer=e.refreshBuffer??60,this.onTokenRefreshed=e.onTokenRefreshed,this.onSessionExpired=e.onSessionExpired}configure(e){e.baseUrl&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),typeof e.token=="string"&&(this.token=e.token),typeof e.packetMagicLen=="number"&&(this.packetMagicLen=e.packetMagicLen),typeof e.encryptRequests=="boolean"&&(this.encryptRequests=e.encryptRequests),typeof e.apiKey=="string"&&(this.apiKey=e.apiKey),typeof e.hmacSecret=="string"&&(this.hmacSecret=e.hmacSecret),typeof e.keepSession=="boolean"&&(this.keepSession=e.keepSession),typeof e.refreshBuffer=="number"&&(this.refreshBuffer=e.refreshBuffer),e.onTokenRefreshed&&(this.onTokenRefreshed=e.onTokenRefreshed),e.onSessionExpired&&(this.onSessionExpired=e.onSessionExpired)}setToken(e){this.token=e}setApiKey(e){this.apiKey=e}setHmacSecret(e){this.hmacSecret=e}setPacketMagicLen(e){this.packetMagicLen=e}getPacketMagicLen(){return this.packetMagicLen}_scheduleKeepSession(e,t){this._clearRefreshTimer(),this._sessionRefreshToken=e;let r=Math.max((t-this.refreshBuffer)*1e3,0);this._refreshTimer=setTimeout(async()=>{if(this._sessionRefreshToken)try{let n=await this.refreshToken(this._sessionRefreshToken);this.onTokenRefreshed?.(n.access_token,n.expires_in),this._scheduleKeepSession(this._sessionRefreshToken,n.expires_in)}catch(n){this._clearRefreshTimer(),this.onSessionExpired?.(n instanceof Error?n:new Error(String(n)))}},r)}_clearRefreshTimer(){this._refreshTimer!==null&&(clearTimeout(this._refreshTimer),this._refreshTimer=null)}stopKeepSession(){this._clearRefreshTimer(),this._sessionRefreshToken=null}async checkHealth(){let t=await(await fetch(`${this.baseUrl}/v1/health`,{signal:AbortSignal.timeout(3e3)})).json();return t.packet_encryption&&(this.encryptRequests=!0),t}async login(e,t){let r=await this.request("POST","/v1/auth/login",{email:e,passwd:t},!1);return this.token=r.data.access_token,this.keepSession&&this._scheduleKeepSession(r.data.refresh_token,r.data.expires_in),r.data}async refreshToken(e){let t=await this.request("POST","/v1/auth/refresh",{refresh_token:e},!1);return this.token=t.data.access_token,this.keepSession&&this._scheduleKeepSession(e,t.data.expires_in),t.data}async logout(e){this.stopKeepSession();let t=await this.request("POST","/v1/auth/logout",{refresh_token:e},!1);return this.token="",t}async transStart(){let e=await this.request("POST","/v1/transaction/start",void 0,!1);return this.activeTxId=e.transaction_id,this.activeTxId}transRollback(e){let t=e??this.activeTxId;return t?(this.activeTxId=null,this.request("POST",`/v1/transaction/rollback/${t}`)):Promise.reject(new Error("No active transaction. Call transStart() first."))}transCommit(e){let t=e??this.activeTxId;return t?(this.activeTxId=null,this.request("POST",`/v1/transaction/commit/${t}`)):Promise.reject(new Error("No active transaction. Call transStart() first."))}get(e,t,r={}){let n=r.skipHooks?"?skipHooks=true":"";return this.request("GET",`/v1/entity/${e}/${t}${n}`)}find(e,t,r={}){let n=r.skipHooks?"?skipHooks=true":"";return this.request("POST",`/v1/entity/${e}/find${n}`,t??{})}list(e,t={}){let{conditions:r,fields:n,orderDir:i,orderBy:a,...o}=t,c={page:1,limit:20,...o};return a&&(c.orderBy=i==="DESC"?`-${a}`:a),n?.length&&(c.fields=n.join(",")),this.request("POST",`/v1/entity/${e}/list?${q(c)}`,r??{})}count(e,t){return this.request("POST",`/v1/entity/${e}/count`,t??{})}query(e,t){return this.request("POST",`/v1/entity/${e}/query`,t)}submit(e,t,r={}){let n=r.transactionId??this.activeTxId,i=n?{"X-Transaction-ID":n}:void 0,a=r.skipHooks?"?skipHooks=true":"";return this.request("POST",`/v1/entity/${e}/submit${a}`,t,!0,i)}delete(e,t,r={}){let n=new URLSearchParams;r.hard&&n.set("hard","true"),r.skipHooks&&n.set("skipHooks","true");let i=n.size?`?${n}`:"",a=r.transactionId??this.activeTxId,o=a?{"X-Transaction-ID":a}:void 0;return this.request("POST",`/v1/entity/${e}/delete/${t}${i}`,void 0,!0,o)}history(e,t,r={}){return this.request("GET",`/v1/entity/${e}/history/${t}?${q({page:1,limit:50,...r})}`)}rollback(e,t){return this.request("POST",`/v1/entity/${e}/rollback/${t}`)}push(e,t,r={}){return this.submit(e,t,r)}pushLogList(e={}){return this.list("push_log",e)}registerPushDevice(e,t,r,n={}){let{platform:i,deviceType:a,browser:o,browserVersion:c,pushEnabled:f=!0,transactionId:h}=n;return this.submit("account_device",{id:t,account_seq:e,push_token:r,push_enabled:f,...i?{platform:i}:{},...a?{device_type:a}:{},...o?{browser:o}:{},...c?{browser_version:c}:{}},{transactionId:h})}updatePushDeviceToken(e,t,r={}){let{pushEnabled:n=!0,transactionId:i}=r;return this.submit("account_device",{seq:e,push_token:t,push_enabled:n},{transactionId:i})}disablePushDevice(e,t={}){return this.submit("account_device",{seq:e,push_enabled:!1},{transactionId:t.transactionId})}readRequestBody(e,t="application/json",r=!1){let n=E(this.hmacSecret,this.token);return I(e,t,r,n,this.packetMagicLen)}get _reqOpts(){return{baseUrl:this.baseUrl,token:this.token,apiKey:this.apiKey,hmacSecret:this.hmacSecret,packetMagicLen:this.packetMagicLen,encryptRequests:this.encryptRequests}}request(e,t,r,n=!0,i){return $(this._reqOpts,e,t,r,n,i)}};var A=new T;function ue(s={}){let{singleton:e=!0,tokenResolver:t,baseUrl:r,packetMagicLen:n,token:i,resumeSession:a}=s,[o,c]=B(!1),[f,h]=B(null),y=L(!0);H(()=>(y.current=!0,()=>{y.current=!1}),[]);let b=L(a);H(()=>{let u=b.current;u&&p.refreshToken(u).catch(()=>{})},[]);let p=D(()=>{let u=e?A:new T({baseUrl:r,packetMagicLen:n,token:i});e&&u.configure({baseUrl:r,packetMagicLen:n,token:i});let d=t?.();return typeof d=="string"&&u.setToken(d),u},[e,t,r,n,i]),l=S(async u=>{y.current&&(c(!0),h(null));try{return await u()}catch(d){let g=d instanceof Error?d:new Error(String(d));throw y.current&&h(g),g}finally{y.current&&c(!1)}},[]),k=S((u,d,g)=>l(()=>p.submit(u,d,g)),[p,l]),_=S((u,d,g)=>l(()=>p.delete(u,d,g)),[p,l]),v=S((u,d)=>l(()=>p.query(u,d)),[p,l]),m=S(()=>{c(!1),h(null)},[]);return{client:p,isPending:o,error:f,reset:m,submit:k,del:_,query:v}}export{ue as useEntityServer};
1
+ import{useCallback as S,useEffect as V,useMemo as Y,useRef as Q,useState as N}from"react";function E(n){let r=import.meta;if(r?.env?.[n]!=null)return r.env[n];if(typeof process<"u"&&process.env&&process.env[n]!=null)return process.env[n]}function _(n){return Object.entries(n).filter(([,r])=>r!=null).map(([r,e])=>`${encodeURIComponent(r==="orderBy"?"order_by":r)}=${encodeURIComponent(String(e))}`).join("&")}import{xchacha20poly1305 as R}from"@noble/ciphers/chacha";import{sha256 as X}from"@noble/hashes/sha2";import{hkdf as J}from"@noble/hashes/hkdf";function P(n,r){let e=n||r,t=new TextEncoder().encode("entity-server:hkdf:v1"),s=new TextEncoder().encode("entity-server:packet-encryption");return J(X,new TextEncoder().encode(e),t,s,32)}function w(n,r){let e=2+r[31]%14,t=new Uint8Array(e),s=new Uint8Array(24);crypto.getRandomValues(t),crypto.getRandomValues(s);let a=R(r,s).encrypt(n),o=new Uint8Array(e+24+a.length);return o.set(t,0),o.set(s,e),o.set(a,e+24),o}function v(n,r){let e=2+r[31]%14,t=new Uint8Array(n);if(t.length<e+24+16)throw new Error("Encrypted packet too short");let s=t.slice(e,e+24),i=t.slice(e+24),o=R(r,s).decrypt(i);return JSON.parse(new TextDecoder().decode(o))}function C(n,r,e,t){let s=r.toLowerCase().includes("application/octet-stream");if(e&&!s)throw new Error("Encrypted request required: Content-Type must be application/octet-stream");if(s){if(n==null)throw new Error("Encrypted request body is empty");if(n instanceof ArrayBuffer)return v(n,t);if(n instanceof Uint8Array){let i=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return v(i,t)}throw new Error("Encrypted request body must be ArrayBuffer or Uint8Array")}return n==null||n===""?{}:typeof n=="string"?JSON.parse(n):n}import{sha256 as z}from"@noble/hashes/sha2";import{hmac as W}from"@noble/hashes/hmac";function O(n,r,e,t,s){let i=String(Math.floor(Date.now()/1e3)),a=crypto.randomUUID(),o=new TextEncoder().encode(`${n}|${r}|${i}|${a}|`),u=new Uint8Array(o.length+e.length);u.set(o,0),u.set(e,o.length);let f=[...W(z,new TextEncoder().encode(s),u)].map(h=>h.toString(16).padStart(2,"0")).join("");return{"X-API-Key":t,"X-Timestamp":i,"X-Nonce":a,"X-Signature":f}}async function B(n,r,e,t,s=!0,i={}){let{baseUrl:a,token:o,apiKey:u,hmacSecret:c,encryptRequests:f}=n,h=s&&!!(u&&c),d={"Content-Type":"application/json",...i};!h&&s&&o&&(d.Authorization=`Bearer ${o}`);let m=null;if(t!=null)if(f&&s&&(o||h)&&r!=="GET"&&r!=="HEAD"){let l=P(c,o);m=w(new TextEncoder().encode(JSON.stringify(t)),l),d["Content-Type"]="application/octet-stream"}else m=JSON.stringify(t);if(h){let y=m instanceof Uint8Array?m:typeof m=="string"?new TextEncoder().encode(m):new Uint8Array(0);Object.assign(d,O(r,e,y,u,c))}let g=await fetch(a+e,{method:r,headers:d,...m!=null?{body:m}:{}});if((g.headers.get("Content-Type")??"").includes("application/octet-stream")){let y=P(c,o);return v(await g.arrayBuffer(),y)}let b=await g.json();if(!b.ok){let y=new Error(b.message??`EntityServer error (HTTP ${g.status})`);throw y.status=g.status,y}return b}var q=class{baseUrl;token;apiKey;hmacSecret;encryptRequests;activeTxId=null;keepSession;refreshBuffer;onTokenRefreshed;onSessionExpired;_sessionRefreshToken=null;_refreshTimer=null;constructor(r={}){let e=E("VITE_ENTITY_SERVER_URL");this.baseUrl=(r.baseUrl??e??"http://localhost:47200").replace(/\/$/,""),this.token=r.token??"",this.apiKey=r.apiKey??"",this.hmacSecret=r.hmacSecret??"",this.encryptRequests=r.encryptRequests??!1,this.keepSession=r.keepSession??!1,this.refreshBuffer=r.refreshBuffer??60,this.onTokenRefreshed=r.onTokenRefreshed,this.onSessionExpired=r.onSessionExpired}configure(r){r.baseUrl&&(this.baseUrl=r.baseUrl.replace(/\/$/,"")),typeof r.token=="string"&&(this.token=r.token),typeof r.encryptRequests=="boolean"&&(this.encryptRequests=r.encryptRequests),typeof r.apiKey=="string"&&(this.apiKey=r.apiKey),typeof r.hmacSecret=="string"&&(this.hmacSecret=r.hmacSecret),typeof r.keepSession=="boolean"&&(this.keepSession=r.keepSession),typeof r.refreshBuffer=="number"&&(this.refreshBuffer=r.refreshBuffer),r.onTokenRefreshed&&(this.onTokenRefreshed=r.onTokenRefreshed),r.onSessionExpired&&(this.onSessionExpired=r.onSessionExpired)}setToken(r){this.token=r}setApiKey(r){this.apiKey=r}setHmacSecret(r){this.hmacSecret=r}setEncryptRequests(r){this.encryptRequests=r}_scheduleKeepSession(r,e,t){this._clearRefreshTimer(),this._sessionRefreshToken=r;let s=Math.max((e-this.refreshBuffer)*1e3,0);this._refreshTimer=setTimeout(async()=>{if(this._sessionRefreshToken)try{let i=await t(this._sessionRefreshToken);this.onTokenRefreshed?.(i.access_token,i.expires_in),this._scheduleKeepSession(this._sessionRefreshToken,i.expires_in,t)}catch(i){this._clearRefreshTimer(),this.onSessionExpired?.(i instanceof Error?i:new Error(String(i)))}},s)}_clearRefreshTimer(){this._refreshTimer!==null&&(clearTimeout(this._refreshTimer),this._refreshTimer=null)}stopKeepSession(){this._clearRefreshTimer(),this._sessionRefreshToken=null}readRequestBody(r,e="application/json",t=!1){let s=P(this.hmacSecret,this.token);return C(r,e,t,s)}get _reqOpts(){return{baseUrl:this.baseUrl,token:this.token,apiKey:this.apiKey,hmacSecret:this.hmacSecret,encryptRequests:this.encryptRequests}}_request(r,e,t,s=!0,i){return B(this._reqOpts,r,e,t,s,i)}async _requestBinary(r,e,t,s=!0){let i={"Content-Type":"application/json"};s&&this.token&&(i.Authorization=`Bearer ${this.token}`),this.apiKey&&(i["X-API-Key"]=this.apiKey);let a=await fetch(this.baseUrl+e,{method:r,headers:i,...t!=null?{body:JSON.stringify(t)}:{}});if(!a.ok){let o=await a.text(),u=new Error(`HTTP ${a.status}: ${o}`);throw u.status=a.status,u}return a.arrayBuffer()}async _requestForm(r,e,t,s=!0){let i={};s&&this.token&&(i.Authorization=`Bearer ${this.token}`),this.apiKey&&(i["X-API-Key"]=this.apiKey);let a=await fetch(this.baseUrl+e,{method:r,headers:i,body:t}),o=await a.json();if(!o.ok){let u=new Error(o.message??`EntityServer error (HTTP ${a.status})`);throw u.status=a.status,u}return o}};function $(n){return class extends n{async checkHealth(){let t=await(await fetch(`${this.baseUrl}/v1/health`,{signal:AbortSignal.timeout(3e3)})).json();return t.packet_encryption&&(this.encryptRequests=!0),t}async login(e,t){let s=await this._request("POST","/v1/auth/login",{email:e,passwd:t},!1);return this.token=s.data.access_token,this.keepSession&&this._scheduleKeepSession(s.data.refresh_token,s.data.expires_in,i=>this.refreshToken(i)),s.data}async refreshToken(e){let t=await this._request("POST","/v1/auth/refresh",{refresh_token:e},!1);return this.token=t.data.access_token,this.keepSession&&this._scheduleKeepSession(e,t.data.expires_in,s=>this.refreshToken(s)),t.data}async logout(e){this.stopKeepSession();let t=await this._request("POST","/v1/auth/logout",{refresh_token:e},!1);return this.token="",t}me(){return this._request("GET","/v1/auth/me")}changePassword(e,t){return this._request("POST","/v1/auth/change-password",{current_passwd:e,new_passwd:t})}withdraw(e){return this._request("POST","/v1/auth/withdraw",e?{passwd:e}:{})}reactivate(e){return this._request("POST","/v1/auth/reactivate",e,!1)}passwordResetRequest(e){return this._request("POST","/v1/auth/password-reset",{email:e},!1)}passwordResetConfirm(e,t){return this._request("POST","/v1/auth/password-reset/confirm",{token:e,new_passwd:t},!1)}oauthLink(e,t,s){return this._request("POST","/v1/auth/oauth/link",{provider:e,code:t,...s?{state:s}:{}})}oauthUnlink(e){return this._request("DELETE",`/v1/auth/oauth/link/${e}`)}oauthProviders(){return this._request("GET","/v1/auth/oauth/providers")}oauthTokenRefresh(e){return this._request("POST",`/v1/auth/oauth/refresh/${e}`)}twoFactorSetup(){return this._request("POST","/v1/auth/2fa/setup")}twoFactorSetupVerify(e,t){return this._request("POST","/v1/auth/2fa/setup/verify",{code:e,setup_token:t})}twoFactorDisable(e){return this._request("DELETE","/v1/auth/2fa",{code:e})}twoFactorStatus(){return this._request("GET","/v1/auth/2fa/status")}twoFactorVerify(e,t){return this._request("POST","/v1/auth/2fa/verify",{two_factor_token:e,code:t},!1)}twoFactorRecovery(e,t){return this._request("POST","/v1/auth/2fa/recovery",{two_factor_token:e,recovery_code:t},!1)}twoFactorRegenerateRecovery(e){return this._request("POST","/v1/auth/2fa/recovery/regenerate",{code:e})}}}function U(n){return class extends n{async transStart(){let e=await this._request("POST","/v1/transaction/start",void 0,!1);return this.activeTxId=e.transaction_id,this.activeTxId}transRollback(e){let t=e??this.activeTxId;return t?(this.activeTxId=null,this._request("POST",`/v1/transaction/rollback/${t}`)):Promise.reject(new Error("No active transaction. Call transStart() first."))}transCommit(e){let t=e??this.activeTxId;return t?(this.activeTxId=null,this._request("POST",`/v1/transaction/commit/${t}`)):Promise.reject(new Error("No active transaction. Call transStart() first."))}get(e,t,s={}){let i=s.skipHooks?"?skipHooks=true":"";return this._request("GET",`/v1/entity/${e}/${t}${i}`)}find(e,t,s={}){let i=s.skipHooks?"?skipHooks=true":"";return this._request("POST",`/v1/entity/${e}/find${i}`,t??{})}list(e,t={}){let{conditions:s,fields:i,orderDir:a,orderBy:o,...u}=t,c={page:1,limit:20,...u};return o&&(c.orderBy=a==="DESC"?`-${o}`:o),i?.length&&(c.fields=i.join(",")),this._request("POST",`/v1/entity/${e}/list?${_(c)}`,s??{})}count(e,t){return this._request("POST",`/v1/entity/${e}/count`,t??{})}query(e,t){return this._request("POST",`/v1/entity/${e}/query`,t)}submit(e,t,s={}){let i=s.transactionId??this.activeTxId,a=i?{"X-Transaction-ID":i}:void 0,o=s.skipHooks?"?skipHooks=true":"";return this._request("POST",`/v1/entity/${e}/submit${o}`,t,!0,a)}delete(e,t,s={}){let i=new URLSearchParams;s.hard&&i.set("hard","true"),s.skipHooks&&i.set("skipHooks","true");let a=i.size?`?${i}`:"",o=s.transactionId??this.activeTxId,u=o?{"X-Transaction-ID":o}:void 0;return this._request("POST",`/v1/entity/${e}/delete/${t}${a}`,void 0,!0,u)}history(e,t,s={}){return this._request("GET",`/v1/entity/${e}/history/${t}?${_({page:1,limit:50,...s})}`)}rollback(e,t){return this._request("POST",`/v1/entity/${e}/rollback/${t}`)}}}function A(n){return class extends n{push(e,t,s={}){return this.submit(e,t,s)}pushLogList(e={}){return this.list("push_log",e)}registerPushDevice(e,t,s,i={}){let{platform:a,deviceType:o,browser:u,browserVersion:c,pushEnabled:f=!0,transactionId:h}=i;return this.submit("account_device",{id:t,account_seq:e,push_token:s,push_enabled:f,...a?{platform:a}:{},...o?{device_type:o}:{},...u?{browser:u}:{},...c?{browser_version:c}:{}},{transactionId:h})}updatePushDeviceToken(e,t,s={}){let{pushEnabled:i=!0,transactionId:a}=s;return this.submit("account_device",{seq:e,push_token:t,push_enabled:i},{transactionId:a})}disablePushDevice(e,t={}){return this.submit("account_device",{seq:e,push_enabled:!1},{transactionId:t.transactionId})}pushSend(e){return this._request("POST","/v1/push/send",e)}pushSendAll(e){return this._request("POST","/v1/push/send-all",e)}pushStatus(e){return this._request("POST",`/v1/push/status/${e}`,{})}}}function I(n){return class extends n{emailVerificationSend(e){return this._request("POST","/v1/email/verification/send",{email:e},!1)}emailVerificationConfirm(e){return this._request("POST","/v1/email/verification/confirm",{token:e},!1)}emailVerificationStatus(){return this._request("GET","/v1/email/verification/status")}emailChange(e,t){return this._request("POST","/v1/email/change",{new_email:e,...t?{code:t}:{}})}}}function M(n){return class extends n{smsSend(e){return this._request("POST","/v1/sms/send",e)}smsStatus(e){return this._request("GET",`/v1/sms/status/${e}`)}smsVerificationSend(e,t={}){return this._request("POST","/v1/sms/verification/send",{phone:e,...t},!1)}smsVerificationVerify(e,t){return this._request("POST","/v1/sms/verification/verify",{phone:e,code:t},!1)}}}function G(n){return class extends n{smtpSend(e){return this._request("POST","/v1/smtp/send",e)}smtpStatus(e){return this._request("POST",`/v1/smtp/status/${e}`,{})}}}function H(n){return class extends n{alimtalkSend(e){return this._request("POST","/v1/alimtalk/send",e)}alimtalkStatus(e){return this._request("GET",`/v1/alimtalk/status/${e}`)}alimtalkTemplates(){return this._request("GET","/v1/alimtalk/templates")}friendtalkSend(e){return this._request("POST","/v1/friendtalk/send",e)}}}function K(n){return class extends n{pgCreateOrder(e){return this._request("POST","/v1/pg/orders",e)}pgGetOrder(e){return this._request("GET",`/v1/pg/orders/${e}`)}pgConfirmPayment(e){return this._request("POST","/v1/pg/confirm",e)}pgCancelPayment(e,t){return this._request("POST",`/v1/pg/orders/${e}/cancel`,t)}pgSyncPayment(e){return this._request("POST",`/v1/pg/orders/${e}/sync`,{})}pgConfig(){return this._request("GET","/v1/pg/config",void 0,!1)}}}function L(n){return class extends n{async fileUpload(e,t,s={}){let i=new FormData;return i.append("file",t,t instanceof File?t.name:"upload"),s.refSeq!=null&&i.append("ref_seq",String(s.refSeq)),s.isPublic!=null&&i.append("is_public",s.isPublic?"true":"false"),this._requestForm("POST",`/v1/files/${e}/upload`,i)}fileDownload(e,t){return this._requestBinary("POST",`/v1/files/${e}/download/${t}`,{})}fileDelete(e,t){return this._request("POST",`/v1/files/${e}/delete/${t}`,{})}fileList(e,t={}){return this._request("POST",`/v1/files/${e}/list`,t.refSeq?{ref_seq:t.refSeq}:{})}fileMeta(e,t){return this._request("POST",`/v1/files/${e}/meta/${t}`,{})}fileToken(e){return this._request("POST",`/v1/files/token/${e}`,{})}fileUrl(e){return`${this.baseUrl}/v1/files/${e}`}}}function F(n){return class extends n{identityRequest(e){return this._request("POST","/v1/identity/request",e)}identityResult(e){return this._request("GET",`/v1/identity/result/${e}`)}identityVerifyCI(e){return this._request("POST","/v1/identity/verify-ci",{ci_hash:e})}}}function D(n){return class extends n{qrcode(e,t={}){return this._requestBinary("POST","/v1/utils/qrcode",{content:e,...t})}qrcodeBase64(e,t={}){return this._request("POST","/v1/utils/qrcode/base64",{content:e,...t})}qrcodeText(e,t={}){return this._request("POST","/v1/utils/qrcode/text",{content:e,...t})}barcode(e,t={}){return this._requestBinary("POST","/v1/utils/barcode",{content:e,...t})}}}var T=class extends D(F(L(K(H(G(M(I(A(U($(q))))))))))){};var j=new T;function rt(n={}){let{singleton:r=!0,tokenResolver:e,baseUrl:t,token:s,resumeSession:i}=n,[a,o]=N(!1),[u,c]=N(null),f=Q(!0);V(()=>(f.current=!0,()=>{f.current=!1}),[]);let h=Q(i);V(()=>{let l=h.current;l&&d.refreshToken(l).catch(()=>{})},[]);let d=Y(()=>{let l=r?j:new T({baseUrl:t,token:s});r&&l.configure({baseUrl:t,token:s});let p=e?.();return typeof p=="string"&&l.setToken(p),l},[r,e,t,s]),m=S(async l=>{f.current&&(o(!0),c(null));try{return await l()}catch(p){let k=p instanceof Error?p:new Error(String(p));throw f.current&&c(k),k}finally{f.current&&o(!1)}},[]),g=S((l,p,k)=>m(()=>d.submit(l,p,k)),[d,m]),x=S((l,p,k)=>m(()=>d.delete(l,p,k)),[d,m]),b=S((l,p)=>m(()=>d.query(l,p)),[d,m]),y=S(()=>{o(!1),c(null)},[]);return{client:d,isPending:a,error:u,reset:y,submit:g,del:x,query:b}}export{rt as useEntityServer};
2
2
  //# sourceMappingURL=react.js.map