entity-server-client 0.3.2 → 1.0.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/EntityServerClient.d.ts +432 -0
- package/dist/client/base.d.ts +84 -0
- package/dist/client/hmac.d.ts +8 -0
- package/dist/client/packet.d.ts +24 -0
- package/dist/client/request.d.ts +16 -0
- package/dist/client/utils.d.ts +8 -0
- package/dist/hooks/useEntityServer.d.ts +63 -0
- package/{src/index.ts → dist/index.d.ts} +1 -3
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/mixins/alimtalk.d.ts +56 -0
- package/dist/mixins/auth.d.ts +100 -0
- package/dist/mixins/email.d.ts +51 -0
- package/dist/mixins/entity.d.ts +126 -0
- package/dist/mixins/file.d.ts +85 -0
- package/dist/mixins/identity.d.ts +52 -0
- package/dist/mixins/llm.d.ts +94 -0
- package/dist/mixins/pg.d.ts +63 -0
- package/dist/mixins/push.d.ts +101 -0
- package/dist/mixins/sms.d.ts +55 -0
- package/dist/mixins/smtp.d.ts +51 -0
- package/dist/mixins/utils.d.ts +88 -0
- package/dist/packet.d.ts +11 -0
- package/dist/packet.js +2 -0
- package/dist/packet.js.map +7 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +7 -0
- package/{src/types.ts → dist/types.d.ts} +2 -42
- package/package.json +9 -36
- package/LICENSE +0 -21
- package/README.md +0 -128
- package/build.mjs +0 -36
- package/docs/api/alimtalk.md +0 -62
- package/docs/api/auth.md +0 -256
- package/docs/api/email.md +0 -37
- package/docs/api/entity.md +0 -273
- package/docs/api/file.md +0 -80
- package/docs/api/health.md +0 -47
- package/docs/api/identity.md +0 -32
- package/docs/api/import.md +0 -45
- package/docs/api/packet.md +0 -90
- package/docs/api/pg.md +0 -90
- package/docs/api/push.md +0 -107
- package/docs/api/react.md +0 -141
- package/docs/api/request.md +0 -118
- package/docs/api/setup.md +0 -43
- package/docs/api/sms.md +0 -45
- package/docs/api/smtp.md +0 -33
- package/docs/api/transaction.md +0 -50
- package/docs/api/utils.md +0 -52
- package/docs/apis.md +0 -26
- package/docs/react.md +0 -137
- package/src/EntityServerClient.ts +0 -28
- package/src/client/base.ts +0 -348
- package/src/client/hmac.ts +0 -41
- package/src/client/packet.ts +0 -77
- package/src/client/request.ts +0 -139
- package/src/client/utils.ts +0 -33
- package/src/hooks/useEntityServer.ts +0 -154
- package/src/mixins/auth.ts +0 -143
- package/src/mixins/entity.ts +0 -205
- package/src/mixins/file.ts +0 -99
- package/src/mixins/push.ts +0 -109
- package/src/mixins/smtp.ts +0 -20
- package/src/mixins/utils.ts +0 -106
- package/src/packet.ts +0 -84
- package/tests/packet.test.mjs +0 -50
- package/tsconfig.json +0 -14
- /package/{src/react.ts → dist/react.d.ts} +0 -0
package/src/mixins/push.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
EntityListParams,
|
|
3
|
-
EntityListResult,
|
|
4
|
-
RegisterPushDeviceOptions,
|
|
5
|
-
} from "../types";
|
|
6
|
-
import type { GConstructor, EntityServerClientBase } from "../client/base";
|
|
7
|
-
|
|
8
|
-
// entity submit을 가진 base 타입 (EntityMixin 적용 후)
|
|
9
|
-
type WithSubmit = EntityServerClientBase & {
|
|
10
|
-
submit(
|
|
11
|
-
entity: string,
|
|
12
|
-
data: Record<string, unknown>,
|
|
13
|
-
opts?: { transactionId?: string; skipHooks?: boolean },
|
|
14
|
-
): Promise<{ ok: boolean; seq: number }>;
|
|
15
|
-
list<T = unknown>(
|
|
16
|
-
entity: string,
|
|
17
|
-
params?: EntityListParams,
|
|
18
|
-
): Promise<{ ok: boolean; data: EntityListResult<T> }>;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export function PushMixin<TBase extends GConstructor<WithSubmit>>(Base: TBase) {
|
|
22
|
-
return class PushMixinClass extends Base {
|
|
23
|
-
// ─── 푸시 submit 래퍼 ────────────────────────────────────────────────
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 푸시 관련 엔티티로 payload를 전송(Submit)합니다.
|
|
27
|
-
* 내부적으로 `submit()` 메서드를 호출합니다.
|
|
28
|
-
*/
|
|
29
|
-
push(
|
|
30
|
-
pushEntity: string,
|
|
31
|
-
payload: Record<string, unknown>,
|
|
32
|
-
opts: { transactionId?: string } = {},
|
|
33
|
-
): Promise<{ ok: boolean; seq: number }> {
|
|
34
|
-
return this.submit(pushEntity, payload, opts);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ─── 푸시 디바이스 관리 ───────────────────────────────────────────────
|
|
38
|
-
|
|
39
|
-
/** 푸시 로그 엔티티 목록을 조회합니다. */
|
|
40
|
-
pushLogList<T = unknown>(
|
|
41
|
-
params: EntityListParams = {},
|
|
42
|
-
): Promise<{ ok: boolean; data: EntityListResult<T> }> {
|
|
43
|
-
return this.list<T>("push_log", params);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** 계정의 푸시 디바이스를 등록합니다. */
|
|
47
|
-
registerPushDevice(
|
|
48
|
-
accountSeq: number,
|
|
49
|
-
deviceId: string,
|
|
50
|
-
pushToken: string,
|
|
51
|
-
opts: RegisterPushDeviceOptions = {},
|
|
52
|
-
): Promise<{ ok: boolean; seq: number }> {
|
|
53
|
-
const {
|
|
54
|
-
platform,
|
|
55
|
-
deviceType,
|
|
56
|
-
browser,
|
|
57
|
-
browserVersion,
|
|
58
|
-
pushEnabled = true,
|
|
59
|
-
transactionId,
|
|
60
|
-
} = opts;
|
|
61
|
-
return this.submit(
|
|
62
|
-
"account_device",
|
|
63
|
-
{
|
|
64
|
-
id: deviceId,
|
|
65
|
-
account_seq: accountSeq,
|
|
66
|
-
push_token: pushToken,
|
|
67
|
-
push_enabled: pushEnabled,
|
|
68
|
-
...(platform ? { platform } : {}),
|
|
69
|
-
...(deviceType ? { device_type: deviceType } : {}),
|
|
70
|
-
...(browser ? { browser } : {}),
|
|
71
|
-
...(browserVersion
|
|
72
|
-
? { browser_version: browserVersion }
|
|
73
|
-
: {}),
|
|
74
|
-
},
|
|
75
|
-
{ transactionId },
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** 디바이스 레코드의 푸시 토큰을 갱신합니다. */
|
|
80
|
-
updatePushDeviceToken(
|
|
81
|
-
deviceSeq: number,
|
|
82
|
-
pushToken: string,
|
|
83
|
-
opts: { pushEnabled?: boolean; transactionId?: string } = {},
|
|
84
|
-
): Promise<{ ok: boolean; seq: number }> {
|
|
85
|
-
const { pushEnabled = true, transactionId } = opts;
|
|
86
|
-
return this.submit(
|
|
87
|
-
"account_device",
|
|
88
|
-
{
|
|
89
|
-
seq: deviceSeq,
|
|
90
|
-
push_token: pushToken,
|
|
91
|
-
push_enabled: pushEnabled,
|
|
92
|
-
},
|
|
93
|
-
{ transactionId },
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** 디바이스의 푸시 수신을 비활성화합니다. */
|
|
98
|
-
disablePushDevice(
|
|
99
|
-
deviceSeq: number,
|
|
100
|
-
opts: { transactionId?: string } = {},
|
|
101
|
-
): Promise<{ ok: boolean; seq: number }> {
|
|
102
|
-
return this.submit(
|
|
103
|
-
"account_device",
|
|
104
|
-
{ seq: deviceSeq, push_enabled: false },
|
|
105
|
-
{ transactionId: opts.transactionId },
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
package/src/mixins/smtp.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { SmtpSendRequest } from "../types";
|
|
2
|
-
import type { GConstructor, EntityServerClientBase } from "../client/base";
|
|
3
|
-
|
|
4
|
-
export function SmtpMixin<TBase extends GConstructor<EntityServerClientBase>>(
|
|
5
|
-
Base: TBase,
|
|
6
|
-
) {
|
|
7
|
-
return class SmtpMixinClass extends Base {
|
|
8
|
-
// ─── SMTP 메일 발송 ───────────────────────────────────────────────────
|
|
9
|
-
|
|
10
|
-
/** SMTP로 메일을 발송합니다. */
|
|
11
|
-
smtpSend(req: SmtpSendRequest): Promise<{ ok: boolean; seq: number }> {
|
|
12
|
-
return this._request("POST", "/v1/smtp/send", req);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** SMTP 발송 상태를 조회합니다. */
|
|
16
|
-
smtpStatus(seq: number): Promise<{ ok: boolean; status: string }> {
|
|
17
|
-
return this._request("POST", `/v1/smtp/status/${seq}`, {});
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
}
|
package/src/mixins/utils.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import type { QRCodeOptions, BarcodeOptions, Pdf2PngOptions } from "../types";
|
|
2
|
-
import type { GConstructor, EntityServerClientBase } from "../client/base";
|
|
3
|
-
|
|
4
|
-
export function UtilsMixin<TBase extends GConstructor<EntityServerClientBase>>(
|
|
5
|
-
Base: TBase,
|
|
6
|
-
) {
|
|
7
|
-
return class UtilsMixinClass extends Base {
|
|
8
|
-
// ─── Utils (QR / 바코드) ──────────────────────────────────────────────
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* QR 코드 PNG를 생성합니다. `ArrayBuffer`를 반환합니다.
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* const buf = await client.qrcode("https://example.com");
|
|
15
|
-
* const blob = new Blob([buf], { type: "image/png" });
|
|
16
|
-
* img.src = URL.createObjectURL(blob);
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
qrcode(
|
|
20
|
-
content: string,
|
|
21
|
-
opts: QRCodeOptions = {},
|
|
22
|
-
): Promise<ArrayBuffer> {
|
|
23
|
-
return this._requestBinary("POST", "/v1/utils/qrcode", {
|
|
24
|
-
content,
|
|
25
|
-
...opts,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* QR 코드를 base64/data URI JSON으로 반환합니다.
|
|
31
|
-
*
|
|
32
|
-
* ```ts
|
|
33
|
-
* const { data_uri } = await client.qrcodeBase64("https://example.com");
|
|
34
|
-
* img.src = data_uri;
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
qrcodeBase64(
|
|
38
|
-
content: string,
|
|
39
|
-
opts: QRCodeOptions = {},
|
|
40
|
-
): Promise<{ ok: boolean; data: string; data_uri: string }> {
|
|
41
|
-
return this._request("POST", "/v1/utils/qrcode/base64", {
|
|
42
|
-
content,
|
|
43
|
-
...opts,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** QR 코드를 ASCII 아트 텍스트로 반환합니다. */
|
|
48
|
-
qrcodeText(
|
|
49
|
-
content: string,
|
|
50
|
-
opts: QRCodeOptions = {},
|
|
51
|
-
): Promise<{ ok: boolean; text: string }> {
|
|
52
|
-
return this._request("POST", "/v1/utils/qrcode/text", {
|
|
53
|
-
content,
|
|
54
|
-
...opts,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 바코드 PNG를 생성합니다. `ArrayBuffer`를 반환합니다.
|
|
60
|
-
*
|
|
61
|
-
* ```ts
|
|
62
|
-
* const buf = await client.barcode("1234567890128", { type: "ean13" });
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
barcode(
|
|
66
|
-
content: string,
|
|
67
|
-
opts: BarcodeOptions = {},
|
|
68
|
-
): Promise<ArrayBuffer> {
|
|
69
|
-
return this._requestBinary("POST", "/v1/utils/barcode", {
|
|
70
|
-
content,
|
|
71
|
-
...opts,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* PDF를 PNG 이미지로 변환합니다.
|
|
77
|
-
*
|
|
78
|
-
* 단일 페이지 요청이면 `image/png` ArrayBuffer,
|
|
79
|
-
* 다중 페이지 요청이면 `application/zip` ArrayBuffer를 반환합니다.
|
|
80
|
-
*
|
|
81
|
-
* ```ts
|
|
82
|
-
* const buf = await client.pdf2png(pdfArrayBuffer, { dpi: 200 });
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
pdf2png(
|
|
86
|
-
pdfData: ArrayBuffer | Uint8Array<ArrayBuffer>,
|
|
87
|
-
opts: Pdf2PngOptions = {},
|
|
88
|
-
): Promise<ArrayBuffer> {
|
|
89
|
-
const form = new FormData();
|
|
90
|
-
form.append(
|
|
91
|
-
"file",
|
|
92
|
-
new Blob([pdfData], { type: "application/pdf" }),
|
|
93
|
-
"document.pdf",
|
|
94
|
-
);
|
|
95
|
-
const params = new URLSearchParams();
|
|
96
|
-
if (opts.dpi != null) params.set("dpi", String(opts.dpi));
|
|
97
|
-
if (opts.firstPage != null)
|
|
98
|
-
params.set("first_page", String(opts.firstPage));
|
|
99
|
-
if (opts.lastPage != null)
|
|
100
|
-
params.set("last_page", String(opts.lastPage));
|
|
101
|
-
const qs = params.toString();
|
|
102
|
-
const path = "/v1/utils/pdf2png" + (qs ? `?${qs}` : "");
|
|
103
|
-
return this._requestFormBinary("POST", path, form);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
package/src/packet.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
|
-
import { xchacha20poly1305 } from "@noble/ciphers/chacha";
|
|
3
|
-
// @ts-ignore
|
|
4
|
-
import { sha256 } from "@noble/hashes/sha2";
|
|
5
|
-
// @ts-ignore
|
|
6
|
-
import { hkdf } from "@noble/hashes/hkdf";
|
|
7
|
-
|
|
8
|
-
export const PACKET_KEY_SIZE = 32;
|
|
9
|
-
export const PACKET_MAGIC_MIN = 2;
|
|
10
|
-
export const PACKET_MAGIC_RANGE = 14;
|
|
11
|
-
export const PACKET_NONCE_SIZE = 24;
|
|
12
|
-
export const PACKET_TAG_SIZE = 16;
|
|
13
|
-
export const PACKET_HKDF_SALT = "entity-server:hkdf:v1";
|
|
14
|
-
export const PACKET_INFO_LABEL = "entity-server:packet-encryption";
|
|
15
|
-
|
|
16
|
-
function toUint8Array(data: ArrayBuffer | Uint8Array): Uint8Array {
|
|
17
|
-
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function derivePacketKey(
|
|
21
|
-
source: string,
|
|
22
|
-
infoLabel = PACKET_INFO_LABEL,
|
|
23
|
-
): Uint8Array {
|
|
24
|
-
return hkdf(
|
|
25
|
-
sha256,
|
|
26
|
-
new TextEncoder().encode(source),
|
|
27
|
-
new TextEncoder().encode(PACKET_HKDF_SALT),
|
|
28
|
-
new TextEncoder().encode(infoLabel),
|
|
29
|
-
PACKET_KEY_SIZE,
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function packetMagicLenFromKey(
|
|
34
|
-
key: ArrayBuffer | Uint8Array,
|
|
35
|
-
magicMin = PACKET_MAGIC_MIN,
|
|
36
|
-
magicRange = PACKET_MAGIC_RANGE,
|
|
37
|
-
): number {
|
|
38
|
-
const keyBytes = toUint8Array(key);
|
|
39
|
-
if (keyBytes.length < PACKET_KEY_SIZE) return magicMin;
|
|
40
|
-
return magicMin + (keyBytes[PACKET_KEY_SIZE - 1]! % magicRange);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function encryptPacket(
|
|
44
|
-
plaintext: ArrayBuffer | Uint8Array,
|
|
45
|
-
key: ArrayBuffer | Uint8Array,
|
|
46
|
-
magicMin = PACKET_MAGIC_MIN,
|
|
47
|
-
magicRange = PACKET_MAGIC_RANGE,
|
|
48
|
-
): Uint8Array {
|
|
49
|
-
const plaintextBytes = toUint8Array(plaintext);
|
|
50
|
-
const keyBytes = toUint8Array(key);
|
|
51
|
-
const magicLen = packetMagicLenFromKey(keyBytes, magicMin, magicRange);
|
|
52
|
-
const magic = crypto.getRandomValues(new Uint8Array(magicLen));
|
|
53
|
-
const nonce = crypto.getRandomValues(new Uint8Array(PACKET_NONCE_SIZE));
|
|
54
|
-
const cipher = xchacha20poly1305(keyBytes, nonce);
|
|
55
|
-
const ciphertext = cipher.encrypt(plaintextBytes);
|
|
56
|
-
const result = new Uint8Array(
|
|
57
|
-
magicLen + PACKET_NONCE_SIZE + ciphertext.length,
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
result.set(magic, 0);
|
|
61
|
-
result.set(nonce, magicLen);
|
|
62
|
-
result.set(ciphertext, magicLen + PACKET_NONCE_SIZE);
|
|
63
|
-
return result;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function decryptPacket(
|
|
67
|
-
buffer: ArrayBuffer | Uint8Array,
|
|
68
|
-
key: ArrayBuffer | Uint8Array,
|
|
69
|
-
magicMin = PACKET_MAGIC_MIN,
|
|
70
|
-
magicRange = PACKET_MAGIC_RANGE,
|
|
71
|
-
): Uint8Array {
|
|
72
|
-
const data = toUint8Array(buffer);
|
|
73
|
-
const keyBytes = toUint8Array(key);
|
|
74
|
-
const magicLen = packetMagicLenFromKey(keyBytes, magicMin, magicRange);
|
|
75
|
-
|
|
76
|
-
if (data.length < magicLen + PACKET_NONCE_SIZE + PACKET_TAG_SIZE) {
|
|
77
|
-
throw new Error("Encrypted packet too short");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const nonce = data.slice(magicLen, magicLen + PACKET_NONCE_SIZE);
|
|
81
|
-
const ciphertext = data.slice(magicLen + PACKET_NONCE_SIZE);
|
|
82
|
-
const cipher = xchacha20poly1305(keyBytes, nonce);
|
|
83
|
-
return cipher.decrypt(ciphertext);
|
|
84
|
-
}
|
package/tests/packet.test.mjs
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
derivePacketKey,
|
|
6
|
-
packetMagicLenFromKey,
|
|
7
|
-
encryptPacket,
|
|
8
|
-
decryptPacket,
|
|
9
|
-
PACKET_MAGIC_MIN,
|
|
10
|
-
PACKET_MAGIC_RANGE,
|
|
11
|
-
PACKET_NONCE_SIZE,
|
|
12
|
-
PACKET_TAG_SIZE,
|
|
13
|
-
} from "../dist/packet.js";
|
|
14
|
-
|
|
15
|
-
test("packet core roundtrips plaintext", () => {
|
|
16
|
-
const key = derivePacketKey("packet-test-token");
|
|
17
|
-
const payload = new TextEncoder().encode(
|
|
18
|
-
JSON.stringify({ ok: true, message: "hello" }),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
const encrypted = encryptPacket(payload, key);
|
|
22
|
-
const decrypted = decryptPacket(encrypted, key);
|
|
23
|
-
|
|
24
|
-
assert.equal(
|
|
25
|
-
new TextDecoder().decode(decrypted),
|
|
26
|
-
JSON.stringify({ ok: true, message: "hello" }),
|
|
27
|
-
);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test("packet core derives a stable magic length from key", () => {
|
|
31
|
-
const key = derivePacketKey("packet-test-token");
|
|
32
|
-
const magicLen = packetMagicLenFromKey(key);
|
|
33
|
-
|
|
34
|
-
assert.ok(magicLen >= PACKET_MAGIC_MIN);
|
|
35
|
-
assert.ok(magicLen < PACKET_MAGIC_MIN + PACKET_MAGIC_RANGE);
|
|
36
|
-
assert.equal(magicLen, packetMagicLenFromKey(key));
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("encrypted packet has expected minimum shape", () => {
|
|
40
|
-
const key = derivePacketKey("packet-test-token");
|
|
41
|
-
const payload = new TextEncoder().encode("abc");
|
|
42
|
-
const magicLen = packetMagicLenFromKey(key);
|
|
43
|
-
|
|
44
|
-
const encrypted = encryptPacket(payload, key);
|
|
45
|
-
|
|
46
|
-
assert.ok(
|
|
47
|
-
encrypted.length >=
|
|
48
|
-
magicLen + PACKET_NONCE_SIZE + PACKET_TAG_SIZE + payload.length,
|
|
49
|
-
);
|
|
50
|
-
});
|
package/tsconfig.json
DELETED
|
File without changes
|