@simplysm/service-server 13.0.12 → 13.0.14
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/README.md +3 -4
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/docs/built-in-services.md +0 -56
- package/package.json +6 -8
- package/src/index.ts +0 -2
- package/dist/services/crypto-service.d.ts +0 -9
- package/dist/services/crypto-service.d.ts.map +0 -1
- package/dist/services/crypto-service.js +0 -29
- package/dist/services/crypto-service.js.map +0 -6
- package/dist/services/smtp-service.d.ts +0 -8
- package/dist/services/smtp-service.d.ts.map +0 -1
- package/dist/services/smtp-service.js +0 -50
- package/dist/services/smtp-service.js.map +0 -6
- package/src/services/crypto-service.ts +0 -36
- package/src/services/smtp-service.ts +0 -59
package/README.md
CHANGED
|
@@ -47,7 +47,6 @@ pnpm add @simplysm/service-server
|
|
|
47
47
|
|
|
48
48
|
- [`OrmService`](docs/built-in-services.md#ormservice) - DB connection/transaction/query execution (WebSocket only, auth required)
|
|
49
49
|
- [`CryptoService`](docs/built-in-services.md#cryptoservice) - SHA256 hash and AES-256-CBC encryption/decryption
|
|
50
|
-
- [`SmtpService`](docs/built-in-services.md#smtpservice) - nodemailer-based email sending
|
|
51
50
|
- [`AutoUpdateService`](docs/built-in-services.md#autoupdateservice) - App auto-update (provides latest version query and download path)
|
|
52
51
|
|
|
53
52
|
### Utilities
|
|
@@ -240,19 +239,18 @@ The package provides several built-in services:
|
|
|
240
239
|
|
|
241
240
|
- [`OrmService`](docs/built-in-services.md#ormservice) - Database operations (MySQL, MSSQL, PostgreSQL)
|
|
242
241
|
- [`CryptoService`](docs/built-in-services.md#cryptoservice) - Hashing and encryption
|
|
243
|
-
- [`SmtpService`](docs/built-in-services.md#smtpservice) - Email sending
|
|
244
242
|
- [`AutoUpdateService`](docs/built-in-services.md#autoupdateservice) - Client app auto-updates
|
|
245
243
|
|
|
246
244
|
Register them like any other service:
|
|
247
245
|
|
|
248
246
|
```typescript
|
|
249
|
-
import { createServiceServer, OrmService, CryptoService
|
|
247
|
+
import { createServiceServer, OrmService, CryptoService } from "@simplysm/service-server";
|
|
250
248
|
|
|
251
249
|
const server = createServiceServer({
|
|
252
250
|
port: 8080,
|
|
253
251
|
rootPath: "/app/data",
|
|
254
252
|
auth: { jwtSecret: "secret" },
|
|
255
|
-
services: [OrmService, CryptoService
|
|
253
|
+
services: [OrmService, CryptoService],
|
|
256
254
|
});
|
|
257
255
|
```
|
|
258
256
|
|
|
@@ -262,6 +260,7 @@ const server = createServiceServer({
|
|
|
262
260
|
- **CORS**: `@fastify/cors` plugin configures CORS
|
|
263
261
|
- **Path Traversal Prevention**: Static file handler and client name validation block `..`, `/`, `\` characters
|
|
264
262
|
- **Hidden File Blocking**: Files starting with `.` return a 403 response
|
|
263
|
+
- **Directory Trailing Slash Redirect**: Directory requests without a trailing slash are redirected to the same path with a trailing slash (standard web server behavior)
|
|
265
264
|
- **Graceful Shutdown**: Detects `SIGINT`/`SIGTERM` signals to safely close WebSocket connections and server (10-second timeout)
|
|
266
265
|
|
|
267
266
|
See [Security](docs/server.md#security) for more details.
|
package/dist/index.d.ts
CHANGED
|
@@ -10,8 +10,6 @@ export * from "./transport/http/upload-handler";
|
|
|
10
10
|
export * from "./transport/http/static-file-handler";
|
|
11
11
|
export { createProtocolWrapper, type ProtocolWrapper } from "./protocol/protocol-wrapper";
|
|
12
12
|
export * from "./services/orm-service";
|
|
13
|
-
export * from "./services/crypto-service";
|
|
14
|
-
export * from "./services/smtp-service";
|
|
15
13
|
export * from "./services/auto-update-service";
|
|
16
14
|
export * from "./utils/config-manager";
|
|
17
15
|
export * from "./legacy/v1-auto-update-handler";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAG5F,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AAGrD,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG1F,cAAc,wBAAwB,CAAC;AACvC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAG5F,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AAGrD,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG1F,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAG/C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,iCAAiC,CAAC;AAGhD,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,6 @@ export * from "./transport/http/upload-handler.js";
|
|
|
10
10
|
export * from "./transport/http/static-file-handler.js";
|
|
11
11
|
import { createProtocolWrapper } from "./protocol/protocol-wrapper.js";
|
|
12
12
|
export * from "./services/orm-service.js";
|
|
13
|
-
export * from "./services/crypto-service.js";
|
|
14
|
-
export * from "./services/smtp-service.js";
|
|
15
13
|
export * from "./services/auto-update-service.js";
|
|
16
14
|
export * from "./utils/config-manager.js";
|
|
17
15
|
export * from "./legacy/v1-auto-update-handler.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,SAAS,8BAAqD;AAC9D,SAAS,2BAA+C;AAGxD,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,6BAAmD;AAG5D,cAAc;AACd,cAAc;
|
|
4
|
+
"mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,SAAS,8BAAqD;AAC9D,SAAS,2BAA+C;AAGxD,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,6BAAmD;AAG5D,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AAGd,cAAc;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -78,62 +78,6 @@ const server = createServiceServer({
|
|
|
78
78
|
| `encryptAes(data)` | `Promise<string>` | AES-256-CBC encryption. `data` is `Uint8Array`. Returns hex string in `iv:encrypted` format |
|
|
79
79
|
| `decryptAes(encText)` | `Promise<Uint8Array>` | AES-256-CBC decryption. Returns original binary |
|
|
80
80
|
|
|
81
|
-
## SmtpService
|
|
82
|
-
|
|
83
|
-
A nodemailer-based email sending service. Can pass SMTP config directly or reference server config file.
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
import { createServiceServer, SmtpService } from "@simplysm/service-server";
|
|
87
|
-
|
|
88
|
-
const server = createServiceServer({
|
|
89
|
-
port: 8080,
|
|
90
|
-
rootPath: "/app/data",
|
|
91
|
-
services: [SmtpService],
|
|
92
|
-
});
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`.config.json` config (when using config reference method):
|
|
96
|
-
|
|
97
|
-
```json
|
|
98
|
-
{
|
|
99
|
-
"smtp": {
|
|
100
|
-
"default": {
|
|
101
|
-
"host": "smtp.example.com",
|
|
102
|
-
"port": 587,
|
|
103
|
-
"secure": false,
|
|
104
|
-
"user": "user@example.com",
|
|
105
|
-
"pass": "password",
|
|
106
|
-
"senderName": "My App",
|
|
107
|
-
"senderEmail": "noreply@example.com"
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
| Method | Returns | Description |
|
|
114
|
-
|--------|---------|------|
|
|
115
|
-
| `send(options)` | `Promise<string>` | Send email by directly passing SMTP config. Returns message ID |
|
|
116
|
-
| `sendByConfig(configName, options)` | `Promise<string>` | Send email by referencing SMTP config in config file. Returns message ID |
|
|
117
|
-
|
|
118
|
-
`send()` options:
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
interface SmtpSendOption {
|
|
122
|
-
host: string;
|
|
123
|
-
port?: number;
|
|
124
|
-
secure?: boolean;
|
|
125
|
-
user?: string;
|
|
126
|
-
pass?: string;
|
|
127
|
-
from: string;
|
|
128
|
-
to: string;
|
|
129
|
-
cc?: string;
|
|
130
|
-
bcc?: string;
|
|
131
|
-
subject: string;
|
|
132
|
-
html: string;
|
|
133
|
-
attachments?: SmtpSendAttachment[];
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
81
|
## AutoUpdateService
|
|
138
82
|
|
|
139
83
|
Supports auto-update for client apps. Searches for latest version files by platform in the client directory.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/service-server",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "13.0.
|
|
4
|
+
"version": "13.0.14",
|
|
5
5
|
"description": "심플리즘 패키지 - 서비스 모듈 (server)",
|
|
6
6
|
"author": "김석래",
|
|
7
7
|
"repository": {
|
|
@@ -31,18 +31,16 @@
|
|
|
31
31
|
"fastify": "^5.7.4",
|
|
32
32
|
"jose": "^6.1.3",
|
|
33
33
|
"mime": "^4.1.0",
|
|
34
|
-
"nodemailer": "^8.0.1",
|
|
35
34
|
"semver": "^7.7.4",
|
|
36
35
|
"utf-8-validate": "^6.0.6",
|
|
37
36
|
"ws": "^8.19.0",
|
|
38
|
-
"@simplysm/core-common": "13.0.
|
|
39
|
-
"@simplysm/core-node": "13.0.
|
|
40
|
-
"@simplysm/orm-common": "13.0.
|
|
41
|
-
"@simplysm/orm-node": "13.0.
|
|
42
|
-
"@simplysm/service-common": "13.0.
|
|
37
|
+
"@simplysm/core-common": "13.0.14",
|
|
38
|
+
"@simplysm/core-node": "13.0.14",
|
|
39
|
+
"@simplysm/orm-common": "13.0.14",
|
|
40
|
+
"@simplysm/orm-node": "13.0.14",
|
|
41
|
+
"@simplysm/service-common": "13.0.14"
|
|
43
42
|
},
|
|
44
43
|
"devDependencies": {
|
|
45
|
-
"@types/nodemailer": "^7.0.9",
|
|
46
44
|
"@types/semver": "^7.7.1",
|
|
47
45
|
"@types/ws": "^8.18.1"
|
|
48
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -23,8 +23,6 @@ export { createProtocolWrapper, type ProtocolWrapper } from "./protocol/protocol
|
|
|
23
23
|
|
|
24
24
|
// Services
|
|
25
25
|
export * from "./services/orm-service";
|
|
26
|
-
export * from "./services/crypto-service";
|
|
27
|
-
export * from "./services/smtp-service";
|
|
28
26
|
export * from "./services/auto-update-service";
|
|
29
27
|
|
|
30
28
|
// Utils
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
-
import { type ServiceMethods } from "../core/define-service";
|
|
3
|
-
export declare const CryptoService: import("..").ServiceDefinition<{
|
|
4
|
-
encrypt(data: string | Bytes): Promise<string>;
|
|
5
|
-
encryptAes(data: Bytes): Promise<string>;
|
|
6
|
-
decryptAes(encText: string): Promise<Bytes>;
|
|
7
|
-
}>;
|
|
8
|
-
export type CryptoServiceType = ServiceMethods<typeof CryptoService>;
|
|
9
|
-
//# sourceMappingURL=crypto-service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-service.d.ts","sourceRoot":"","sources":["../../src/services/crypto-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE5E,eAAO,MAAM,aAAa;kBACJ,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;qBAK7B,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;wBAUpB,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;EAWhD,CAAC;AAEJ,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { bytesConcat, bytesToHex, bytesFromHex } from "@simplysm/core-common";
|
|
2
|
-
import crypto from "crypto";
|
|
3
|
-
import { defineService } from "../core/define-service.js";
|
|
4
|
-
const CryptoService = defineService("Crypto", (ctx) => ({
|
|
5
|
-
async encrypt(data) {
|
|
6
|
-
const config = await ctx.getConfig("crypto");
|
|
7
|
-
return crypto.createHmac("sha256", config.key).update(data).digest("hex");
|
|
8
|
-
},
|
|
9
|
-
async encryptAes(data) {
|
|
10
|
-
const config = await ctx.getConfig("crypto");
|
|
11
|
-
const iv = crypto.randomBytes(16);
|
|
12
|
-
const cipher = crypto.createCipheriv("aes-256-cbc", config.key, iv);
|
|
13
|
-
const encrypted = cipher.update(data);
|
|
14
|
-
return bytesToHex(iv) + ":" + bytesToHex(bytesConcat([encrypted, cipher.final()]));
|
|
15
|
-
},
|
|
16
|
-
async decryptAes(encText) {
|
|
17
|
-
const config = await ctx.getConfig("crypto");
|
|
18
|
-
const textParts = encText.split(":");
|
|
19
|
-
const iv = bytesFromHex(textParts.shift());
|
|
20
|
-
const encryptedText = bytesFromHex(textParts.join(":"));
|
|
21
|
-
const decipher = crypto.createDecipheriv("aes-256-cbc", config.key, iv);
|
|
22
|
-
const decrypted = decipher.update(encryptedText);
|
|
23
|
-
return bytesConcat([decrypted, decipher.final()]);
|
|
24
|
-
}
|
|
25
|
-
}));
|
|
26
|
-
export {
|
|
27
|
-
CryptoService
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=crypto-service.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/services/crypto-service.ts"],
|
|
4
|
-
"mappings": "AACA,SAAS,aAAa,YAAY,oBAAoB;AAEtD,OAAO,YAAY;AACnB,SAAS,qBAA0C;AAE5C,MAAM,gBAAgB,cAAc,UAAU,CAAC,SAAS;AAAA,EAC7D,MAAM,QAAQ,MAAuC;AACnD,UAAM,SAAS,MAAM,IAAI,UAAwB,QAAQ;AACzD,WAAO,OAAO,WAAW,UAAU,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAAA,EAC1E;AAAA,EAEA,MAAM,WAAW,MAA8B;AAC7C,UAAM,SAAS,MAAM,IAAI,UAAwB,QAAQ;AAEzD,UAAM,KAAK,OAAO,YAAY,EAAE;AAChC,UAAM,SAAS,OAAO,eAAe,eAAe,OAAO,KAAK,EAAE;AAClE,UAAM,YAAY,OAAO,OAAO,IAAI;AAEpC,WAAO,WAAW,EAAE,IAAI,MAAM,WAAW,YAAY,CAAC,WAAW,OAAO,MAAM,CAAC,CAAC,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,WAAW,SAAiC;AAChD,UAAM,SAAS,MAAM,IAAI,UAAwB,QAAQ;AAEzD,UAAM,YAAY,QAAQ,MAAM,GAAG;AACnC,UAAM,KAAK,aAAa,UAAU,MAAM,CAAE;AAC1C,UAAM,gBAAgB,aAAa,UAAU,KAAK,GAAG,CAAC;AACtD,UAAM,WAAW,OAAO,iBAAiB,eAAe,OAAO,KAAK,EAAE;AACtE,UAAM,YAAY,SAAS,OAAO,aAAa;AAE/C,WAAO,YAAY,CAAC,WAAW,SAAS,MAAM,CAAC,CAAC;AAAA,EAClD;AACF,EAAE;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { SmtpSendByConfigOption, SmtpSendOption } from "@simplysm/service-common";
|
|
2
|
-
import { type ServiceMethods } from "../core/define-service";
|
|
3
|
-
export declare const SmtpService: import("..").ServiceDefinition<{
|
|
4
|
-
send: (options: SmtpSendOption) => Promise<string>;
|
|
5
|
-
sendByConfig(configName: string, options: SmtpSendByConfigOption): Promise<string>;
|
|
6
|
-
}>;
|
|
7
|
-
export type SmtpServiceType = ServiceMethods<typeof SmtpService>;
|
|
8
|
-
//# sourceMappingURL=smtp-service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"smtp-service.d.ts","sourceRoot":"","sources":["../../src/services/smtp-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,sBAAsB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE5E,eAAO,MAAM,WAAW;oBACO,cAAc,KAAG,OAAO,CAAC,MAAM,CAAC;6BAkC5B,MAAM,WAAW,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;EAiB1F,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import nodemailer from "nodemailer";
|
|
2
|
-
import { defineService } from "../core/define-service.js";
|
|
3
|
-
const SmtpService = defineService("Smtp", (ctx) => {
|
|
4
|
-
const send = async (options) => {
|
|
5
|
-
const transport = nodemailer.createTransport({
|
|
6
|
-
host: options.host,
|
|
7
|
-
port: options.port,
|
|
8
|
-
secure: options.secure,
|
|
9
|
-
auth: options.user != null ? {
|
|
10
|
-
user: options.user,
|
|
11
|
-
pass: options.pass
|
|
12
|
-
} : void 0,
|
|
13
|
-
tls: {
|
|
14
|
-
rejectUnauthorized: false
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
const mailOptions = {
|
|
18
|
-
...options,
|
|
19
|
-
attachments: options.attachments?.map((att) => ({
|
|
20
|
-
...att,
|
|
21
|
-
// eslint-disable-next-line no-restricted-globals -- nodemailer 라이브러리 요구사항
|
|
22
|
-
content: att.content != null ? Buffer.from(att.content) : void 0
|
|
23
|
-
}))
|
|
24
|
-
};
|
|
25
|
-
const info = await transport.sendMail(mailOptions);
|
|
26
|
-
return info.messageId;
|
|
27
|
-
};
|
|
28
|
-
return {
|
|
29
|
-
send,
|
|
30
|
-
async sendByConfig(configName, options) {
|
|
31
|
-
const config = (await ctx.getConfig("smtp"))[configName];
|
|
32
|
-
if (config == null) {
|
|
33
|
-
throw new Error(`SMTP \uC124\uC815\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${configName}`);
|
|
34
|
-
}
|
|
35
|
-
return send({
|
|
36
|
-
user: config.user,
|
|
37
|
-
pass: config.pass,
|
|
38
|
-
host: config.host,
|
|
39
|
-
port: config.port,
|
|
40
|
-
secure: config.secure,
|
|
41
|
-
from: `"${config.senderName}" <${config.senderEmail ?? config.user}>`,
|
|
42
|
-
...options
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
export {
|
|
48
|
-
SmtpService
|
|
49
|
-
};
|
|
50
|
-
//# sourceMappingURL=smtp-service.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/services/smtp-service.ts"],
|
|
4
|
-
"mappings": "AAAA,OAAO,gBAAgB;AAEvB,SAAS,qBAA0C;AAE5C,MAAM,cAAc,cAAc,QAAQ,CAAC,QAAQ;AACxD,QAAM,OAAO,OAAO,YAA6C;AAC/D,UAAM,YAAY,WAAW,gBAAgB;AAAA,MAC3C,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,MACE,QAAQ,QAAQ,OACZ;AAAA,QACE,MAAM,QAAQ;AAAA,QACd,MAAM,QAAQ;AAAA,MAChB,IACA;AAAA,MACN,KAAK;AAAA,QACH,oBAAoB;AAAA,MACtB;AAAA,IACF,CAAC;AAGD,UAAM,cAAc;AAAA,MAClB,GAAG;AAAA,MACH,aAAa,QAAQ,aAAa,IAAI,CAAC,SAAS;AAAA,QAC9C,GAAG;AAAA;AAAA,QAEH,SAAS,IAAI,WAAW,OAAO,OAAO,KAAK,IAAI,OAAO,IAAI;AAAA,MAC5D,EAAE;AAAA,IACJ;AAEA,UAAM,OAAO,MAAM,UAAU,SAAS,WAAW;AACjD,WAAO,KAAK;AAAA,EACd;AAEA,SAAO;AAAA,IACL;AAAA,IAEA,MAAM,aAAa,YAAoB,SAAkD;AACvF,YAAM,UAAU,MAAM,IAAI,UAAkD,MAAM,GAAG,UAAU;AAC/F,UAAI,UAAU,MAAM;AAClB,cAAM,IAAI,MAAM,yEAAuB,UAAU,EAAE;AAAA,MACrD;AAEA,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,QAAQ,OAAO;AAAA,QACf,MAAM,IAAI,OAAO,UAAU,MAAM,OAAO,eAAe,OAAO,IAAI;AAAA,QAClE,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AACF,CAAC;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
-
import { bytesConcat, bytesToHex, bytesFromHex } from "@simplysm/core-common";
|
|
3
|
-
import type { CryptoConfig } from "@simplysm/service-common";
|
|
4
|
-
import crypto from "crypto";
|
|
5
|
-
import { defineService, type ServiceMethods } from "../core/define-service";
|
|
6
|
-
|
|
7
|
-
export const CryptoService = defineService("Crypto", (ctx) => ({
|
|
8
|
-
async encrypt(data: string | Bytes): Promise<string> {
|
|
9
|
-
const config = await ctx.getConfig<CryptoConfig>("crypto");
|
|
10
|
-
return crypto.createHmac("sha256", config.key).update(data).digest("hex");
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
async encryptAes(data: Bytes): Promise<string> {
|
|
14
|
-
const config = await ctx.getConfig<CryptoConfig>("crypto");
|
|
15
|
-
|
|
16
|
-
const iv = crypto.randomBytes(16);
|
|
17
|
-
const cipher = crypto.createCipheriv("aes-256-cbc", config.key, iv);
|
|
18
|
-
const encrypted = cipher.update(data);
|
|
19
|
-
|
|
20
|
-
return bytesToHex(iv) + ":" + bytesToHex(bytesConcat([encrypted, cipher.final()]));
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
async decryptAes(encText: string): Promise<Bytes> {
|
|
24
|
-
const config = await ctx.getConfig<CryptoConfig>("crypto");
|
|
25
|
-
|
|
26
|
-
const textParts = encText.split(":");
|
|
27
|
-
const iv = bytesFromHex(textParts.shift()!);
|
|
28
|
-
const encryptedText = bytesFromHex(textParts.join(":"));
|
|
29
|
-
const decipher = crypto.createDecipheriv("aes-256-cbc", config.key, iv);
|
|
30
|
-
const decrypted = decipher.update(encryptedText);
|
|
31
|
-
|
|
32
|
-
return bytesConcat([decrypted, decipher.final()]);
|
|
33
|
-
},
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
export type CryptoServiceType = ServiceMethods<typeof CryptoService>;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import nodemailer from "nodemailer";
|
|
2
|
-
import type { SmtpConfig, SmtpSendByConfigOption, SmtpSendOption } from "@simplysm/service-common";
|
|
3
|
-
import { defineService, type ServiceMethods } from "../core/define-service";
|
|
4
|
-
|
|
5
|
-
export const SmtpService = defineService("Smtp", (ctx) => {
|
|
6
|
-
const send = async (options: SmtpSendOption): Promise<string> => {
|
|
7
|
-
const transport = nodemailer.createTransport({
|
|
8
|
-
host: options.host,
|
|
9
|
-
port: options.port,
|
|
10
|
-
secure: options.secure,
|
|
11
|
-
auth:
|
|
12
|
-
options.user != null
|
|
13
|
-
? {
|
|
14
|
-
user: options.user,
|
|
15
|
-
pass: options.pass,
|
|
16
|
-
}
|
|
17
|
-
: undefined,
|
|
18
|
-
tls: {
|
|
19
|
-
rejectUnauthorized: false,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// nodemailer 타입 정의는 Buffer를 요구하지만, 실제로 Uint8Array도 작동함
|
|
24
|
-
const mailOptions = {
|
|
25
|
-
...options,
|
|
26
|
-
attachments: options.attachments?.map((att) => ({
|
|
27
|
-
...att,
|
|
28
|
-
// eslint-disable-next-line no-restricted-globals -- nodemailer 라이브러리 요구사항
|
|
29
|
-
content: att.content != null ? Buffer.from(att.content) : undefined,
|
|
30
|
-
})),
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const info = await transport.sendMail(mailOptions);
|
|
34
|
-
return info.messageId;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
send,
|
|
39
|
-
|
|
40
|
-
async sendByConfig(configName: string, options: SmtpSendByConfigOption): Promise<string> {
|
|
41
|
-
const config = (await ctx.getConfig<Record<string, SmtpConfig | undefined>>("smtp"))[configName];
|
|
42
|
-
if (config == null) {
|
|
43
|
-
throw new Error(`SMTP 설정을 찾을 수 없습니다: ${configName}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return send({
|
|
47
|
-
user: config.user,
|
|
48
|
-
pass: config.pass,
|
|
49
|
-
host: config.host,
|
|
50
|
-
port: config.port,
|
|
51
|
-
secure: config.secure,
|
|
52
|
-
from: `"${config.senderName}" <${config.senderEmail ?? config.user}>`,
|
|
53
|
-
...options,
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
export type SmtpServiceType = ServiceMethods<typeof SmtpService>;
|