@simplysm/storage 13.0.0-beta.7 → 13.0.2
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/clients/ftp-storage-client.d.ts.map +1 -0
- package/dist/clients/ftp-storage-client.js.map +0 -1
- package/dist/clients/sftp-storage-client.d.ts.map +1 -0
- package/dist/clients/sftp-storage-client.js +27 -6
- package/dist/clients/sftp-storage-client.js.map +1 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -6
- package/dist/index.js.map +0 -1
- package/dist/storage-factory.d.ts.map +1 -0
- package/dist/storage-factory.js +2 -2
- package/dist/storage-factory.js.map +0 -1
- package/dist/types/storage-conn-config.d.ts.map +1 -0
- package/dist/types/storage-conn-config.js.map +0 -1
- package/dist/types/storage-type.d.ts.map +1 -0
- package/dist/types/storage-type.js.map +0 -1
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js.map +0 -1
- package/package.json +6 -5
- package/src/clients/ftp-storage-client.ts +146 -0
- package/src/clients/sftp-storage-client.ts +160 -0
- package/src/index.ts +14 -0
- package/src/storage-factory.ts +47 -0
- package/src/types/storage-conn-config.ts +6 -0
- package/src/types/storage-type.ts +1 -0
- package/src/types/storage.ts +20 -0
- package/dist/core-common/src/common.types.d.ts +0 -74
- package/dist/core-common/src/common.types.d.ts.map +0 -1
- package/dist/core-common/src/env.d.ts +0 -6
- package/dist/core-common/src/env.d.ts.map +0 -1
- package/dist/core-common/src/errors/argument-error.d.ts +0 -25
- package/dist/core-common/src/errors/argument-error.d.ts.map +0 -1
- package/dist/core-common/src/errors/not-implemented-error.d.ts +0 -29
- package/dist/core-common/src/errors/not-implemented-error.d.ts.map +0 -1
- package/dist/core-common/src/errors/sd-error.d.ts +0 -27
- package/dist/core-common/src/errors/sd-error.d.ts.map +0 -1
- package/dist/core-common/src/errors/timeout-error.d.ts +0 -31
- package/dist/core-common/src/errors/timeout-error.d.ts.map +0 -1
- package/dist/core-common/src/extensions/arr-ext.d.ts +0 -15
- package/dist/core-common/src/extensions/arr-ext.d.ts.map +0 -1
- package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +0 -19
- package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +0 -1
- package/dist/core-common/src/extensions/arr-ext.types.d.ts +0 -215
- package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +0 -1
- package/dist/core-common/src/extensions/map-ext.d.ts +0 -57
- package/dist/core-common/src/extensions/map-ext.d.ts.map +0 -1
- package/dist/core-common/src/extensions/set-ext.d.ts +0 -36
- package/dist/core-common/src/extensions/set-ext.d.ts.map +0 -1
- package/dist/core-common/src/features/debounce-queue.d.ts +0 -53
- package/dist/core-common/src/features/debounce-queue.d.ts.map +0 -1
- package/dist/core-common/src/features/event-emitter.d.ts +0 -66
- package/dist/core-common/src/features/event-emitter.d.ts.map +0 -1
- package/dist/core-common/src/features/serial-queue.d.ts +0 -47
- package/dist/core-common/src/features/serial-queue.d.ts.map +0 -1
- package/dist/core-common/src/index.d.ts +0 -32
- package/dist/core-common/src/index.d.ts.map +0 -1
- package/dist/core-common/src/types/date-only.d.ts +0 -152
- package/dist/core-common/src/types/date-only.d.ts.map +0 -1
- package/dist/core-common/src/types/date-time.d.ts +0 -96
- package/dist/core-common/src/types/date-time.d.ts.map +0 -1
- package/dist/core-common/src/types/lazy-gc-map.d.ts +0 -80
- package/dist/core-common/src/types/lazy-gc-map.d.ts.map +0 -1
- package/dist/core-common/src/types/time.d.ts +0 -68
- package/dist/core-common/src/types/time.d.ts.map +0 -1
- package/dist/core-common/src/types/uuid.d.ts +0 -35
- package/dist/core-common/src/types/uuid.d.ts.map +0 -1
- package/dist/core-common/src/utils/bytes.d.ts +0 -51
- package/dist/core-common/src/utils/bytes.d.ts.map +0 -1
- package/dist/core-common/src/utils/date-format.d.ts +0 -90
- package/dist/core-common/src/utils/date-format.d.ts.map +0 -1
- package/dist/core-common/src/utils/json.d.ts +0 -34
- package/dist/core-common/src/utils/json.d.ts.map +0 -1
- package/dist/core-common/src/utils/num.d.ts +0 -60
- package/dist/core-common/src/utils/num.d.ts.map +0 -1
- package/dist/core-common/src/utils/obj.d.ts +0 -258
- package/dist/core-common/src/utils/obj.d.ts.map +0 -1
- package/dist/core-common/src/utils/path.d.ts +0 -23
- package/dist/core-common/src/utils/path.d.ts.map +0 -1
- package/dist/core-common/src/utils/primitive.d.ts +0 -18
- package/dist/core-common/src/utils/primitive.d.ts.map +0 -1
- package/dist/core-common/src/utils/str.d.ts +0 -103
- package/dist/core-common/src/utils/str.d.ts.map +0 -1
- package/dist/core-common/src/utils/template-strings.d.ts +0 -84
- package/dist/core-common/src/utils/template-strings.d.ts.map +0 -1
- package/dist/core-common/src/utils/transferable.d.ts +0 -47
- package/dist/core-common/src/utils/transferable.d.ts.map +0 -1
- package/dist/core-common/src/utils/wait.d.ts +0 -19
- package/dist/core-common/src/utils/wait.d.ts.map +0 -1
- package/dist/core-common/src/utils/xml.d.ts +0 -36
- package/dist/core-common/src/utils/xml.d.ts.map +0 -1
- package/dist/core-common/src/zip/sd-zip.d.ts +0 -80
- package/dist/core-common/src/zip/sd-zip.d.ts.map +0 -1
- package/dist/storage/src/clients/ftp-storage-client.d.ts.map +0 -1
- package/dist/storage/src/clients/sftp-storage-client.d.ts.map +0 -1
- package/dist/storage/src/index.d.ts.map +0 -1
- package/dist/storage/src/storage-factory.d.ts.map +0 -1
- package/dist/storage/src/types/storage-conn-config.d.ts.map +0 -1
- package/dist/storage/src/types/storage-type.d.ts.map +0 -1
- package/dist/storage/src/types/storage.d.ts.map +0 -1
- /package/dist/{storage/src/clients → clients}/ftp-storage-client.d.ts +0 -0
- /package/dist/{storage/src/clients → clients}/sftp-storage-client.d.ts +0 -0
- /package/dist/{storage/src/index.d.ts → index.d.ts} +0 -0
- /package/dist/{storage/src/storage-factory.d.ts → storage-factory.d.ts} +0 -0
- /package/dist/{storage/src/types → types}/storage-conn-config.d.ts +0 -0
- /package/dist/{storage/src/types → types}/storage-type.d.ts +0 -0
- /package/dist/{storage/src/types → types}/storage.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ftp-storage-client.d.ts","sourceRoot":"","sources":["../../src/clients/ftp-storage-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,OAAO;IAGlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,OAAO,CAAyB;gBAEX,OAAO,GAAE,OAAe;IAErD;;;;;;;OAOG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvD,OAAO,CAAC,cAAc;IAOtB,0CAA0C;IACpC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAK7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAWhD;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB1C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,0CAA0C;IACpC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9E,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;;;;;OAMG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CASvB"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/clients/ftp-storage-client.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Bytes } from \"@simplysm/core-common\";\nimport { bytesConcat, SdError } from \"@simplysm/core-common\";\nimport ftp from \"basic-ftp\";\nimport { PassThrough, Readable } from \"stream\";\nimport type { Storage, FileInfo } from \"../types/storage\";\nimport type { StorageConnConfig } from \"../types/storage-conn-config\";\n\n/**\n * FTP/FTPS \uD504\uB85C\uD1A0\uCF5C\uC744 \uC0AC\uC6A9\uD558\uB294 \uC2A4\uD1A0\uB9AC\uC9C0 \uD074\uB77C\uC774\uC5B8\uD2B8.\n *\n * @remarks\n * \uC0DD\uC131\uC790\uC758 `secure` \uD30C\uB77C\uBBF8\uD130\uB85C FTPS \uC0AC\uC6A9 \uC5EC\uBD80\uB97C \uC124\uC815\uD569\uB2C8\uB2E4.\n * \uC9C1\uC811 \uC0AC\uC6A9\uBCF4\uB2E4 {@link StorageFactory.connect}\uB97C \uD1B5\uD55C \uC0AC\uC6A9\uC744 \uAD8C\uC7A5\uD569\uB2C8\uB2E4.\n */\nexport class FtpStorageClient implements Storage {\n private _client: ftp.Client | undefined;\n\n constructor(private readonly _secure: boolean = false) {}\n\n /**\n * FTP \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD569\uB2C8\uB2E4.\n *\n * @remarks\n * - \uC5F0\uACB0 \uD6C4 \uBC18\uB4DC\uC2DC {@link close}\uB85C \uC5F0\uACB0\uC744 \uC885\uB8CC\uD574\uC57C \uD569\uB2C8\uB2E4.\n * - \uB3D9\uC77C \uC778\uC2A4\uD134\uC2A4\uC5D0\uC11C \uC5EC\uB7EC \uBC88 \uD638\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694. (\uC5F0\uACB0 \uB204\uC218 \uBC1C\uC0DD)\n * - \uC790\uB3D9 \uC5F0\uACB0/\uC885\uB8CC \uAD00\uB9AC\uAC00 \uD544\uC694\uD558\uBA74 {@link StorageFactory.connect}\uB97C \uC0AC\uC6A9\uD558\uC138\uC694. (\uAD8C\uC7A5)\n */\n async connect(config: StorageConnConfig): Promise<void> {\n if (this._client !== undefined) {\n throw new SdError(\"\uC774\uBBF8 FTP \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 close()\uB97C \uD638\uCD9C\uD558\uC138\uC694.\");\n }\n const client = new ftp.Client();\n try {\n await client.access({\n host: config.host,\n port: config.port,\n user: config.user,\n password: config.pass,\n secure: this._secure,\n });\n this._client = client;\n } catch (err) {\n client.close();\n throw err;\n }\n }\n\n private _requireClient(): ftp.Client {\n if (this._client === undefined) {\n throw new SdError(\"FTP \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uB418\uC5B4\uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\");\n }\n return this._client;\n }\n\n /** \uB514\uB809\uD1A0\uB9AC\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4. \uC0C1\uC704 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC5C6\uC73C\uBA74 \uD568\uAED8 \uC0DD\uC131\uD569\uB2C8\uB2E4. */\n async mkdir(dirPath: string): Promise<void> {\n await this._requireClient().ensureDir(dirPath);\n }\n\n async rename(fromPath: string, toPath: string): Promise<void> {\n await this._requireClient().rename(fromPath, toPath);\n }\n\n async readdir(dirPath: string): Promise<FileInfo[]> {\n const fileInfos = await this._requireClient().list(dirPath);\n return fileInfos.map((item) => ({ name: item.name, isFile: item.isFile }));\n }\n\n async readFile(filePath: string): Promise<Bytes> {\n const client = this._requireClient();\n const chunks: Bytes[] = [];\n const writable = new PassThrough();\n writable.on(\"data\", (chunk: Uint8Array) => {\n chunks.push(chunk);\n });\n await client.downloadTo(writable, filePath);\n return bytesConcat(chunks);\n }\n\n /**\n * \uD30C\uC77C \uB610\uB294 \uB514\uB809\uD1A0\uB9AC \uC874\uC7AC \uC5EC\uBD80\uB97C \uD655\uC778\uD569\uB2C8\uB2E4.\n *\n * @remarks\n * \uD30C\uC77C \uD655\uC778 \uC2DC size() \uBA85\uB839\uC73C\uB85C O(1) \uC131\uB2A5\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.\n * \uB514\uB809\uD1A0\uB9AC \uD655\uC778 \uC2DC \uC0C1\uC704 \uB514\uB809\uD1A0\uB9AC \uBAA9\uB85D\uC744 \uC870\uD68C\uD558\uBBC0\uB85C, \uD56D\uBAA9 \uC218\uAC00 \uB9CE\uC73C\uBA74 \uC131\uB2A5\uC774 \uC800\uD558\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n *\n * \uC2AC\uB798\uC2DC\uAC00 \uC5C6\uB294 \uACBD\uB85C(\uC608: `file.txt`)\uB294 \uB8E8\uD2B8 \uB514\uB809\uD1A0\uB9AC(`/`)\uC5D0\uC11C \uAC80\uC0C9\uD569\uB2C8\uB2E4.\n *\n * \uC0C1\uC704 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uACBD\uC6B0\uC5D0\uB3C4 false\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.\n * \uB124\uD2B8\uC6CC\uD06C \uC624\uB958, \uAD8C\uD55C \uC624\uB958 \uB4F1 \uBAA8\uB4E0 \uC608\uC678\uB3C4 false\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4.\n */\n async exists(filePath: string): Promise<boolean> {\n try {\n // \uD30C\uC77C\uC778 \uACBD\uC6B0 size()\uB85C \uBE60\uB974\uAC8C \uD655\uC778 (O(1))\n await this._requireClient().size(filePath);\n return true;\n } catch {\n // size() \uC2E4\uD328 \uC2DC \uB514\uB809\uD1A0\uB9AC\uC77C \uC218 \uC788\uC73C\uBBC0\uB85C list()\uB85C \uD655\uC778\n try {\n const lastSlash = filePath.lastIndexOf(\"/\");\n const dirPath = lastSlash > 0 ? filePath.substring(0, lastSlash) : \"/\";\n const fileName = filePath.substring(lastSlash + 1);\n const list = await this._requireClient().list(dirPath);\n return list.some((item) => item.name === fileName);\n } catch {\n return false;\n }\n }\n }\n\n async remove(filePath: string): Promise<void> {\n await this._requireClient().remove(filePath);\n }\n\n /** \uB85C\uCEEC \uD30C\uC77C \uACBD\uB85C \uB610\uB294 \uBC14\uC774\uD2B8 \uB370\uC774\uD130\uB97C \uC6D0\uACA9 \uACBD\uB85C\uC5D0 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4. */\n async put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void> {\n let param: string | Readable;\n if (typeof localPathOrBuffer === \"string\") {\n param = localPathOrBuffer;\n } else {\n param = Readable.from(localPathOrBuffer);\n }\n await this._requireClient().uploadFrom(param, storageFilePath);\n }\n\n async uploadDir(fromPath: string, toPath: string): Promise<void> {\n await this._requireClient().uploadFromDir(fromPath, toPath);\n }\n\n /**\n * \uC5F0\uACB0\uC744 \uC885\uB8CC\uD569\uB2C8\uB2E4.\n *\n * @remarks\n * \uC774\uBBF8 \uC885\uB8CC\uB41C \uC0C1\uD0DC\uC5D0\uC11C \uD638\uCD9C\uD574\uB3C4 \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\n * \uC885\uB8CC \uD6C4\uC5D0\uB294 \uB3D9\uC77C \uC778\uC2A4\uD134\uC2A4\uC5D0\uC11C {@link connect}\uB97C \uB2E4\uC2DC \uD638\uCD9C\uD558\uC5EC \uC7AC\uC5F0\uACB0\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n */\n close(): Promise<void> {\n if (this._client === undefined) {\n return Promise.resolve();\n }\n\n this._client.close();\n this._client = undefined;\n return Promise.resolve();\n }\n}\n"],
|
|
5
4
|
"mappings": "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",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sftp-storage-client.d.ts","sourceRoot":"","sources":["../../src/clients/sftp-storage-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKtE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,OAAO,CAAC,OAAO,CAAyB;IAExC;;;;;;;OAOG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6CvD,OAAO,CAAC,cAAc;IAOtB,0CAA0C;IACpC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D;;;;;;OAMG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW1C,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAQ7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAc1C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,0CAA0C;IACpC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9E,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;;;;;OAMG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
|
@@ -16,12 +16,33 @@ class SftpStorageClient {
|
|
|
16
16
|
}
|
|
17
17
|
const client = new SftpClient();
|
|
18
18
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
if (config.pass != null) {
|
|
20
|
+
await client.connect({
|
|
21
|
+
host: config.host,
|
|
22
|
+
port: config.port,
|
|
23
|
+
username: config.user,
|
|
24
|
+
password: config.pass
|
|
25
|
+
});
|
|
26
|
+
} else {
|
|
27
|
+
const fsP = await import("fs/promises");
|
|
28
|
+
const os = await import("os");
|
|
29
|
+
const pathMod = await import("path");
|
|
30
|
+
const keyPath = pathMod.join(os.homedir(), ".ssh", "id_ed25519");
|
|
31
|
+
const baseOptions = {
|
|
32
|
+
host: config.host,
|
|
33
|
+
port: config.port,
|
|
34
|
+
username: config.user,
|
|
35
|
+
...process.env["SSH_AUTH_SOCK"] != null ? { agent: process.env["SSH_AUTH_SOCK"] } : {}
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
await client.connect({
|
|
39
|
+
...baseOptions,
|
|
40
|
+
privateKey: await fsP.readFile(keyPath)
|
|
41
|
+
});
|
|
42
|
+
} catch {
|
|
43
|
+
await client.connect(baseOptions);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
25
46
|
this._client = client;
|
|
26
47
|
} catch (err) {
|
|
27
48
|
await client.end();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/clients/sftp-storage-client.ts"],
|
|
4
|
-
"
|
|
5
|
-
"mappings": "AACA,SAAS,eAAe;AACxB,OAAO,gBAAgB;AAahB,MAAM,kBAAqC;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUR,MAAM,QAAQ,QAA0C;AACtD,QAAI,KAAK,YAAY,QAAW;AAC9B,YAAM,IAAI,QAAQ,oJAA2C;AAAA,IAC/D;AAEA,UAAM,SAAS,IAAI,WAAW;AAC9B,QAAI;AACF,YAAM,OAAO,QAAQ;AAAA,QACnB,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,MACnB,CAAC;AACD,WAAK,UAAU;AAAA,IACjB,SAAS,KAAK;AACZ,YAAM,OAAO,IAAI;AACjB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,iBAA6B;AACnC,QAAI,KAAK,YAAY,QAAW;AAC9B,YAAM,IAAI,QAAQ,wFAAuB;AAAA,IAC3C;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,MAAM,SAAgC;AAC1C,UAAM,KAAK,eAAe,EAAE,MAAM,SAAS,IAAI;AAAA,EACjD;AAAA,EAEA,MAAM,OAAO,UAAkB,QAA+B;AAC5D,UAAM,KAAK,eAAe,EAAE,OAAO,UAAU,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,UAAoC;AAC/C,QAAI;AAGF,YAAM,SAAS,MAAM,KAAK,eAAe,EAAE,OAAO,QAAQ;AAC1D,aAAO,OAAO,WAAW;AAAA,IAC3B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,SAAsC;AAClD,UAAM,OAAO,MAAM,KAAK,eAAe,EAAE,KAAK,OAAO;AACrD,WAAO,KAAK,IAAI,CAAC,UAAU;AAAA,MACzB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK,SAAS;AAAA,IACxB,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,SAAS,UAAkC;AAG/C,UAAM,SAAU,MAAM,KAAK,eAAe,EAAE,IAAI,QAAQ;AACxD,QAAI,kBAAkB,YAAY;AAChC,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO,IAAI,YAAY,EAAE,OAAO,MAAM;AAAA,IACxC;AACA,UAAM,IAAI,QAAQ,8EAAkB;AAAA,EACtC;AAAA,EAEA,MAAM,OAAO,UAAiC;AAC5C,UAAM,KAAK,eAAe,EAAE,OAAO,QAAQ;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAM,IAAI,mBAAmC,iBAAwC;AACnF,QAAI,OAAO,sBAAsB,UAAU;AACzC,YAAM,KAAK,eAAe,EAAE,QAAQ,mBAAmB,eAAe;AAAA,IACxE,OAAO;AAEL,YAAM,KAAK,eAAe,EAAE,IAAI,OAAO,KAAK,iBAAiB,GAAG,eAAe;AAAA,IACjF;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,UAAkB,QAA+B;AAC/D,UAAM,KAAK,eAAe,EAAE,UAAU,UAAU,MAAM;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAuB;AAC3B,QAAI,KAAK,YAAY,QAAW;AAC9B;AAAA,IACF;AACA,UAAM,KAAK,QAAQ,IAAI;AACvB,SAAK,UAAU;AAAA,EACjB;AACF;",
|
|
4
|
+
"mappings": "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",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AAIrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAI9C,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from "./types/storage-conn-config";
|
|
2
|
-
export * from "./types/storage";
|
|
3
|
-
export * from "./types/storage-type";
|
|
4
|
-
export * from "./clients/ftp-storage-client";
|
|
5
|
-
export * from "./clients/sftp-storage-client";
|
|
6
|
-
export * from "./storage-factory";
|
|
1
|
+
export * from "./types/storage-conn-config.js";
|
|
2
|
+
export * from "./types/storage.js";
|
|
3
|
+
export * from "./types/storage-type.js";
|
|
4
|
+
export * from "./clients/ftp-storage-client.js";
|
|
5
|
+
export * from "./clients/sftp-storage-client.js";
|
|
6
|
+
export * from "./storage-factory.js";
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["//#region Types\nexport * from \"./types/storage-conn-config\";\nexport * from \"./types/storage\";\nexport * from \"./types/storage-type\";\n//#endregion\n\n//#region Clients\nexport * from \"./clients/ftp-storage-client\";\nexport * from \"./clients/sftp-storage-client\";\n//#endregion\n\n//#region Factory\nexport * from \"./storage-factory\";\n//#endregion\n"],
|
|
5
4
|
"mappings": "AACA,cAAc;AACd,cAAc;AACd,cAAc;AAId,cAAc;AACd,cAAc;AAId,cAAc;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-factory.d.ts","sourceRoot":"","sources":["../src/storage-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD;;;;GAIG;AACH,qBAAa,cAAc;IACzB;;;;;;OAMG;WACU,OAAO,CAAC,CAAC,EACpB,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,iBAAiB,EACzB,EAAE,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,CAAC,CAAC;IAab,OAAO,CAAC,MAAM,CAAC,aAAa;CAU7B"}
|
package/dist/storage-factory.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FtpStorageClient } from "./clients/ftp-storage-client";
|
|
2
|
-
import { SftpStorageClient } from "./clients/sftp-storage-client";
|
|
1
|
+
import { FtpStorageClient } from "./clients/ftp-storage-client.js";
|
|
2
|
+
import { SftpStorageClient } from "./clients/sftp-storage-client.js";
|
|
3
3
|
class StorageFactory {
|
|
4
4
|
/**
|
|
5
5
|
* 스토리지에 연결하고 콜백을 실행한 후 자동으로 연결을 종료한다.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/storage-factory.ts"],
|
|
4
|
-
"sourcesContent": ["import type { StorageConnConfig } from \"./types/storage-conn-config\";\nimport type { Storage } from \"./types/storage\";\nimport type { StorageType } from \"./types/storage-type\";\nimport { FtpStorageClient } from \"./clients/ftp-storage-client\";\nimport { SftpStorageClient } from \"./clients/sftp-storage-client\";\n\n/**\n * \uC2A4\uD1A0\uB9AC\uC9C0 \uD074\uB77C\uC774\uC5B8\uD2B8 \uD329\uD1A0\uB9AC\n *\n * FTP, FTPS, SFTP \uC2A4\uD1A0\uB9AC\uC9C0 \uC5F0\uACB0\uC744 \uC0DD\uC131\uD558\uACE0 \uAD00\uB9AC\uD55C\uB2E4.\n */\nexport class StorageFactory {\n /**\n * \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uC5F0\uACB0\uD558\uACE0 \uCF5C\uBC31\uC744 \uC2E4\uD589\uD55C \uD6C4 \uC790\uB3D9\uC73C\uB85C \uC5F0\uACB0\uC744 \uC885\uB8CC\uD55C\uB2E4.\n *\n * @remarks\n * \uCF5C\uBC31 \uD328\uD134\uC73C\uB85C \uC5F0\uACB0/\uC885\uB8CC\uAC00 \uC790\uB3D9 \uAD00\uB9AC\uB418\uBBC0\uB85C, \uC9C1\uC811 \uD074\uB77C\uC774\uC5B8\uD2B8\uB97C \uC0AC\uC6A9\uD558\uB294 \uAC83\uBCF4\uB2E4 \uAD8C\uC7A5\uB41C\uB2E4.\n * \uCF5C\uBC31\uC5D0\uC11C \uC608\uC678\uAC00 \uBC1C\uC0DD\uD574\uB3C4 \uC5F0\uACB0\uC740 \uC790\uB3D9\uC73C\uB85C \uC885\uB8CC\uB41C\uB2E4.\n */\n static async connect<R>(\n type: StorageType,\n config: StorageConnConfig,\n fn: (storage: Storage) => R | Promise<R>,\n ): Promise<R> {\n const client = StorageFactory._createClient(type);\n\n await client.connect(config);\n try {\n return await fn(client);\n } finally {\n await client.close().catch(() => {\n // \uC774\uBBF8 \uB2EB\uD78C \uACBD\uC6B0 \uBB34\uC2DC\n });\n }\n }\n\n private static _createClient(type: StorageType): Storage {\n switch (type) {\n case \"sftp\":\n return new SftpStorageClient();\n case \"ftps\":\n return new FtpStorageClient(true);\n case \"ftp\":\n return new FtpStorageClient(false);\n }\n }\n}\n"],
|
|
5
4
|
"mappings": "AAGA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAO3B,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1B,aAAa,QACX,MACA,QACA,IACY;AACZ,UAAM,SAAS,eAAe,cAAc,IAAI;AAEhD,UAAM,OAAO,QAAQ,MAAM;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG,MAAM;AAAA,IACxB,UAAE;AACA,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,MAEjC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAe,cAAc,MAA4B;AACvD,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,IAAI,kBAAkB;AAAA,MAC/B,KAAK;AACH,eAAO,IAAI,iBAAiB,IAAI;AAAA,MAClC,KAAK;AACH,eAAO,IAAI,iBAAiB,KAAK;AAAA,IACrC;AAAA,EACF;AACF;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-conn-config.d.ts","sourceRoot":"","sources":["../../src/types/storage-conn-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-type.d.ts","sourceRoot":"","sources":["../../src/types/storage-type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/storage",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "13.0.
|
|
4
|
+
"version": "13.0.2",
|
|
5
5
|
"description": "심플리즘 패키지 - 스토리지 모듈 (node)",
|
|
6
6
|
"author": "김석래",
|
|
7
7
|
"repository": {
|
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
"main": "./dist/index.js",
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
16
|
"files": [
|
|
17
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
18
19
|
],
|
|
19
20
|
"dependencies": {
|
|
20
|
-
"@simplysm/core-common": "workspace:*",
|
|
21
21
|
"basic-ftp": "^5.1.0",
|
|
22
|
-
"ssh2-sftp-client": "^12.0.1"
|
|
22
|
+
"ssh2-sftp-client": "^12.0.1",
|
|
23
|
+
"@simplysm/core-common": "13.0.2"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@types/ssh2-sftp-client": "^9.0.6"
|
|
26
27
|
}
|
|
27
|
-
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
+
import { bytesConcat, SdError } from "@simplysm/core-common";
|
|
3
|
+
import ftp from "basic-ftp";
|
|
4
|
+
import { PassThrough, Readable } from "stream";
|
|
5
|
+
import type { Storage, FileInfo } from "../types/storage";
|
|
6
|
+
import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* FTP/FTPS 프로토콜을 사용하는 스토리지 클라이언트.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* 생성자의 `secure` 파라미터로 FTPS 사용 여부를 설정합니다.
|
|
13
|
+
* 직접 사용보다 {@link StorageFactory.connect}를 통한 사용을 권장합니다.
|
|
14
|
+
*/
|
|
15
|
+
export class FtpStorageClient implements Storage {
|
|
16
|
+
private _client: ftp.Client | undefined;
|
|
17
|
+
|
|
18
|
+
constructor(private readonly _secure: boolean = false) {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* FTP 서버에 연결합니다.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* - 연결 후 반드시 {@link close}로 연결을 종료해야 합니다.
|
|
25
|
+
* - 동일 인스턴스에서 여러 번 호출하지 마세요. (연결 누수 발생)
|
|
26
|
+
* - 자동 연결/종료 관리가 필요하면 {@link StorageFactory.connect}를 사용하세요. (권장)
|
|
27
|
+
*/
|
|
28
|
+
async connect(config: StorageConnConfig): Promise<void> {
|
|
29
|
+
if (this._client !== undefined) {
|
|
30
|
+
throw new SdError("이미 FTP 서버에 연결되어 있습니다. 먼저 close()를 호출하세요.");
|
|
31
|
+
}
|
|
32
|
+
const client = new ftp.Client();
|
|
33
|
+
try {
|
|
34
|
+
await client.access({
|
|
35
|
+
host: config.host,
|
|
36
|
+
port: config.port,
|
|
37
|
+
user: config.user,
|
|
38
|
+
password: config.pass,
|
|
39
|
+
secure: this._secure,
|
|
40
|
+
});
|
|
41
|
+
this._client = client;
|
|
42
|
+
} catch (err) {
|
|
43
|
+
client.close();
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private _requireClient(): ftp.Client {
|
|
49
|
+
if (this._client === undefined) {
|
|
50
|
+
throw new SdError("FTP 서버에 연결되어있지 않습니다.");
|
|
51
|
+
}
|
|
52
|
+
return this._client;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 디렉토리를 생성합니다. 상위 디렉토리가 없으면 함께 생성합니다. */
|
|
56
|
+
async mkdir(dirPath: string): Promise<void> {
|
|
57
|
+
await this._requireClient().ensureDir(dirPath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async rename(fromPath: string, toPath: string): Promise<void> {
|
|
61
|
+
await this._requireClient().rename(fromPath, toPath);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async readdir(dirPath: string): Promise<FileInfo[]> {
|
|
65
|
+
const fileInfos = await this._requireClient().list(dirPath);
|
|
66
|
+
return fileInfos.map((item) => ({ name: item.name, isFile: item.isFile }));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async readFile(filePath: string): Promise<Bytes> {
|
|
70
|
+
const client = this._requireClient();
|
|
71
|
+
const chunks: Bytes[] = [];
|
|
72
|
+
const writable = new PassThrough();
|
|
73
|
+
writable.on("data", (chunk: Uint8Array) => {
|
|
74
|
+
chunks.push(chunk);
|
|
75
|
+
});
|
|
76
|
+
await client.downloadTo(writable, filePath);
|
|
77
|
+
return bytesConcat(chunks);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 파일 또는 디렉토리 존재 여부를 확인합니다.
|
|
82
|
+
*
|
|
83
|
+
* @remarks
|
|
84
|
+
* 파일 확인 시 size() 명령으로 O(1) 성능을 제공합니다.
|
|
85
|
+
* 디렉토리 확인 시 상위 디렉토리 목록을 조회하므로, 항목 수가 많으면 성능이 저하될 수 있습니다.
|
|
86
|
+
*
|
|
87
|
+
* 슬래시가 없는 경로(예: `file.txt`)는 루트 디렉토리(`/`)에서 검색합니다.
|
|
88
|
+
*
|
|
89
|
+
* 상위 디렉토리가 존재하지 않는 경우에도 false를 반환합니다.
|
|
90
|
+
* 네트워크 오류, 권한 오류 등 모든 예외도 false를 반환합니다.
|
|
91
|
+
*/
|
|
92
|
+
async exists(filePath: string): Promise<boolean> {
|
|
93
|
+
try {
|
|
94
|
+
// 파일인 경우 size()로 빠르게 확인 (O(1))
|
|
95
|
+
await this._requireClient().size(filePath);
|
|
96
|
+
return true;
|
|
97
|
+
} catch {
|
|
98
|
+
// size() 실패 시 디렉토리일 수 있으므로 list()로 확인
|
|
99
|
+
try {
|
|
100
|
+
const lastSlash = filePath.lastIndexOf("/");
|
|
101
|
+
const dirPath = lastSlash > 0 ? filePath.substring(0, lastSlash) : "/";
|
|
102
|
+
const fileName = filePath.substring(lastSlash + 1);
|
|
103
|
+
const list = await this._requireClient().list(dirPath);
|
|
104
|
+
return list.some((item) => item.name === fileName);
|
|
105
|
+
} catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async remove(filePath: string): Promise<void> {
|
|
112
|
+
await this._requireClient().remove(filePath);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** 로컬 파일 경로 또는 바이트 데이터를 원격 경로에 업로드합니다. */
|
|
116
|
+
async put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void> {
|
|
117
|
+
let param: string | Readable;
|
|
118
|
+
if (typeof localPathOrBuffer === "string") {
|
|
119
|
+
param = localPathOrBuffer;
|
|
120
|
+
} else {
|
|
121
|
+
param = Readable.from(localPathOrBuffer);
|
|
122
|
+
}
|
|
123
|
+
await this._requireClient().uploadFrom(param, storageFilePath);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async uploadDir(fromPath: string, toPath: string): Promise<void> {
|
|
127
|
+
await this._requireClient().uploadFromDir(fromPath, toPath);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 연결을 종료합니다.
|
|
132
|
+
*
|
|
133
|
+
* @remarks
|
|
134
|
+
* 이미 종료된 상태에서 호출해도 에러가 발생하지 않습니다.
|
|
135
|
+
* 종료 후에는 동일 인스턴스에서 {@link connect}를 다시 호출하여 재연결할 수 있습니다.
|
|
136
|
+
*/
|
|
137
|
+
close(): Promise<void> {
|
|
138
|
+
if (this._client === undefined) {
|
|
139
|
+
return Promise.resolve();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
this._client.close();
|
|
143
|
+
this._client = undefined;
|
|
144
|
+
return Promise.resolve();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
+
import { SdError } from "@simplysm/core-common";
|
|
3
|
+
import SftpClient from "ssh2-sftp-client";
|
|
4
|
+
import type { Storage, FileInfo } from "../types/storage";
|
|
5
|
+
import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
6
|
+
|
|
7
|
+
// ssh2-sftp-client 라이브러리 타입 정의에서 Buffer 사용
|
|
8
|
+
type SftpGetResult = string | NodeJS.WritableStream | Bytes;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* SFTP 프로토콜을 사용하는 스토리지 클라이언트.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* 직접 사용보다 {@link StorageFactory.connect}를 통한 사용을 권장합니다.
|
|
15
|
+
*/
|
|
16
|
+
export class SftpStorageClient implements Storage {
|
|
17
|
+
private _client: SftpClient | undefined;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* SFTP 서버에 연결합니다.
|
|
21
|
+
*
|
|
22
|
+
* @remarks
|
|
23
|
+
* - 연결 후 반드시 {@link close}로 연결을 종료해야 합니다.
|
|
24
|
+
* - 동일 인스턴스에서 여러 번 호출하지 마세요. (연결 누수 발생)
|
|
25
|
+
* - 자동 연결/종료 관리가 필요하면 {@link StorageFactory.connect}를 사용하세요. (권장)
|
|
26
|
+
*/
|
|
27
|
+
async connect(config: StorageConnConfig): Promise<void> {
|
|
28
|
+
if (this._client !== undefined) {
|
|
29
|
+
throw new SdError("이미 SFTP 서버에 연결되어 있습니다. 먼저 close()를 호출하세요.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const client = new SftpClient();
|
|
33
|
+
try {
|
|
34
|
+
if (config.pass != null) {
|
|
35
|
+
await client.connect({
|
|
36
|
+
host: config.host,
|
|
37
|
+
port: config.port,
|
|
38
|
+
username: config.user,
|
|
39
|
+
password: config.pass,
|
|
40
|
+
});
|
|
41
|
+
} else {
|
|
42
|
+
// SSH agent + 키 파일로 인증 시도
|
|
43
|
+
const fsP = await import("fs/promises");
|
|
44
|
+
const os = await import("os");
|
|
45
|
+
const pathMod = await import("path");
|
|
46
|
+
const keyPath = pathMod.join(os.homedir(), ".ssh", "id_ed25519");
|
|
47
|
+
|
|
48
|
+
const baseOptions = {
|
|
49
|
+
host: config.host,
|
|
50
|
+
port: config.port,
|
|
51
|
+
username: config.user,
|
|
52
|
+
...(process.env["SSH_AUTH_SOCK"] != null ? { agent: process.env["SSH_AUTH_SOCK"] } : {}),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await client.connect({
|
|
57
|
+
...baseOptions,
|
|
58
|
+
privateKey: await fsP.readFile(keyPath),
|
|
59
|
+
});
|
|
60
|
+
} catch {
|
|
61
|
+
// privateKey 파싱 실패 (암호화된 키 등) → agent만으로 재시도
|
|
62
|
+
await client.connect(baseOptions);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this._client = client;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
await client.end();
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private _requireClient(): SftpClient {
|
|
73
|
+
if (this._client === undefined) {
|
|
74
|
+
throw new SdError("SFTP 서버에 연결되어있지 않습니다.");
|
|
75
|
+
}
|
|
76
|
+
return this._client;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 디렉토리를 생성합니다. 상위 디렉토리가 없으면 함께 생성합니다. */
|
|
80
|
+
async mkdir(dirPath: string): Promise<void> {
|
|
81
|
+
await this._requireClient().mkdir(dirPath, true);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async rename(fromPath: string, toPath: string): Promise<void> {
|
|
85
|
+
await this._requireClient().rename(fromPath, toPath);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 파일 또는 디렉토리 존재 여부를 확인합니다.
|
|
90
|
+
*
|
|
91
|
+
* @remarks
|
|
92
|
+
* 상위 디렉토리가 존재하지 않는 경우에도 false를 반환합니다.
|
|
93
|
+
* 네트워크 오류, 권한 오류 등 모든 예외도 false를 반환합니다.
|
|
94
|
+
*/
|
|
95
|
+
async exists(filePath: string): Promise<boolean> {
|
|
96
|
+
try {
|
|
97
|
+
// ssh2-sftp-client의 exists()는 false | 'd' | '-' | 'l' 를 반환한다.
|
|
98
|
+
// false: 존재하지 않음, 'd': 디렉토리, '-': 파일, 'l': 심볼릭 링크
|
|
99
|
+
const result = await this._requireClient().exists(filePath);
|
|
100
|
+
return typeof result === "string";
|
|
101
|
+
} catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async readdir(dirPath: string): Promise<FileInfo[]> {
|
|
107
|
+
const list = await this._requireClient().list(dirPath);
|
|
108
|
+
return list.map((item) => ({
|
|
109
|
+
name: item.name,
|
|
110
|
+
isFile: item.type === "-",
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async readFile(filePath: string): Promise<Bytes> {
|
|
115
|
+
// ssh2-sftp-client의 get()은 dst 미전달 시 Buffer를 반환한다.
|
|
116
|
+
// 타입 정의(string | WritableStream | Buffer)와 달리 실제로는 Buffer만 반환된다.
|
|
117
|
+
const result = (await this._requireClient().get(filePath)) as SftpGetResult;
|
|
118
|
+
if (result instanceof Uint8Array) {
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
// 타입 정의상 string도 가능하므로 방어 코드
|
|
122
|
+
if (typeof result === "string") {
|
|
123
|
+
return new TextEncoder().encode(result);
|
|
124
|
+
}
|
|
125
|
+
throw new SdError("예상치 못한 응답 타입입니다.");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async remove(filePath: string): Promise<void> {
|
|
129
|
+
await this._requireClient().delete(filePath);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** 로컬 파일 경로 또는 바이트 데이터를 원격 경로에 업로드합니다. */
|
|
133
|
+
async put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void> {
|
|
134
|
+
if (typeof localPathOrBuffer === "string") {
|
|
135
|
+
await this._requireClient().fastPut(localPathOrBuffer, storageFilePath);
|
|
136
|
+
} else {
|
|
137
|
+
// eslint-disable-next-line no-restricted-globals -- ssh2-sftp-client 라이브러리 요구사항
|
|
138
|
+
await this._requireClient().put(Buffer.from(localPathOrBuffer), storageFilePath);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async uploadDir(fromPath: string, toPath: string): Promise<void> {
|
|
143
|
+
await this._requireClient().uploadDir(fromPath, toPath);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 연결을 종료합니다.
|
|
148
|
+
*
|
|
149
|
+
* @remarks
|
|
150
|
+
* 이미 종료된 상태에서 호출해도 에러가 발생하지 않습니다.
|
|
151
|
+
* 종료 후에는 동일 인스턴스에서 {@link connect}를 다시 호출하여 재연결할 수 있습니다.
|
|
152
|
+
*/
|
|
153
|
+
async close(): Promise<void> {
|
|
154
|
+
if (this._client === undefined) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
await this._client.end();
|
|
158
|
+
this._client = undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region Types
|
|
2
|
+
export * from "./types/storage-conn-config";
|
|
3
|
+
export * from "./types/storage";
|
|
4
|
+
export * from "./types/storage-type";
|
|
5
|
+
//#endregion
|
|
6
|
+
|
|
7
|
+
//#region Clients
|
|
8
|
+
export * from "./clients/ftp-storage-client";
|
|
9
|
+
export * from "./clients/sftp-storage-client";
|
|
10
|
+
//#endregion
|
|
11
|
+
|
|
12
|
+
//#region Factory
|
|
13
|
+
export * from "./storage-factory";
|
|
14
|
+
//#endregion
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { StorageConnConfig } from "./types/storage-conn-config";
|
|
2
|
+
import type { Storage } from "./types/storage";
|
|
3
|
+
import type { StorageType } from "./types/storage-type";
|
|
4
|
+
import { FtpStorageClient } from "./clients/ftp-storage-client";
|
|
5
|
+
import { SftpStorageClient } from "./clients/sftp-storage-client";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 스토리지 클라이언트 팩토리
|
|
9
|
+
*
|
|
10
|
+
* FTP, FTPS, SFTP 스토리지 연결을 생성하고 관리한다.
|
|
11
|
+
*/
|
|
12
|
+
export class StorageFactory {
|
|
13
|
+
/**
|
|
14
|
+
* 스토리지에 연결하고 콜백을 실행한 후 자동으로 연결을 종료한다.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* 콜백 패턴으로 연결/종료가 자동 관리되므로, 직접 클라이언트를 사용하는 것보다 권장된다.
|
|
18
|
+
* 콜백에서 예외가 발생해도 연결은 자동으로 종료된다.
|
|
19
|
+
*/
|
|
20
|
+
static async connect<R>(
|
|
21
|
+
type: StorageType,
|
|
22
|
+
config: StorageConnConfig,
|
|
23
|
+
fn: (storage: Storage) => R | Promise<R>,
|
|
24
|
+
): Promise<R> {
|
|
25
|
+
const client = StorageFactory._createClient(type);
|
|
26
|
+
|
|
27
|
+
await client.connect(config);
|
|
28
|
+
try {
|
|
29
|
+
return await fn(client);
|
|
30
|
+
} finally {
|
|
31
|
+
await client.close().catch(() => {
|
|
32
|
+
// 이미 닫힌 경우 무시
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private static _createClient(type: StorageType): Storage {
|
|
38
|
+
switch (type) {
|
|
39
|
+
case "sftp":
|
|
40
|
+
return new SftpStorageClient();
|
|
41
|
+
case "ftps":
|
|
42
|
+
return new FtpStorageClient(true);
|
|
43
|
+
case "ftp":
|
|
44
|
+
return new FtpStorageClient(false);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type StorageType = "ftp" | "ftps" | "sftp";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
+
import type { StorageConnConfig } from "./storage-conn-config";
|
|
3
|
+
|
|
4
|
+
export interface FileInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
isFile: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Storage {
|
|
10
|
+
connect(config: StorageConnConfig): Promise<void>;
|
|
11
|
+
mkdir(dirPath: string): Promise<void>;
|
|
12
|
+
rename(fromPath: string, toPath: string): Promise<void>;
|
|
13
|
+
readdir(dirPath: string): Promise<FileInfo[]>;
|
|
14
|
+
readFile(filePath: string): Promise<Bytes>;
|
|
15
|
+
exists(filePath: string): Promise<boolean>;
|
|
16
|
+
put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void>;
|
|
17
|
+
uploadDir(fromPath: string, toPath: string): Promise<void>;
|
|
18
|
+
remove(filePath: string): Promise<void>;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
}
|