@carlonicora/nestjs-neo4jsonapi 1.98.0 → 1.100.0
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/bootstrap/app.module.factory.d.ts.map +1 -1
- package/dist/bootstrap/app.module.factory.js +14 -5
- package/dist/bootstrap/app.module.factory.js.map +1 -1
- package/dist/bootstrap/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap/bootstrap.js +31 -7
- package/dist/bootstrap/bootstrap.js.map +1 -1
- package/dist/bootstrap/bootstrap.options.d.ts +52 -0
- package/dist/bootstrap/bootstrap.options.d.ts.map +1 -1
- package/dist/common/filters/http-exception.filter.d.ts.map +1 -1
- package/dist/common/filters/http-exception.filter.js +9 -0
- package/dist/common/filters/http-exception.filter.js.map +1 -1
- package/dist/common/filters/index.d.ts +1 -0
- package/dist/common/filters/index.d.ts.map +1 -1
- package/dist/common/filters/index.js +1 -0
- package/dist/common/filters/index.js.map +1 -1
- package/dist/common/filters/throttler-exception.filter.d.ts +10 -0
- package/dist/common/filters/throttler-exception.filter.d.ts.map +1 -0
- package/dist/common/filters/throttler-exception.filter.js +34 -0
- package/dist/common/filters/throttler-exception.filter.js.map +1 -0
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +29 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/interfaces/config.ai.interface.d.ts +67 -0
- package/dist/config/interfaces/config.ai.interface.d.ts.map +1 -1
- package/dist/core/core.module.d.ts +10 -1
- package/dist/core/core.module.d.ts.map +1 -1
- package/dist/core/core.module.js +5 -4
- package/dist/core/core.module.js.map +1 -1
- package/dist/core/email/services/email.service.d.ts +12 -3
- package/dist/core/email/services/email.service.d.ts.map +1 -1
- package/dist/core/email/services/email.service.js +67 -32
- package/dist/core/email/services/email.service.js.map +1 -1
- package/dist/core/jsonapi/services/jsonapi.service.d.ts +1 -1
- package/dist/core/jsonapi/services/jsonapi.service.d.ts.map +1 -1
- package/dist/core/jsonapi/services/jsonapi.service.js +3 -3
- package/dist/core/jsonapi/services/jsonapi.service.js.map +1 -1
- package/dist/core/llm/index.d.ts +4 -0
- package/dist/core/llm/index.d.ts.map +1 -1
- package/dist/core/llm/index.js +4 -0
- package/dist/core/llm/index.js.map +1 -1
- package/dist/core/llm/llm.module.d.ts.map +1 -1
- package/dist/core/llm/llm.module.js +8 -1
- package/dist/core/llm/llm.module.js.map +1 -1
- package/dist/core/llm/services/document-ai.service.d.ts +35 -0
- package/dist/core/llm/services/document-ai.service.d.ts.map +1 -0
- package/dist/core/llm/services/document-ai.service.js +100 -0
- package/dist/core/llm/services/document-ai.service.js.map +1 -0
- package/dist/core/llm/services/embedder-token-bucket.service.d.ts +29 -0
- package/dist/core/llm/services/embedder-token-bucket.service.d.ts.map +1 -0
- package/dist/core/llm/services/embedder-token-bucket.service.js +127 -0
- package/dist/core/llm/services/embedder-token-bucket.service.js.map +1 -0
- package/dist/core/llm/services/llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/llm.service.js +8 -0
- package/dist/core/llm/services/llm.service.js.map +1 -1
- package/dist/core/llm/services/model.service.d.ts +42 -2
- package/dist/core/llm/services/model.service.d.ts.map +1 -1
- package/dist/core/llm/services/model.service.js +108 -3
- package/dist/core/llm/services/model.service.js.map +1 -1
- package/dist/core/llm/services/rate-limited-embedder.d.ts +31 -0
- package/dist/core/llm/services/rate-limited-embedder.d.ts.map +1 -0
- package/dist/core/llm/services/rate-limited-embedder.js +194 -0
- package/dist/core/llm/services/rate-limited-embedder.js.map +1 -0
- package/dist/core/llm/services/vision.llm.service.d.ts +16 -0
- package/dist/core/llm/services/vision.llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/vision.llm.service.js +46 -5
- package/dist/core/llm/services/vision.llm.service.js.map +1 -1
- package/dist/core/llm/utils/mock-from-zod.d.ts +3 -0
- package/dist/core/llm/utils/mock-from-zod.d.ts.map +1 -0
- package/dist/core/llm/utils/mock-from-zod.js +47 -0
- package/dist/core/llm/utils/mock-from-zod.js.map +1 -0
- package/dist/core/neo4j/services/neo4j.service.d.ts +3 -1
- package/dist/core/neo4j/services/neo4j.service.d.ts.map +1 -1
- package/dist/core/neo4j/services/neo4j.service.js +16 -8
- package/dist/core/neo4j/services/neo4j.service.js.map +1 -1
- package/dist/core/redis/services/redis.client.storage.service.d.ts +14 -0
- package/dist/core/redis/services/redis.client.storage.service.d.ts.map +1 -1
- package/dist/core/redis/services/redis.client.storage.service.js +28 -0
- package/dist/core/redis/services/redis.client.storage.service.js.map +1 -1
- package/dist/core/security/security.module.d.ts +12 -0
- package/dist/core/security/security.module.d.ts.map +1 -1
- package/dist/core/security/security.module.js +20 -2
- package/dist/core/security/security.module.js.map +1 -1
- package/dist/core/websocket/services/presence.service.d.ts +3 -1
- package/dist/core/websocket/services/presence.service.d.ts.map +1 -1
- package/dist/core/websocket/services/presence.service.js +14 -11
- package/dist/core/websocket/services/presence.service.js.map +1 -1
- package/dist/core/websocket/services/websocket.service.d.ts +9 -5
- package/dist/core/websocket/services/websocket.service.d.ts.map +1 -1
- package/dist/core/websocket/services/websocket.service.js +12 -4
- package/dist/core/websocket/services/websocket.service.js.map +1 -1
- package/dist/foundations/chunk/entities/chunk.entity.d.ts +1 -0
- package/dist/foundations/chunk/entities/chunk.entity.d.ts.map +1 -1
- package/dist/foundations/chunk/entities/chunk.entity.js +1 -0
- package/dist/foundations/chunk/entities/chunk.entity.js.map +1 -1
- package/dist/foundations/chunker/chunker.module.d.ts.map +1 -1
- package/dist/foundations/chunker/chunker.module.js +3 -1
- package/dist/foundations/chunker/chunker.module.js.map +1 -1
- package/dist/foundations/chunker/index.d.ts +1 -0
- package/dist/foundations/chunker/index.d.ts.map +1 -1
- package/dist/foundations/chunker/index.js +1 -0
- package/dist/foundations/chunker/index.js.map +1 -1
- package/dist/foundations/chunker/services/chunker.service.d.ts +6 -1
- package/dist/foundations/chunker/services/chunker.service.d.ts.map +1 -1
- package/dist/foundations/chunker/services/chunker.service.js +123 -1
- package/dist/foundations/chunker/services/chunker.service.js.map +1 -1
- package/dist/foundations/chunker/services/types/email.service.d.ts +35 -0
- package/dist/foundations/chunker/services/types/email.service.d.ts.map +1 -0
- package/dist/foundations/chunker/services/types/email.service.js +124 -0
- package/dist/foundations/chunker/services/types/email.service.js.map +1 -0
- package/dist/foundations/foundations.modules.d.ts +6 -1
- package/dist/foundations/foundations.modules.d.ts.map +1 -1
- package/dist/foundations/foundations.modules.js +4 -6
- package/dist/foundations/foundations.modules.js.map +1 -1
- package/dist/foundations/s3/services/s3.service.d.ts +83 -0
- package/dist/foundations/s3/services/s3.service.d.ts.map +1 -1
- package/dist/foundations/s3/services/s3.service.js +267 -0
- package/dist/foundations/s3/services/s3.service.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var EmailParserService_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.EmailParserService = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const mailparser_1 = require("mailparser");
|
|
13
|
+
let EmailParserService = EmailParserService_1 = class EmailParserService {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.logger = new common_1.Logger(EmailParserService_1.name);
|
|
16
|
+
}
|
|
17
|
+
async parseEml(buffer) {
|
|
18
|
+
const parsed = await (0, mailparser_1.simpleParser)(buffer);
|
|
19
|
+
const formatAddress = (addr) => {
|
|
20
|
+
if (!addr)
|
|
21
|
+
return "";
|
|
22
|
+
if (typeof addr === "string")
|
|
23
|
+
return addr;
|
|
24
|
+
if (addr.text)
|
|
25
|
+
return addr.text;
|
|
26
|
+
if (addr.value) {
|
|
27
|
+
return addr.value.map((v) => v.address || v.name || "").join(", ");
|
|
28
|
+
}
|
|
29
|
+
return String(addr);
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
subject: parsed.subject || "(No Subject)",
|
|
33
|
+
from: formatAddress(parsed.from),
|
|
34
|
+
to: formatAddress(parsed.to),
|
|
35
|
+
cc: parsed.cc ? formatAddress(parsed.cc) : undefined,
|
|
36
|
+
date: parsed.date?.toISOString() || "",
|
|
37
|
+
textBody: parsed.text || "",
|
|
38
|
+
htmlBody: parsed.html || undefined,
|
|
39
|
+
attachments: (parsed.attachments || []).map((att) => ({
|
|
40
|
+
filename: att.filename || "unnamed",
|
|
41
|
+
contentType: att.contentType || "application/octet-stream",
|
|
42
|
+
content: att.content,
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async parseMsg(buffer) {
|
|
47
|
+
// Dynamic import since msgreader uses default export
|
|
48
|
+
const MsgReaderModule = await import("@kenjiuno/msgreader");
|
|
49
|
+
const MsgReader = MsgReaderModule.default;
|
|
50
|
+
const arrayBuffer = new Uint8Array(buffer).buffer;
|
|
51
|
+
const reader = new MsgReader(arrayBuffer);
|
|
52
|
+
const msgData = reader.getFileData();
|
|
53
|
+
const toRecipients = (msgData.recipients || [])
|
|
54
|
+
.filter((r) => !r.recipType || r.recipType === "to" || r.recipType === 1)
|
|
55
|
+
.map((r) => {
|
|
56
|
+
const name = r.name || "";
|
|
57
|
+
const email = r.email || "";
|
|
58
|
+
return email ? (name ? `${name} <${email}>` : email) : name;
|
|
59
|
+
})
|
|
60
|
+
.join(", ");
|
|
61
|
+
const ccRecipients = (msgData.recipients || [])
|
|
62
|
+
.filter((r) => r.recipType === "cc" || r.recipType === 2)
|
|
63
|
+
.map((r) => {
|
|
64
|
+
const name = r.name || "";
|
|
65
|
+
const email = r.email || "";
|
|
66
|
+
return email ? (name ? `${name} <${email}>` : email) : name;
|
|
67
|
+
})
|
|
68
|
+
.join(", ");
|
|
69
|
+
const senderName = msgData.senderName || "";
|
|
70
|
+
const senderEmail = msgData.senderEmail || "";
|
|
71
|
+
const from = senderEmail ? (senderName ? `${senderName} <${senderEmail}>` : senderEmail) : senderName;
|
|
72
|
+
const attachments = [];
|
|
73
|
+
if (msgData.attachments) {
|
|
74
|
+
for (const attMeta of msgData.attachments) {
|
|
75
|
+
const att = reader.getAttachment(attMeta);
|
|
76
|
+
if (att) {
|
|
77
|
+
attachments.push({
|
|
78
|
+
filename: att.fileName || "unnamed",
|
|
79
|
+
contentType: "application/octet-stream",
|
|
80
|
+
content: Buffer.from(att.content),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
subject: msgData.subject || "(No Subject)",
|
|
87
|
+
from,
|
|
88
|
+
to: toRecipients,
|
|
89
|
+
cc: ccRecipients || undefined,
|
|
90
|
+
date: msgData.clientSubmitTime || msgData.creationTime || "",
|
|
91
|
+
textBody: msgData.body || "",
|
|
92
|
+
attachments,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
assembleMarkdown(params) {
|
|
96
|
+
const sections = [];
|
|
97
|
+
sections.push(`# Email: ${params.subject}`);
|
|
98
|
+
sections.push(`**From:** ${params.from}`);
|
|
99
|
+
sections.push(`**To:** ${params.to}`);
|
|
100
|
+
if (params.cc) {
|
|
101
|
+
sections.push(`**CC:** ${params.cc}`);
|
|
102
|
+
}
|
|
103
|
+
if (params.date) {
|
|
104
|
+
sections.push(`**Date:** ${params.date}`);
|
|
105
|
+
}
|
|
106
|
+
sections.push("---");
|
|
107
|
+
if (params.textBody) {
|
|
108
|
+
sections.push(params.textBody);
|
|
109
|
+
}
|
|
110
|
+
if (params.attachmentContents && params.attachmentContents.length > 0) {
|
|
111
|
+
sections.push("---");
|
|
112
|
+
for (const att of params.attachmentContents) {
|
|
113
|
+
sections.push(`## Attachment: ${att.filename}`);
|
|
114
|
+
sections.push(att.content);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return sections.join("\n\n");
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
exports.EmailParserService = EmailParserService;
|
|
121
|
+
exports.EmailParserService = EmailParserService = EmailParserService_1 = __decorate([
|
|
122
|
+
(0, common_1.Injectable)()
|
|
123
|
+
], EmailParserService);
|
|
124
|
+
//# sourceMappingURL=email.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.service.js","sourceRoot":"","sources":["../../../../../src/foundations/chunker/services/types/email.service.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAoD;AACpD,2CAA0C;AAyBnC,IAAM,kBAAkB,0BAAxB,MAAM,kBAAkB;IAAxB;QACG,WAAM,GAAW,IAAI,eAAM,CAAC,oBAAkB,CAAC,IAAI,CAAC,CAAC;IA6H/D,CAAC;IA3HC,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAY,EAAC,MAAM,CAAC,CAAC;QAE1C,MAAM,aAAa,GAAG,CAAC,IAAS,EAAU,EAAE;YAC1C,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,CAAC;YACrB,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC,IAAI,CAAC;YAChC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,cAAc;YACzC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC;YAChC,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YACpD,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;YACtC,QAAQ,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;YAC3B,QAAQ,EAAE,MAAM,CAAC,IAAI,IAAI,SAAS;YAClC,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACpD,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,SAAS;gBACnC,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,0BAA0B;gBAC1D,OAAO,EAAE,GAAG,CAAC,OAAO;aACrB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,qDAAqD;QACrD,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,OAAoD,CAAC;QAEvF,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,MAAqB,CAAC;QACjE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QAErC,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;aAC5C,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC;aAC7E,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YACd,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;aAC5C,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC;aAC7D,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YACd,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;QAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,KAAK,WAAW,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QAEtG,MAAM,WAAW,GAA4B,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBAC1C,IAAI,GAAG,EAAE,CAAC;oBACR,WAAW,CAAC,IAAI,CAAC;wBACf,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,SAAS;wBACnC,WAAW,EAAE,0BAA0B;wBACvC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;qBAClC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,cAAc;YAC1C,IAAI;YACJ,EAAE,EAAE,YAAY;YAChB,EAAE,EAAE,YAAY,IAAI,SAAS;YAC7B,IAAI,EAAE,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,YAAY,IAAI,EAAE;YAC5D,QAAQ,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;YAC5B,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,MAShB;QACC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,QAAQ,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5C,QAAQ,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErB,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,kBAAkB,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAChD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;CACF,CAAA;AA9HY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;GACA,kBAAkB,CA8H9B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DynamicModule } from "@nestjs/common";
|
|
1
|
+
import { DynamicModule, Type } from "@nestjs/common";
|
|
2
2
|
import { ContentExtensionConfig } from "./content/interfaces/content.extension.interface";
|
|
3
3
|
import { ReferralModuleConfig } from "./referral/interfaces/referral.config.interface";
|
|
4
4
|
/**
|
|
@@ -9,6 +9,11 @@ export interface FoundationsModuleConfig {
|
|
|
9
9
|
contentExtension?: ContentExtensionConfig;
|
|
10
10
|
/** Optional configuration for the referral feature module */
|
|
11
11
|
referral?: ReferralModuleConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Foundation module classes to exclude from registration.
|
|
14
|
+
* Default [] keeps all modules registered (neural-erp behavior unchanged).
|
|
15
|
+
*/
|
|
16
|
+
exclude?: Type<any>[];
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* FoundationsModule - Centralized module for all foundation/domain modules
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundations.modules.d.ts","sourceRoot":"","sources":["../../src/foundations/foundations.modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"foundations.modules.d.ts","sourceRoot":"","sources":["../../src/foundations/foundations.modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAS7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAC;AAE1F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AA0BvF;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;CACvB;AAwCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBACa,iBAAiB;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,uBAAuB,GAAG,aAAa;CAShE"}
|
|
@@ -114,14 +114,12 @@ let FoundationsModule = FoundationsModule_1 = class FoundationsModule {
|
|
|
114
114
|
* @returns DynamicModule with all foundation modules configured
|
|
115
115
|
*/
|
|
116
116
|
static forRoot(config) {
|
|
117
|
+
const excluded = new Set(config?.exclude ?? []);
|
|
118
|
+
const modules = STATIC_FOUNDATION_MODULES.filter((m) => !excluded.has(m));
|
|
117
119
|
return {
|
|
118
120
|
module: FoundationsModule_1,
|
|
119
|
-
imports: [
|
|
120
|
-
|
|
121
|
-
content_module_1.ContentModule.forRoot(config?.contentExtension),
|
|
122
|
-
referral_module_1.ReferralModule.forRoot(config?.referral),
|
|
123
|
-
],
|
|
124
|
-
exports: [...STATIC_FOUNDATION_MODULES, content_module_1.ContentModule, referral_module_1.ReferralModule],
|
|
121
|
+
imports: [...modules, content_module_1.ContentModule.forRoot(config?.contentExtension), referral_module_1.ReferralModule.forRoot(config?.referral)],
|
|
122
|
+
exports: [...modules, content_module_1.ContentModule, referral_module_1.ReferralModule],
|
|
125
123
|
};
|
|
126
124
|
}
|
|
127
125
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundations.modules.js","sourceRoot":"","sources":["../../src/foundations/foundations.modules.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"foundations.modules.js","sourceRoot":"","sources":["../../src/foundations/foundations.modules.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA6D;AAC7D,mEAA+D;AAC/D,sEAAkE;AAClE,uDAAmD;AACnD,oDAAgD;AAChD,uDAAmD;AACnD,6DAAyD;AACzD,6DAAyD;AACzD,6DAAyD;AAEzD,gEAA4D;AAE5D,4EAAuE;AACvE,6DAAyD;AACzD,0DAAqD;AACrD,sEAAkE;AAClE,0DAAsD;AACtD,4EAAwE;AACxE,uDAAmD;AACnD,oDAAgD;AAChD,mEAA+D;AAC/D,oDAAgD;AAChD,8CAA0C;AAC1C,kFAA6E;AAC7E,iDAAmD;AACnD,qDAAuD;AACvD,mEAAoE;AACpE,+DAAiE;AACjE,4EAAuE;AACvE,kFAA6E;AAC7E,0DAAsD;AACtD,4EAAuE;AACvE,sEAAkE;AAClE,sEAAiE;AACjE,oDAAgD;AAChD,gEAA4D;AAiB5D;;;GAGG;AACH,MAAM,yBAAyB,GAAG;IAChC,kCAAe;IACf,oCAAgB;IAChB,0BAAW;IACX,wBAAU;IACV,0BAAW;IACX,8BAAa;IACb,8BAAa;IACb,uCAAiB;IACjB,8BAAa;IACb,2BAAW;IACX,oCAAgB;IAChB,4BAAY;IACZ,wCAAkB;IAClB,0BAAW;IACX,wBAAU;IACV,kCAAe;IACf,wBAAU;IACV,oBAAQ;IACR,oCAAgB;IAChB,mCAAe;IACf,wBAAU;IACV,gCAAc;IACd,4BAAY;IACZ,iDAAyB;IACzB,8CAAwB;IACxB,gCAAiB;IACjB,oCAAmB;IACnB,2CAAmB;IACnB,uCAAiB;IACjB,2CAAmB;IACnB,uCAAiB;CAClB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEI,IAAM,iBAAiB,yBAAvB,MAAM,iBAAiB;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,MAAgC;QAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAY,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,OAAO;YACL,MAAM,EAAE,mBAAiB;YACzB,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,8BAAa,CAAC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,gCAAc,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAChH,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,8BAAa,EAAE,gCAAc,CAAC;SACrD,CAAC;IACJ,CAAC;CACF,CAAA;AAhBY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,iBAAiB,CAgB7B"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Readable } from "stream";
|
|
1
2
|
import { ConfigService } from "@nestjs/config";
|
|
2
3
|
import { ClsService } from "nestjs-cls";
|
|
3
4
|
import { BaseConfigInterface } from "../../../config/interfaces";
|
|
@@ -78,5 +79,87 @@ export declare class S3Service {
|
|
|
78
79
|
key: string;
|
|
79
80
|
}): Promise<string>;
|
|
80
81
|
private _getAzureObjectContent;
|
|
82
|
+
/**
|
|
83
|
+
* Single-page list for streaming consumers. Unlike listObjects (which accumulates every page
|
|
84
|
+
* into one array), this returns one page plus the continuation token so the caller can resume
|
|
85
|
+
* on demand. StartAfter lets a caller resume after a known key; it is ignored when
|
|
86
|
+
* ContinuationToken is set.
|
|
87
|
+
*/
|
|
88
|
+
listObjectsPage(params: {
|
|
89
|
+
prefix: string;
|
|
90
|
+
startAfter?: string;
|
|
91
|
+
continuationToken?: string;
|
|
92
|
+
maxKeys?: number;
|
|
93
|
+
}): Promise<{
|
|
94
|
+
objects: {
|
|
95
|
+
key: string;
|
|
96
|
+
size: number;
|
|
97
|
+
}[];
|
|
98
|
+
nextContinuationToken?: string;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Download a file from S3/Azure and return both its buffer and the response Content-Type.
|
|
102
|
+
* Used by workers that hash + re-upload while preserving the original content type.
|
|
103
|
+
*/
|
|
104
|
+
downloadFileBuffer(params: {
|
|
105
|
+
key: string;
|
|
106
|
+
}): Promise<{
|
|
107
|
+
buffer: Buffer;
|
|
108
|
+
contentType?: string;
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Upload a readable stream with an exact key using multipart upload.
|
|
112
|
+
* Unlike uploadBufferWithKey, this streams data without holding the full content in memory.
|
|
113
|
+
*/
|
|
114
|
+
uploadStream(params: {
|
|
115
|
+
key: string;
|
|
116
|
+
contentType: string;
|
|
117
|
+
stream: Readable;
|
|
118
|
+
}): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Copy a file from one location to another within the same bucket/container.
|
|
121
|
+
* Supports both S3-compatible storage and Azure Blob Storage.
|
|
122
|
+
*/
|
|
123
|
+
copyFile(params: {
|
|
124
|
+
sourceKey: string;
|
|
125
|
+
destinationKey: string;
|
|
126
|
+
}): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* List all objects under a given prefix.
|
|
129
|
+
* Handles pagination for S3-compatible storage and Azure.
|
|
130
|
+
*/
|
|
131
|
+
listObjects(params: {
|
|
132
|
+
prefix: string;
|
|
133
|
+
}): Promise<{
|
|
134
|
+
key: string;
|
|
135
|
+
size: number;
|
|
136
|
+
}[]>;
|
|
137
|
+
private _listAzureObjects;
|
|
138
|
+
/**
|
|
139
|
+
* Download a file from S3/Azure and return its content as a string.
|
|
140
|
+
* Useful for reading JSON or HTML content stored in object storage.
|
|
141
|
+
*/
|
|
142
|
+
downloadFileAsString(params: {
|
|
143
|
+
key: string;
|
|
144
|
+
}): Promise<string | null>;
|
|
145
|
+
private _downloadAzureFileAsString;
|
|
146
|
+
/**
|
|
147
|
+
* Download a file from S3/Azure and return its content as a Buffer.
|
|
148
|
+
* Useful for reading binary files like attachments.
|
|
149
|
+
*/
|
|
150
|
+
downloadFileAsBuffer(params: {
|
|
151
|
+
key: string;
|
|
152
|
+
}): Promise<Buffer | null>;
|
|
153
|
+
private _downloadAzureFileAsBuffer;
|
|
154
|
+
/**
|
|
155
|
+
* Upload a buffer with an exact key — NO extension appending.
|
|
156
|
+
* Unlike uploadFile (which adds .pdf, .zip, etc.), this method
|
|
157
|
+
* preserves the key exactly as provided.
|
|
158
|
+
*/
|
|
159
|
+
uploadBufferWithKey(params: {
|
|
160
|
+
buffer: Buffer;
|
|
161
|
+
key: string;
|
|
162
|
+
contentType: string;
|
|
163
|
+
}): Promise<void>;
|
|
81
164
|
}
|
|
82
165
|
//# sourceMappingURL=s3.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.service.d.ts","sourceRoot":"","sources":["../../../../src/foundations/s3/services/s3.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"s3.service.d.ts","sourceRoot":"","sources":["../../../../src/foundations/s3/services/s3.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.S3Service = void 0;
|
|
13
13
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
14
|
+
const lib_storage_1 = require("@aws-sdk/lib-storage");
|
|
14
15
|
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
15
16
|
const storage_blob_1 = require("@azure/storage-blob");
|
|
16
17
|
const common_1 = require("@nestjs/common");
|
|
@@ -520,6 +521,272 @@ let S3Service = class S3Service {
|
|
|
520
521
|
throw error;
|
|
521
522
|
}
|
|
522
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Single-page list for streaming consumers. Unlike listObjects (which accumulates every page
|
|
526
|
+
* into one array), this returns one page plus the continuation token so the caller can resume
|
|
527
|
+
* on demand. StartAfter lets a caller resume after a known key; it is ignored when
|
|
528
|
+
* ContinuationToken is set.
|
|
529
|
+
*/
|
|
530
|
+
async listObjectsPage(params) {
|
|
531
|
+
await this._loadConfiguration();
|
|
532
|
+
if (!this._endpoint)
|
|
533
|
+
return { objects: [] };
|
|
534
|
+
if (this._storageType === "azure") {
|
|
535
|
+
throw new Error("listObjectsPage is not supported for azure storage");
|
|
536
|
+
}
|
|
537
|
+
const listResponse = await this.s3Client.send(new client_s3_1.ListObjectsV2Command({
|
|
538
|
+
Bucket: this._bucket,
|
|
539
|
+
Prefix: params.prefix,
|
|
540
|
+
StartAfter: params.continuationToken ? undefined : params.startAfter,
|
|
541
|
+
ContinuationToken: params.continuationToken,
|
|
542
|
+
MaxKeys: params.maxKeys,
|
|
543
|
+
}));
|
|
544
|
+
const objects = [];
|
|
545
|
+
for (const obj of listResponse.Contents ?? []) {
|
|
546
|
+
if (obj.Key && obj.Size !== undefined)
|
|
547
|
+
objects.push({ key: obj.Key, size: obj.Size });
|
|
548
|
+
}
|
|
549
|
+
return { objects, nextContinuationToken: listResponse.NextContinuationToken };
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Download a file from S3/Azure and return both its buffer and the response Content-Type.
|
|
553
|
+
* Used by workers that hash + re-upload while preserving the original content type.
|
|
554
|
+
*/
|
|
555
|
+
async downloadFileBuffer(params) {
|
|
556
|
+
await this._loadConfiguration();
|
|
557
|
+
if (!this._endpoint) {
|
|
558
|
+
throw new Error("S3 not configured");
|
|
559
|
+
}
|
|
560
|
+
if (this._storageType === "azure") {
|
|
561
|
+
const blobClient = this.containerClient.getBlobClient(params.key);
|
|
562
|
+
const downloadResponse = await blobClient.download();
|
|
563
|
+
if (!downloadResponse.readableStreamBody) {
|
|
564
|
+
throw new Error(`Azure blob not found: ${params.key}`);
|
|
565
|
+
}
|
|
566
|
+
const chunks = [];
|
|
567
|
+
for await (const chunk of downloadResponse.readableStreamBody) {
|
|
568
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
buffer: Buffer.concat(chunks),
|
|
572
|
+
contentType: downloadResponse.contentType ?? undefined,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
const command = new client_s3_1.GetObjectCommand({
|
|
576
|
+
Bucket: this._bucket,
|
|
577
|
+
Key: params.key,
|
|
578
|
+
});
|
|
579
|
+
const response = await this.s3Client.send(command);
|
|
580
|
+
if (!response.Body) {
|
|
581
|
+
throw new Error(`S3 object not found: ${params.key}`);
|
|
582
|
+
}
|
|
583
|
+
const chunks = [];
|
|
584
|
+
for await (const chunk of response.Body) {
|
|
585
|
+
chunks.push(Buffer.from(chunk));
|
|
586
|
+
}
|
|
587
|
+
return {
|
|
588
|
+
buffer: Buffer.concat(chunks),
|
|
589
|
+
contentType: response.ContentType,
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Upload a readable stream with an exact key using multipart upload.
|
|
594
|
+
* Unlike uploadBufferWithKey, this streams data without holding the full content in memory.
|
|
595
|
+
*/
|
|
596
|
+
async uploadStream(params) {
|
|
597
|
+
await this._loadConfiguration();
|
|
598
|
+
if (!this._endpoint)
|
|
599
|
+
return;
|
|
600
|
+
if (this._storageType === "azure") {
|
|
601
|
+
const blobClient = this.containerClient.getBlockBlobClient(params.key);
|
|
602
|
+
await blobClient.uploadStream(params.stream, 8 * 1024 * 1024, 4, {
|
|
603
|
+
blobHTTPHeaders: { blobContentType: params.contentType },
|
|
604
|
+
});
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
// S3-compatible storage — multipart upload via @aws-sdk/lib-storage
|
|
608
|
+
const upload = new lib_storage_1.Upload({
|
|
609
|
+
client: this.s3Client,
|
|
610
|
+
params: {
|
|
611
|
+
Bucket: this._bucket,
|
|
612
|
+
Key: params.key,
|
|
613
|
+
Body: params.stream,
|
|
614
|
+
ContentType: params.contentType,
|
|
615
|
+
},
|
|
616
|
+
partSize: 10 * 1024 * 1024,
|
|
617
|
+
queueSize: 4,
|
|
618
|
+
});
|
|
619
|
+
await upload.done();
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Copy a file from one location to another within the same bucket/container.
|
|
623
|
+
* Supports both S3-compatible storage and Azure Blob Storage.
|
|
624
|
+
*/
|
|
625
|
+
async copyFile(params) {
|
|
626
|
+
await this._loadConfiguration();
|
|
627
|
+
if (!this._endpoint)
|
|
628
|
+
return;
|
|
629
|
+
if (this._storageType === "azure") {
|
|
630
|
+
const sourceBlobClient = this.containerClient.getBlobClient(params.sourceKey);
|
|
631
|
+
const destBlobClient = this.containerClient.getBlobClient(params.destinationKey);
|
|
632
|
+
const copyPoller = await destBlobClient.beginCopyFromURL(sourceBlobClient.url);
|
|
633
|
+
await copyPoller.pollUntilDone();
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
// S3-compatible storage (AWS, DigitalOcean, Hetzner, MinIO)
|
|
637
|
+
const command = new client_s3_1.CopyObjectCommand({
|
|
638
|
+
Bucket: this._bucket,
|
|
639
|
+
CopySource: `${this._bucket}/${params.sourceKey}`,
|
|
640
|
+
Key: params.destinationKey,
|
|
641
|
+
});
|
|
642
|
+
await this.s3Client.send(command);
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* List all objects under a given prefix.
|
|
646
|
+
* Handles pagination for S3-compatible storage and Azure.
|
|
647
|
+
*/
|
|
648
|
+
async listObjects(params) {
|
|
649
|
+
await this._loadConfiguration();
|
|
650
|
+
if (!this._endpoint)
|
|
651
|
+
return [];
|
|
652
|
+
if (this._storageType === "azure")
|
|
653
|
+
return await this._listAzureObjects(params);
|
|
654
|
+
const results = [];
|
|
655
|
+
let continuationToken;
|
|
656
|
+
do {
|
|
657
|
+
const listResponse = await this.s3Client.send(new client_s3_1.ListObjectsV2Command({
|
|
658
|
+
Bucket: this._bucket,
|
|
659
|
+
Prefix: params.prefix,
|
|
660
|
+
ContinuationToken: continuationToken,
|
|
661
|
+
}));
|
|
662
|
+
if (listResponse.Contents) {
|
|
663
|
+
for (const obj of listResponse.Contents) {
|
|
664
|
+
if (obj.Key && obj.Size !== undefined) {
|
|
665
|
+
results.push({ key: obj.Key, size: obj.Size });
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
continuationToken = listResponse.NextContinuationToken;
|
|
670
|
+
} while (continuationToken);
|
|
671
|
+
return results;
|
|
672
|
+
}
|
|
673
|
+
async _listAzureObjects(params) {
|
|
674
|
+
const results = [];
|
|
675
|
+
const blobs = this.containerClient.listBlobsFlat({ prefix: params.prefix });
|
|
676
|
+
for await (const blob of blobs) {
|
|
677
|
+
results.push({
|
|
678
|
+
key: blob.name,
|
|
679
|
+
size: blob.properties.contentLength ?? 0,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
return results;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Download a file from S3/Azure and return its content as a string.
|
|
686
|
+
* Useful for reading JSON or HTML content stored in object storage.
|
|
687
|
+
*/
|
|
688
|
+
async downloadFileAsString(params) {
|
|
689
|
+
await this._loadConfiguration();
|
|
690
|
+
if (!this._endpoint)
|
|
691
|
+
return null;
|
|
692
|
+
if (this._storageType === "azure") {
|
|
693
|
+
return await this._downloadAzureFileAsString(params);
|
|
694
|
+
}
|
|
695
|
+
try {
|
|
696
|
+
const response = await this.s3Client.send(new client_s3_1.GetObjectCommand({ Bucket: this._bucket, Key: params.key }));
|
|
697
|
+
if (response.Body) {
|
|
698
|
+
return await response.Body.transformToString();
|
|
699
|
+
}
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
catch (error) {
|
|
703
|
+
console.error(`Failed to download file ${params.key}:`, error);
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
async _downloadAzureFileAsString(params) {
|
|
708
|
+
try {
|
|
709
|
+
const blobClient = this.containerClient.getBlobClient(params.key);
|
|
710
|
+
const downloadResponse = await blobClient.download();
|
|
711
|
+
if (downloadResponse.readableStreamBody) {
|
|
712
|
+
const chunks = [];
|
|
713
|
+
for await (const chunk of downloadResponse.readableStreamBody) {
|
|
714
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
715
|
+
}
|
|
716
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
catch (error) {
|
|
721
|
+
console.error(`Failed to download Azure file ${params.key}:`, error);
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Download a file from S3/Azure and return its content as a Buffer.
|
|
727
|
+
* Useful for reading binary files like attachments.
|
|
728
|
+
*/
|
|
729
|
+
async downloadFileAsBuffer(params) {
|
|
730
|
+
await this._loadConfiguration();
|
|
731
|
+
if (!this._endpoint)
|
|
732
|
+
return null;
|
|
733
|
+
if (this._storageType === "azure") {
|
|
734
|
+
return await this._downloadAzureFileAsBuffer(params);
|
|
735
|
+
}
|
|
736
|
+
try {
|
|
737
|
+
const response = await this.s3Client.send(new client_s3_1.GetObjectCommand({ Bucket: this._bucket, Key: params.key }));
|
|
738
|
+
if (response.Body) {
|
|
739
|
+
const byteArray = await response.Body.transformToByteArray();
|
|
740
|
+
return Buffer.from(byteArray);
|
|
741
|
+
}
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
catch (error) {
|
|
745
|
+
console.error(`Failed to download file as buffer ${params.key}:`, error);
|
|
746
|
+
return null;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
async _downloadAzureFileAsBuffer(params) {
|
|
750
|
+
try {
|
|
751
|
+
const blobClient = this.containerClient.getBlobClient(params.key);
|
|
752
|
+
const downloadResponse = await blobClient.download();
|
|
753
|
+
if (downloadResponse.readableStreamBody) {
|
|
754
|
+
const chunks = [];
|
|
755
|
+
for await (const chunk of downloadResponse.readableStreamBody) {
|
|
756
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
757
|
+
}
|
|
758
|
+
return Buffer.concat(chunks);
|
|
759
|
+
}
|
|
760
|
+
return null;
|
|
761
|
+
}
|
|
762
|
+
catch (error) {
|
|
763
|
+
console.error(`Failed to download Azure file as buffer ${params.key}:`, error);
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Upload a buffer with an exact key — NO extension appending.
|
|
769
|
+
* Unlike uploadFile (which adds .pdf, .zip, etc.), this method
|
|
770
|
+
* preserves the key exactly as provided.
|
|
771
|
+
*/
|
|
772
|
+
async uploadBufferWithKey(params) {
|
|
773
|
+
await this._loadConfiguration();
|
|
774
|
+
if (!this._endpoint)
|
|
775
|
+
return;
|
|
776
|
+
if (this._storageType === "azure") {
|
|
777
|
+
const blobClient = this.containerClient.getBlockBlobClient(params.key);
|
|
778
|
+
await blobClient.upload(params.buffer, params.buffer.length, {
|
|
779
|
+
blobHTTPHeaders: { blobContentType: params.contentType },
|
|
780
|
+
});
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
await this.s3Client.send(new client_s3_1.PutObjectCommand({
|
|
784
|
+
Bucket: this._bucket,
|
|
785
|
+
Key: params.key,
|
|
786
|
+
Body: params.buffer,
|
|
787
|
+
ContentType: params.contentType,
|
|
788
|
+
}));
|
|
789
|
+
}
|
|
523
790
|
};
|
|
524
791
|
exports.S3Service = S3Service;
|
|
525
792
|
exports.S3Service = S3Service = __decorate([
|