@smythos/sre 1.6.8 → 1.6.10
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/CHANGELOG +111 -111
- package/LICENSE +18 -18
- package/README.md +135 -135
- package/dist/bundle-analysis-lazy.html +4949 -0
- package/dist/bundle-analysis.html +4949 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/types/Components/Triggers/Gmail.trigger.d.ts +58 -0
- package/dist/types/Components/Triggers/GmailTrigger.class.d.ts +44 -0
- package/dist/types/Components/Triggers/Trigger.class.d.ts +21 -0
- package/dist/types/Components/Triggers/WhatsApp.trigger.d.ts +22 -0
- package/dist/types/helpers/AIPerformanceAnalyzer.helper.d.ts +45 -0
- package/dist/types/helpers/AIPerformanceCollector.helper.d.ts +111 -0
- package/dist/types/subsystems/IO/Storage.service/connectors/AzureBlobStorage.class.d.ts +211 -0
- package/dist/types/subsystems/IO/VectorDB.service/connectors/WeaviateVectorDB.class.d.ts +187 -0
- package/dist/types/subsystems/PerformanceManager/Performance.service/PerformanceConnector.d.ts +102 -0
- package/dist/types/subsystems/PerformanceManager/Performance.service/connectors/LocalPerformanceConnector.class.d.ts +100 -0
- package/dist/types/subsystems/PerformanceManager/Performance.service/index.d.ts +22 -0
- package/dist/types/subsystems/Security/Credentials/Credentials.class.d.ts +2 -0
- package/dist/types/subsystems/Security/Credentials/ManagedOAuth2Credentials.class.d.ts +18 -0
- package/dist/types/subsystems/Security/Credentials/OAuth2Credentials.class.d.ts +14 -0
- package/dist/types/types/Performance.types.d.ts +468 -0
- package/dist/types/utils/package-manager.utils.d.ts +26 -0
- package/package.json +1 -1
- package/src/Components/APICall/APICall.class.ts +161 -161
- package/src/Components/APICall/AccessTokenManager.ts +166 -166
- package/src/Components/APICall/ArrayBufferResponse.helper.ts +58 -58
- package/src/Components/APICall/OAuth.helper.ts +447 -447
- package/src/Components/APICall/mimeTypeCategories.ts +46 -46
- package/src/Components/APICall/parseData.ts +167 -167
- package/src/Components/APICall/parseHeaders.ts +41 -41
- package/src/Components/APICall/parseProxy.ts +68 -68
- package/src/Components/APICall/parseUrl.ts +91 -91
- package/src/Components/APIEndpoint.class.ts +234 -234
- package/src/Components/APIOutput.class.ts +58 -58
- package/src/Components/AgentPlugin.class.ts +102 -102
- package/src/Components/Async.class.ts +155 -155
- package/src/Components/Await.class.ts +90 -90
- package/src/Components/Classifier.class.ts +158 -158
- package/src/Components/Component.class.ts +147 -147
- package/src/Components/ComponentHost.class.ts +38 -38
- package/src/Components/DataSourceCleaner.class.ts +92 -92
- package/src/Components/DataSourceIndexer.class.ts +181 -181
- package/src/Components/DataSourceLookup.class.ts +161 -161
- package/src/Components/ECMASandbox.class.ts +72 -72
- package/src/Components/FEncDec.class.ts +29 -29
- package/src/Components/FHash.class.ts +33 -33
- package/src/Components/FSign.class.ts +80 -80
- package/src/Components/FSleep.class.ts +25 -25
- package/src/Components/FTimestamp.class.ts +66 -66
- package/src/Components/FileStore.class.ts +78 -78
- package/src/Components/ForEach.class.ts +97 -97
- package/src/Components/GPTPlugin.class.ts +70 -70
- package/src/Components/GenAILLM.class.ts +586 -586
- package/src/Components/HuggingFace.class.ts +313 -313
- package/src/Components/Image/imageSettings.config.ts +70 -70
- package/src/Components/ImageGenerator.class.ts +483 -483
- package/src/Components/JSONFilter.class.ts +54 -54
- package/src/Components/LLMAssistant.class.ts +213 -213
- package/src/Components/LogicAND.class.ts +28 -28
- package/src/Components/LogicAtLeast.class.ts +85 -85
- package/src/Components/LogicAtMost.class.ts +86 -86
- package/src/Components/LogicOR.class.ts +29 -29
- package/src/Components/LogicXOR.class.ts +34 -34
- package/src/Components/MCPClient.class.ts +137 -137
- package/src/Components/MemoryDeleteKeyVal.class.ts +70 -70
- package/src/Components/MemoryReadKeyVal.class.ts +67 -67
- package/src/Components/MemoryWriteKeyVal.class.ts +62 -62
- package/src/Components/MemoryWriteObject.class.ts +97 -97
- package/src/Components/MultimodalLLM.class.ts +128 -128
- package/src/Components/OpenAPI.class.ts +72 -72
- package/src/Components/PromptGenerator.class.ts +122 -122
- package/src/Components/ScrapflyWebScrape.class.ts +183 -183
- package/src/Components/ServerlessCode.class.ts +123 -123
- package/src/Components/TavilyWebSearch.class.ts +103 -103
- package/src/Components/VisionLLM.class.ts +104 -104
- package/src/Components/ZapierAction.class.ts +127 -127
- package/src/Components/index.ts +97 -97
- package/src/Core/AgentProcess.helper.ts +240 -240
- package/src/Core/Connector.class.ts +123 -123
- package/src/Core/ConnectorsService.ts +197 -197
- package/src/Core/DummyConnector.ts +49 -49
- package/src/Core/HookService.ts +105 -105
- package/src/Core/SmythRuntime.class.ts +241 -241
- package/src/Core/SystemEvents.ts +16 -16
- package/src/Core/boot.ts +56 -56
- package/src/config.ts +15 -15
- package/src/constants.ts +126 -126
- package/src/data/hugging-face.params.json +579 -579
- package/src/helpers/AWSLambdaCode.helper.ts +624 -624
- package/src/helpers/BinaryInput.helper.ts +331 -331
- package/src/helpers/Conversation.helper.ts +1157 -1157
- package/src/helpers/ECMASandbox.helper.ts +64 -64
- package/src/helpers/JsonContent.helper.ts +97 -97
- package/src/helpers/LocalCache.helper.ts +97 -97
- package/src/helpers/Log.helper.ts +274 -274
- package/src/helpers/OpenApiParser.helper.ts +150 -150
- package/src/helpers/S3Cache.helper.ts +147 -147
- package/src/helpers/SmythURI.helper.ts +5 -5
- package/src/helpers/Sysconfig.helper.ts +95 -95
- package/src/helpers/TemplateString.helper.ts +243 -243
- package/src/helpers/TypeChecker.helper.ts +329 -329
- package/src/index.ts +3 -3
- package/src/index.ts.bak +3 -3
- package/src/subsystems/AgentManager/Agent.class.ts +1114 -1114
- package/src/subsystems/AgentManager/Agent.helper.ts +3 -3
- package/src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts +230 -230
- package/src/subsystems/AgentManager/AgentData.service/connectors/CLIAgentDataConnector.class.ts +66 -66
- package/src/subsystems/AgentManager/AgentData.service/connectors/LocalAgentDataConnector.class.ts +145 -145
- package/src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts +39 -39
- package/src/subsystems/AgentManager/AgentData.service/index.ts +18 -18
- package/src/subsystems/AgentManager/AgentLogger.class.ts +301 -301
- package/src/subsystems/AgentManager/AgentRequest.class.ts +51 -51
- package/src/subsystems/AgentManager/AgentRuntime.class.ts +557 -557
- package/src/subsystems/AgentManager/AgentSSE.class.ts +101 -101
- package/src/subsystems/AgentManager/AgentSettings.class.ts +52 -52
- package/src/subsystems/AgentManager/Component.service/ComponentConnector.ts +32 -32
- package/src/subsystems/AgentManager/Component.service/connectors/LocalComponentConnector.class.ts +60 -60
- package/src/subsystems/AgentManager/Component.service/index.ts +11 -11
- package/src/subsystems/AgentManager/EmbodimentSettings.class.ts +47 -47
- package/src/subsystems/AgentManager/ForkedAgent.class.ts +154 -154
- package/src/subsystems/AgentManager/OSResourceMonitor.ts +77 -77
- package/src/subsystems/ComputeManager/Code.service/CodeConnector.ts +98 -98
- package/src/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.ts +171 -171
- package/src/subsystems/ComputeManager/Code.service/connectors/ECMASandbox.class.ts +131 -131
- package/src/subsystems/ComputeManager/Code.service/index.ts +13 -13
- package/src/subsystems/IO/CLI.service/CLIConnector.ts +47 -47
- package/src/subsystems/IO/CLI.service/index.ts +9 -9
- package/src/subsystems/IO/Log.service/LogConnector.ts +32 -32
- package/src/subsystems/IO/Log.service/connectors/ConsoleLog.class.ts +28 -28
- package/src/subsystems/IO/Log.service/index.ts +13 -13
- package/src/subsystems/IO/NKV.service/NKVConnector.ts +43 -43
- package/src/subsystems/IO/NKV.service/connectors/NKVLocalStorage.class.ts +234 -234
- package/src/subsystems/IO/NKV.service/connectors/NKVRAM.class.ts +204 -204
- package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +182 -182
- package/src/subsystems/IO/NKV.service/index.ts +14 -14
- package/src/subsystems/IO/Router.service/RouterConnector.ts +21 -21
- package/src/subsystems/IO/Router.service/connectors/ExpressRouter.class.ts +48 -48
- package/src/subsystems/IO/Router.service/connectors/NullRouter.class.ts +40 -40
- package/src/subsystems/IO/Router.service/index.ts +11 -11
- package/src/subsystems/IO/Storage.service/SmythFS.class.ts +488 -488
- package/src/subsystems/IO/Storage.service/StorageConnector.ts +66 -66
- package/src/subsystems/IO/Storage.service/connectors/LocalStorage.class.ts +327 -327
- package/src/subsystems/IO/Storage.service/connectors/S3Storage.class.ts +482 -482
- package/src/subsystems/IO/Storage.service/index.ts +13 -13
- package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +108 -108
- package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +465 -465
- package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +387 -387
- package/src/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.ts +408 -408
- package/src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts +107 -107
- package/src/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.ts +118 -118
- package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +109 -109
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +26 -26
- package/src/subsystems/IO/VectorDB.service/index.ts +14 -14
- package/src/subsystems/LLMManager/LLM.helper.ts +251 -251
- package/src/subsystems/LLMManager/LLM.inference.ts +345 -345
- package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +492 -492
- package/src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts +171 -171
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +666 -666
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +407 -407
- package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +92 -92
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +983 -983
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +319 -319
- package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +361 -361
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +257 -257
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +430 -430
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.ts +503 -503
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +524 -524
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterface.ts +100 -100
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterfaceFactory.ts +81 -81
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +1145 -1145
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/constants.ts +13 -13
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/index.ts +4 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/utils.ts +11 -11
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/types.ts +32 -32
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +478 -478
- package/src/subsystems/LLMManager/LLM.service/index.ts +47 -47
- package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +303 -303
- package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +280 -271
- package/src/subsystems/LLMManager/ModelsProvider.service/index.ts +11 -11
- package/src/subsystems/LLMManager/custom-models.ts +854 -854
- package/src/subsystems/LLMManager/models.ts +2540 -2540
- package/src/subsystems/LLMManager/paramMappings.ts +69 -69
- package/src/subsystems/MemoryManager/Cache.service/CacheConnector.ts +86 -86
- package/src/subsystems/MemoryManager/Cache.service/connectors/LocalStorageCache.class.ts +297 -297
- package/src/subsystems/MemoryManager/Cache.service/connectors/RAMCache.class.ts +214 -214
- package/src/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.ts +252 -252
- package/src/subsystems/MemoryManager/Cache.service/connectors/S3Cache.class.ts +373 -373
- package/src/subsystems/MemoryManager/Cache.service/index.ts +15 -15
- package/src/subsystems/MemoryManager/LLMCache.ts +72 -72
- package/src/subsystems/MemoryManager/LLMContext.ts +124 -124
- package/src/subsystems/MemoryManager/LLMMemory.service/LLMMemoryConnector.ts +26 -26
- package/src/subsystems/MemoryManager/RuntimeContext.ts +277 -277
- package/src/subsystems/Security/AccessControl/ACL.class.ts +208 -208
- package/src/subsystems/Security/AccessControl/AccessCandidate.class.ts +82 -82
- package/src/subsystems/Security/AccessControl/AccessRequest.class.ts +52 -52
- package/src/subsystems/Security/Account.service/AccountConnector.ts +44 -44
- package/src/subsystems/Security/Account.service/connectors/DummyAccount.class.ts +130 -130
- package/src/subsystems/Security/Account.service/connectors/JSONFileAccount.class.ts +170 -170
- package/src/subsystems/Security/Account.service/connectors/MySQLAccount.class.ts +76 -76
- package/src/subsystems/Security/Account.service/index.ts +14 -14
- package/src/subsystems/Security/Credentials.helper.ts +62 -62
- package/src/subsystems/Security/ManagedVault.service/ManagedVaultConnector.ts +38 -38
- package/src/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.ts +53 -53
- package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +154 -154
- package/src/subsystems/Security/ManagedVault.service/index.ts +12 -12
- package/src/subsystems/Security/SecureConnector.class.ts +110 -110
- package/src/subsystems/Security/Vault.service/Vault.helper.ts +30 -30
- package/src/subsystems/Security/Vault.service/VaultConnector.ts +29 -29
- package/src/subsystems/Security/Vault.service/connectors/HashicorpVault.class.ts +46 -46
- package/src/subsystems/Security/Vault.service/connectors/JSONFileVault.class.ts +221 -221
- package/src/subsystems/Security/Vault.service/connectors/NullVault.class.ts +54 -54
- package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +140 -140
- package/src/subsystems/Security/Vault.service/index.ts +12 -12
- package/src/types/ACL.types.ts +104 -104
- package/src/types/AWS.types.ts +10 -10
- package/src/types/Agent.types.ts +61 -61
- package/src/types/AgentLogger.types.ts +17 -17
- package/src/types/Cache.types.ts +1 -1
- package/src/types/Common.types.ts +2 -2
- package/src/types/LLM.types.ts +520 -520
- package/src/types/Redis.types.ts +8 -8
- package/src/types/SRE.types.ts +64 -64
- package/src/types/Security.types.ts +14 -14
- package/src/types/Storage.types.ts +5 -5
- package/src/types/VectorDB.types.ts +86 -86
- package/src/utils/base64.utils.ts +275 -275
- package/src/utils/cli.utils.ts +68 -68
- package/src/utils/data.utils.ts +322 -322
- package/src/utils/date-time.utils.ts +22 -22
- package/src/utils/general.utils.ts +238 -238
- package/src/utils/index.ts +12 -12
- package/src/utils/lazy-client.ts +261 -261
- package/src/utils/numbers.utils.ts +13 -13
- package/src/utils/oauth.utils.ts +35 -35
- package/src/utils/string.utils.ts +414 -414
- package/src/utils/url.utils.ts +19 -19
- package/src/utils/validation.utils.ts +74 -74
- package/dist/types/subsystems/LLMManager/ModelsProvider.service/connectors/SmythModelsProvider.class.d.ts +0 -39
package/src/utils/data.utils.ts
CHANGED
|
@@ -1,322 +1,322 @@
|
|
|
1
|
-
import { Readable } from 'stream';
|
|
2
|
-
import axios from 'axios';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
|
|
5
|
-
import { identifyMimeTypeFromBase64DataUrl, isBase64FileUrl, isBase64, identifyMimetypeFromBase64, isBase64DataUrl } from './base64.utils';
|
|
6
|
-
import { isBinaryFileSync } from 'isbinaryfile';
|
|
7
|
-
import { fileTypeFromBuffer } from 'file-type';
|
|
8
|
-
import { BinaryInput } from '@sre/helpers/BinaryInput.helper';
|
|
9
|
-
import { identifyMimetypeFromString } from './string.utils';
|
|
10
|
-
import { IAccessCandidate } from '@sre/types/ACL.types';
|
|
11
|
-
|
|
12
|
-
// Helper function to convert stream to buffer
|
|
13
|
-
export async function streamToBuffer(stream: Readable): Promise<Buffer> {
|
|
14
|
-
const chunks: Buffer[] = [];
|
|
15
|
-
for await (const chunk of stream) {
|
|
16
|
-
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
17
|
-
}
|
|
18
|
-
return Buffer.concat(chunks);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
22
|
-
// == Helpers from Legacy Smyth implementation ==============================================
|
|
23
|
-
// FIXME : below functions should probably be converted to a validator
|
|
24
|
-
|
|
25
|
-
//export declare function isBinaryFile(file: string | Buffer, size?: number): Promise<boolean>;
|
|
26
|
-
//export declare function isBinaryFileSync(file: string | Buffer, size?: number): boolean;
|
|
27
|
-
const binaryMimeTypes = ['image/', 'audio/', 'video/', 'application/pdf', 'application/zip', 'application/octet-stream'];
|
|
28
|
-
|
|
29
|
-
export function dataToBuffer(data: any): Buffer | null {
|
|
30
|
-
let bufferData;
|
|
31
|
-
switch (true) {
|
|
32
|
-
case data instanceof ArrayBuffer:
|
|
33
|
-
bufferData = Buffer.from(new Uint8Array(data));
|
|
34
|
-
break;
|
|
35
|
-
case ArrayBuffer.isView(data) && !(data instanceof DataView):
|
|
36
|
-
bufferData = Buffer.from(new Uint8Array(data.buffer));
|
|
37
|
-
break;
|
|
38
|
-
case data instanceof DataView:
|
|
39
|
-
bufferData = Buffer.from(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
40
|
-
break;
|
|
41
|
-
case Buffer.isBuffer(data):
|
|
42
|
-
bufferData = data;
|
|
43
|
-
break;
|
|
44
|
-
case typeof data === 'string':
|
|
45
|
-
bufferData = Buffer.from(data, 'utf-8');
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return bufferData;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const getSizeFromBinary = (data: any) => {
|
|
55
|
-
const buffer = dataToBuffer(data);
|
|
56
|
-
if (!buffer) return 0;
|
|
57
|
-
return buffer.byteLength;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Calculates the size in bytes of a base64-encoded string after decoding
|
|
62
|
-
*
|
|
63
|
-
* @param base64String - The base64 string to calculate the size for. Can be a raw base64 string or a data URL.
|
|
64
|
-
* @returns The size in bytes of the decoded data
|
|
65
|
-
*/
|
|
66
|
-
function getBase64FileSize(base64String: string): number {
|
|
67
|
-
// Remove data URL prefix if present
|
|
68
|
-
const base64Data = base64String.includes(';base64,') ? base64String.split(';base64,')[1] : base64String;
|
|
69
|
-
|
|
70
|
-
// Formula: (n * 3) / 4 - padding
|
|
71
|
-
const padding = base64Data.endsWith('==') ? 2 : base64Data.endsWith('=') ? 1 : 0;
|
|
72
|
-
return Math.floor((base64Data.length * 3) / 4) - padding;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export const isPlainObject = (data: any): boolean => {
|
|
76
|
-
return (
|
|
77
|
-
typeof data === 'object' &&
|
|
78
|
-
data !== null &&
|
|
79
|
-
!Array.isArray(data) &&
|
|
80
|
-
Object.prototype.toString.call(data) === '[object Object]' &&
|
|
81
|
-
data.constructor === Object
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// isBuffer checks if the provided data is a Buffer object in Node.js.
|
|
86
|
-
export const isBuffer = (data: any): boolean => {
|
|
87
|
-
try {
|
|
88
|
-
return Buffer.isBuffer(data);
|
|
89
|
-
} catch {
|
|
90
|
-
// Buffer.isBuffer throws error when non-array Object is passed
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// isBinaryMimeType checks if the provided mimetype indicates binary data.
|
|
96
|
-
export const isBinaryMimeType = (mimetype): boolean => {
|
|
97
|
-
if (mimetype) {
|
|
98
|
-
return binaryMimeTypes.some((type) => mimetype.startsWith(type));
|
|
99
|
-
}
|
|
100
|
-
return false;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// isBinaryData checks if the provided data is binary.
|
|
104
|
-
// If the data is a Buffer, ArrayBuffer, TypedArray, or DataView, it checks if it contains binary data.
|
|
105
|
-
export const isBinaryData = (data): boolean => {
|
|
106
|
-
// To prevent returning true when we have emojis in the string like "Hello 😀"
|
|
107
|
-
if (typeof data === 'string') return false;
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
const buffer = dataToBuffer(data);
|
|
111
|
-
if (!buffer) return false;
|
|
112
|
-
return isBinaryFileSync(buffer, buffer.byteLength);
|
|
113
|
-
} catch (error) {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// TODO: Need to check if this is intentional, I think we're checking for http/https urls only
|
|
119
|
-
export function isUrl(str: string): boolean {
|
|
120
|
-
if (typeof str !== 'string') return false;
|
|
121
|
-
// This regex checks for protocol, hostname, domain, port (optional), path (optional), and query string (optional)
|
|
122
|
-
//const regex = /^(https?:\/\/)([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|
|
123
|
-
const regex = /^([a-zA-Z0-9]+:\/\/)([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|
|
124
|
-
|
|
125
|
-
return regex.test(str);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function isFile(str: string): boolean {
|
|
129
|
-
// Check if string exists and length is within limit
|
|
130
|
-
if (!str || str.length >= 1000) {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Validate path format for both Windows and Unix systems
|
|
135
|
-
if (!isValidPathFormat(str)) {
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Check if file exists using fs.stat
|
|
140
|
-
try {
|
|
141
|
-
const stats = fs.statSync(str);
|
|
142
|
-
return stats.isFile();
|
|
143
|
-
} catch (error) {
|
|
144
|
-
// File doesn't exist or permission denied
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Validates if a string is in a valid file path format for both Windows and Unix systems
|
|
151
|
-
* Supports both absolute and relative paths
|
|
152
|
-
*/
|
|
153
|
-
function isValidPathFormat(path: string): boolean {
|
|
154
|
-
// Check for invalid characters that are not allowed in file paths
|
|
155
|
-
const invalidChars = /[\0<>"|?*]/;
|
|
156
|
-
if (invalidChars.test(path)) {
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Windows path patterns
|
|
161
|
-
const windowsAbsolute = /^[a-zA-Z]:[\\\/]/; // C:\ or C:/
|
|
162
|
-
const windowsUNC = /^\\\\[^\\]+\\[^\\]+/; // \\server\share
|
|
163
|
-
const windowsRelative = /^\.{1,2}[\\\/]/; // .\ or ..\ or ./ or ../
|
|
164
|
-
|
|
165
|
-
// Unix path patterns
|
|
166
|
-
const unixAbsolute = /^\//; // /path/to/file
|
|
167
|
-
const unixHome = /^~[\/]/; // ~/path/to/file
|
|
168
|
-
const unixRelative = /^\.{1,2}\//; // ./ or ../
|
|
169
|
-
|
|
170
|
-
// Relative paths without leading ./ or .\
|
|
171
|
-
const genericRelative = /^[^\\\/]/; // path/to/file or path\to\file
|
|
172
|
-
|
|
173
|
-
// Check if path matches any valid pattern
|
|
174
|
-
return (
|
|
175
|
-
windowsAbsolute.test(path) ||
|
|
176
|
-
windowsUNC.test(path) ||
|
|
177
|
-
windowsRelative.test(path) ||
|
|
178
|
-
unixAbsolute.test(path) ||
|
|
179
|
-
unixHome.test(path) ||
|
|
180
|
-
unixRelative.test(path) ||
|
|
181
|
-
genericRelative.test(path)
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export function isSmythFsUrl(str: string): boolean {
|
|
186
|
-
if (typeof str !== 'string') return false;
|
|
187
|
-
const regex = /^smythfs:\/\/([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|
|
188
|
-
return regex.test(str);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export const isSmythFileObject = (data: any): boolean => {
|
|
192
|
-
return !!(typeof data === 'object' && data !== null && data?.url && isUrl(data?.url) && 'size' in data && 'mimetype' in data);
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
export const isBufferObject = (data: Record<string, any>): boolean => {
|
|
196
|
-
if (!data) return false;
|
|
197
|
-
|
|
198
|
-
return typeof data === 'object' && data !== null && data?.buffer && isBuffer(data.buffer) && 'size' in data && 'mimetype' in data;
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export const isBase64Object = (data: Record<string, any>): boolean => {
|
|
202
|
-
if (!data) return false;
|
|
203
|
-
|
|
204
|
-
return typeof data === 'object' && data !== null && data?.base64 && isBase64(data.base64) && 'size' in data && 'mimetype' in data;
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
export async function getMimeType(data: any): Promise<string> {
|
|
208
|
-
const mimeTypeGetters = {
|
|
209
|
-
blob: () => data.type,
|
|
210
|
-
buffer: async () => {
|
|
211
|
-
try {
|
|
212
|
-
// TODO: debug why this is not returning a file type for images when used through BinaryInput.helper.ts
|
|
213
|
-
const fileType = await fileTypeFromBuffer(data);
|
|
214
|
-
return fileType?.mime ?? '';
|
|
215
|
-
} catch {
|
|
216
|
-
console.warn('Failed to get mime type from buffer');
|
|
217
|
-
return '';
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
url: async () => {
|
|
221
|
-
try {
|
|
222
|
-
const response = await axios.get(data); // head() method does not work for all URLs
|
|
223
|
-
const contentType = response.headers['content-type'];
|
|
224
|
-
return contentType;
|
|
225
|
-
} catch {
|
|
226
|
-
console.warn('Failed to get mime type from URL');
|
|
227
|
-
return '';
|
|
228
|
-
}
|
|
229
|
-
},
|
|
230
|
-
smythFile: () => data.mimetype,
|
|
231
|
-
base64DataUrl: () => identifyMimeTypeFromBase64DataUrl(data),
|
|
232
|
-
base64: () => identifyMimetypeFromBase64(data),
|
|
233
|
-
string: () => identifyMimetypeFromString(data),
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
const typeChecks = {
|
|
237
|
-
blob: data instanceof Blob,
|
|
238
|
-
buffer: isBuffer(data),
|
|
239
|
-
url: isUrl(data),
|
|
240
|
-
smythFile: isSmythFileObject(data),
|
|
241
|
-
base64DataUrl: isBase64FileUrl(data),
|
|
242
|
-
base64: isBase64(data),
|
|
243
|
-
string: typeof data === 'string',
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const [matchedType = ''] = Object.entries(typeChecks).find(([, value]) => value) || [];
|
|
247
|
-
if (!matchedType) return '';
|
|
248
|
-
|
|
249
|
-
return await mimeTypeGetters?.[matchedType]?.();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Mask data like Buffer, FormData, etc. in debug output
|
|
253
|
-
// TODO [Forhad]: Need to get the size of FormData
|
|
254
|
-
export async function formatDataForDebug(data: any, candidate: IAccessCandidate) {
|
|
255
|
-
let dataForDebug;
|
|
256
|
-
|
|
257
|
-
if (!data) {
|
|
258
|
-
return data;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
try {
|
|
262
|
-
if (data.constructor?.name === 'BinaryInput') {
|
|
263
|
-
const jsonData = await data.getJsonData(candidate);
|
|
264
|
-
dataForDebug = `[BinaryInput size=${jsonData?.size}]`;
|
|
265
|
-
} else if (isBuffer(data)) {
|
|
266
|
-
dataForDebug = `[Buffer size=${data.byteLength}]`;
|
|
267
|
-
} else if (data.constructor?.name === 'FormData') {
|
|
268
|
-
dataForDebug = `[FormData]`;
|
|
269
|
-
} else if (isBase64(data) || isBase64DataUrl(data)) {
|
|
270
|
-
dataForDebug = `[Base64 size=${getBase64FileSize(data)}]`;
|
|
271
|
-
} else {
|
|
272
|
-
dataForDebug = data;
|
|
273
|
-
}
|
|
274
|
-
} catch (error) {
|
|
275
|
-
// Fallback to a safe representation if any error occurs
|
|
276
|
-
dataForDebug = '[Binary]';
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return dataForDebug;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// TODO: Maybe we need move this function to any helper file, as it depends on BinaryInput class
|
|
283
|
-
export async function normalizeImageInput(inputImage: string | BinaryInput): Promise<string> {
|
|
284
|
-
if (!inputImage) {
|
|
285
|
-
return '';
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Handle string inputs
|
|
289
|
-
if (typeof inputImage === 'string') {
|
|
290
|
-
if (isBase64(inputImage)) {
|
|
291
|
-
// Convert raw base64 to data URL with proper MIME type
|
|
292
|
-
const mimeType = (await getMimeType(inputImage)) || 'image/png';
|
|
293
|
-
return `data:${mimeType};base64,${inputImage}`;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (isBase64DataUrl(inputImage)) {
|
|
297
|
-
return inputImage; // Already in correct format
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (isUrl(inputImage)) {
|
|
301
|
-
return inputImage; // Valid URL, return as-is
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
throw new Error('Invalid string input: must be base64, data URL, or HTTP(S) URL');
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Handle BinaryInput
|
|
308
|
-
// * There is a bug (server crash) when we check like this: inputImage instanceof BinaryInput
|
|
309
|
-
// TODO [Forhad]: Need find out the root cause and fix it
|
|
310
|
-
if (inputImage.constructor?.name === 'BinaryInput') {
|
|
311
|
-
try {
|
|
312
|
-
const buffer = await inputImage.getBuffer();
|
|
313
|
-
const mimeType = (await getMimeType(buffer)) || 'image/png';
|
|
314
|
-
const base64Data = buffer.toString('base64');
|
|
315
|
-
return `data:${mimeType};base64,${base64Data}`;
|
|
316
|
-
} catch (error) {
|
|
317
|
-
throw new Error(`Failed to process BinaryInput: ${error.message}`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
throw new Error('Unsupported input type');
|
|
322
|
-
}
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
|
|
5
|
+
import { identifyMimeTypeFromBase64DataUrl, isBase64FileUrl, isBase64, identifyMimetypeFromBase64, isBase64DataUrl } from './base64.utils';
|
|
6
|
+
import { isBinaryFileSync } from 'isbinaryfile';
|
|
7
|
+
import { fileTypeFromBuffer } from 'file-type';
|
|
8
|
+
import { BinaryInput } from '@sre/helpers/BinaryInput.helper';
|
|
9
|
+
import { identifyMimetypeFromString } from './string.utils';
|
|
10
|
+
import { IAccessCandidate } from '@sre/types/ACL.types';
|
|
11
|
+
|
|
12
|
+
// Helper function to convert stream to buffer
|
|
13
|
+
export async function streamToBuffer(stream: Readable): Promise<Buffer> {
|
|
14
|
+
const chunks: Buffer[] = [];
|
|
15
|
+
for await (const chunk of stream) {
|
|
16
|
+
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
17
|
+
}
|
|
18
|
+
return Buffer.concat(chunks);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
22
|
+
// == Helpers from Legacy Smyth implementation ==============================================
|
|
23
|
+
// FIXME : below functions should probably be converted to a validator
|
|
24
|
+
|
|
25
|
+
//export declare function isBinaryFile(file: string | Buffer, size?: number): Promise<boolean>;
|
|
26
|
+
//export declare function isBinaryFileSync(file: string | Buffer, size?: number): boolean;
|
|
27
|
+
const binaryMimeTypes = ['image/', 'audio/', 'video/', 'application/pdf', 'application/zip', 'application/octet-stream'];
|
|
28
|
+
|
|
29
|
+
export function dataToBuffer(data: any): Buffer | null {
|
|
30
|
+
let bufferData;
|
|
31
|
+
switch (true) {
|
|
32
|
+
case data instanceof ArrayBuffer:
|
|
33
|
+
bufferData = Buffer.from(new Uint8Array(data));
|
|
34
|
+
break;
|
|
35
|
+
case ArrayBuffer.isView(data) && !(data instanceof DataView):
|
|
36
|
+
bufferData = Buffer.from(new Uint8Array(data.buffer));
|
|
37
|
+
break;
|
|
38
|
+
case data instanceof DataView:
|
|
39
|
+
bufferData = Buffer.from(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
40
|
+
break;
|
|
41
|
+
case Buffer.isBuffer(data):
|
|
42
|
+
bufferData = data;
|
|
43
|
+
break;
|
|
44
|
+
case typeof data === 'string':
|
|
45
|
+
bufferData = Buffer.from(data, 'utf-8');
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return bufferData;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const getSizeFromBinary = (data: any) => {
|
|
55
|
+
const buffer = dataToBuffer(data);
|
|
56
|
+
if (!buffer) return 0;
|
|
57
|
+
return buffer.byteLength;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Calculates the size in bytes of a base64-encoded string after decoding
|
|
62
|
+
*
|
|
63
|
+
* @param base64String - The base64 string to calculate the size for. Can be a raw base64 string or a data URL.
|
|
64
|
+
* @returns The size in bytes of the decoded data
|
|
65
|
+
*/
|
|
66
|
+
function getBase64FileSize(base64String: string): number {
|
|
67
|
+
// Remove data URL prefix if present
|
|
68
|
+
const base64Data = base64String.includes(';base64,') ? base64String.split(';base64,')[1] : base64String;
|
|
69
|
+
|
|
70
|
+
// Formula: (n * 3) / 4 - padding
|
|
71
|
+
const padding = base64Data.endsWith('==') ? 2 : base64Data.endsWith('=') ? 1 : 0;
|
|
72
|
+
return Math.floor((base64Data.length * 3) / 4) - padding;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const isPlainObject = (data: any): boolean => {
|
|
76
|
+
return (
|
|
77
|
+
typeof data === 'object' &&
|
|
78
|
+
data !== null &&
|
|
79
|
+
!Array.isArray(data) &&
|
|
80
|
+
Object.prototype.toString.call(data) === '[object Object]' &&
|
|
81
|
+
data.constructor === Object
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// isBuffer checks if the provided data is a Buffer object in Node.js.
|
|
86
|
+
export const isBuffer = (data: any): boolean => {
|
|
87
|
+
try {
|
|
88
|
+
return Buffer.isBuffer(data);
|
|
89
|
+
} catch {
|
|
90
|
+
// Buffer.isBuffer throws error when non-array Object is passed
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// isBinaryMimeType checks if the provided mimetype indicates binary data.
|
|
96
|
+
export const isBinaryMimeType = (mimetype): boolean => {
|
|
97
|
+
if (mimetype) {
|
|
98
|
+
return binaryMimeTypes.some((type) => mimetype.startsWith(type));
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// isBinaryData checks if the provided data is binary.
|
|
104
|
+
// If the data is a Buffer, ArrayBuffer, TypedArray, or DataView, it checks if it contains binary data.
|
|
105
|
+
export const isBinaryData = (data): boolean => {
|
|
106
|
+
// To prevent returning true when we have emojis in the string like "Hello 😀"
|
|
107
|
+
if (typeof data === 'string') return false;
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const buffer = dataToBuffer(data);
|
|
111
|
+
if (!buffer) return false;
|
|
112
|
+
return isBinaryFileSync(buffer, buffer.byteLength);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// TODO: Need to check if this is intentional, I think we're checking for http/https urls only
|
|
119
|
+
export function isUrl(str: string): boolean {
|
|
120
|
+
if (typeof str !== 'string') return false;
|
|
121
|
+
// This regex checks for protocol, hostname, domain, port (optional), path (optional), and query string (optional)
|
|
122
|
+
//const regex = /^(https?:\/\/)([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|
|
123
|
+
const regex = /^([a-zA-Z0-9]+:\/\/)([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|
|
124
|
+
|
|
125
|
+
return regex.test(str);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function isFile(str: string): boolean {
|
|
129
|
+
// Check if string exists and length is within limit
|
|
130
|
+
if (!str || str.length >= 1000) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Validate path format for both Windows and Unix systems
|
|
135
|
+
if (!isValidPathFormat(str)) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check if file exists using fs.stat
|
|
140
|
+
try {
|
|
141
|
+
const stats = fs.statSync(str);
|
|
142
|
+
return stats.isFile();
|
|
143
|
+
} catch (error) {
|
|
144
|
+
// File doesn't exist or permission denied
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Validates if a string is in a valid file path format for both Windows and Unix systems
|
|
151
|
+
* Supports both absolute and relative paths
|
|
152
|
+
*/
|
|
153
|
+
function isValidPathFormat(path: string): boolean {
|
|
154
|
+
// Check for invalid characters that are not allowed in file paths
|
|
155
|
+
const invalidChars = /[\0<>"|?*]/;
|
|
156
|
+
if (invalidChars.test(path)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Windows path patterns
|
|
161
|
+
const windowsAbsolute = /^[a-zA-Z]:[\\\/]/; // C:\ or C:/
|
|
162
|
+
const windowsUNC = /^\\\\[^\\]+\\[^\\]+/; // \\server\share
|
|
163
|
+
const windowsRelative = /^\.{1,2}[\\\/]/; // .\ or ..\ or ./ or ../
|
|
164
|
+
|
|
165
|
+
// Unix path patterns
|
|
166
|
+
const unixAbsolute = /^\//; // /path/to/file
|
|
167
|
+
const unixHome = /^~[\/]/; // ~/path/to/file
|
|
168
|
+
const unixRelative = /^\.{1,2}\//; // ./ or ../
|
|
169
|
+
|
|
170
|
+
// Relative paths without leading ./ or .\
|
|
171
|
+
const genericRelative = /^[^\\\/]/; // path/to/file or path\to\file
|
|
172
|
+
|
|
173
|
+
// Check if path matches any valid pattern
|
|
174
|
+
return (
|
|
175
|
+
windowsAbsolute.test(path) ||
|
|
176
|
+
windowsUNC.test(path) ||
|
|
177
|
+
windowsRelative.test(path) ||
|
|
178
|
+
unixAbsolute.test(path) ||
|
|
179
|
+
unixHome.test(path) ||
|
|
180
|
+
unixRelative.test(path) ||
|
|
181
|
+
genericRelative.test(path)
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function isSmythFsUrl(str: string): boolean {
|
|
186
|
+
if (typeof str !== 'string') return false;
|
|
187
|
+
const regex = /^smythfs:\/\/([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|
|
188
|
+
return regex.test(str);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const isSmythFileObject = (data: any): boolean => {
|
|
192
|
+
return !!(typeof data === 'object' && data !== null && data?.url && isUrl(data?.url) && 'size' in data && 'mimetype' in data);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export const isBufferObject = (data: Record<string, any>): boolean => {
|
|
196
|
+
if (!data) return false;
|
|
197
|
+
|
|
198
|
+
return typeof data === 'object' && data !== null && data?.buffer && isBuffer(data.buffer) && 'size' in data && 'mimetype' in data;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const isBase64Object = (data: Record<string, any>): boolean => {
|
|
202
|
+
if (!data) return false;
|
|
203
|
+
|
|
204
|
+
return typeof data === 'object' && data !== null && data?.base64 && isBase64(data.base64) && 'size' in data && 'mimetype' in data;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export async function getMimeType(data: any): Promise<string> {
|
|
208
|
+
const mimeTypeGetters = {
|
|
209
|
+
blob: () => data.type,
|
|
210
|
+
buffer: async () => {
|
|
211
|
+
try {
|
|
212
|
+
// TODO: debug why this is not returning a file type for images when used through BinaryInput.helper.ts
|
|
213
|
+
const fileType = await fileTypeFromBuffer(data);
|
|
214
|
+
return fileType?.mime ?? '';
|
|
215
|
+
} catch {
|
|
216
|
+
console.warn('Failed to get mime type from buffer');
|
|
217
|
+
return '';
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
url: async () => {
|
|
221
|
+
try {
|
|
222
|
+
const response = await axios.get(data); // head() method does not work for all URLs
|
|
223
|
+
const contentType = response.headers['content-type'];
|
|
224
|
+
return contentType;
|
|
225
|
+
} catch {
|
|
226
|
+
console.warn('Failed to get mime type from URL');
|
|
227
|
+
return '';
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
smythFile: () => data.mimetype,
|
|
231
|
+
base64DataUrl: () => identifyMimeTypeFromBase64DataUrl(data),
|
|
232
|
+
base64: () => identifyMimetypeFromBase64(data),
|
|
233
|
+
string: () => identifyMimetypeFromString(data),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const typeChecks = {
|
|
237
|
+
blob: data instanceof Blob,
|
|
238
|
+
buffer: isBuffer(data),
|
|
239
|
+
url: isUrl(data),
|
|
240
|
+
smythFile: isSmythFileObject(data),
|
|
241
|
+
base64DataUrl: isBase64FileUrl(data),
|
|
242
|
+
base64: isBase64(data),
|
|
243
|
+
string: typeof data === 'string',
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const [matchedType = ''] = Object.entries(typeChecks).find(([, value]) => value) || [];
|
|
247
|
+
if (!matchedType) return '';
|
|
248
|
+
|
|
249
|
+
return await mimeTypeGetters?.[matchedType]?.();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Mask data like Buffer, FormData, etc. in debug output
|
|
253
|
+
// TODO [Forhad]: Need to get the size of FormData
|
|
254
|
+
export async function formatDataForDebug(data: any, candidate: IAccessCandidate) {
|
|
255
|
+
let dataForDebug;
|
|
256
|
+
|
|
257
|
+
if (!data) {
|
|
258
|
+
return data;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
if (data.constructor?.name === 'BinaryInput') {
|
|
263
|
+
const jsonData = await data.getJsonData(candidate);
|
|
264
|
+
dataForDebug = `[BinaryInput size=${jsonData?.size}]`;
|
|
265
|
+
} else if (isBuffer(data)) {
|
|
266
|
+
dataForDebug = `[Buffer size=${data.byteLength}]`;
|
|
267
|
+
} else if (data.constructor?.name === 'FormData') {
|
|
268
|
+
dataForDebug = `[FormData]`;
|
|
269
|
+
} else if (isBase64(data) || isBase64DataUrl(data)) {
|
|
270
|
+
dataForDebug = `[Base64 size=${getBase64FileSize(data)}]`;
|
|
271
|
+
} else {
|
|
272
|
+
dataForDebug = data;
|
|
273
|
+
}
|
|
274
|
+
} catch (error) {
|
|
275
|
+
// Fallback to a safe representation if any error occurs
|
|
276
|
+
dataForDebug = '[Binary]';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return dataForDebug;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// TODO: Maybe we need move this function to any helper file, as it depends on BinaryInput class
|
|
283
|
+
export async function normalizeImageInput(inputImage: string | BinaryInput): Promise<string> {
|
|
284
|
+
if (!inputImage) {
|
|
285
|
+
return '';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Handle string inputs
|
|
289
|
+
if (typeof inputImage === 'string') {
|
|
290
|
+
if (isBase64(inputImage)) {
|
|
291
|
+
// Convert raw base64 to data URL with proper MIME type
|
|
292
|
+
const mimeType = (await getMimeType(inputImage)) || 'image/png';
|
|
293
|
+
return `data:${mimeType};base64,${inputImage}`;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (isBase64DataUrl(inputImage)) {
|
|
297
|
+
return inputImage; // Already in correct format
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (isUrl(inputImage)) {
|
|
301
|
+
return inputImage; // Valid URL, return as-is
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
throw new Error('Invalid string input: must be base64, data URL, or HTTP(S) URL');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Handle BinaryInput
|
|
308
|
+
// * There is a bug (server crash) when we check like this: inputImage instanceof BinaryInput
|
|
309
|
+
// TODO [Forhad]: Need find out the root cause and fix it
|
|
310
|
+
if (inputImage.constructor?.name === 'BinaryInput') {
|
|
311
|
+
try {
|
|
312
|
+
const buffer = await inputImage.getBuffer();
|
|
313
|
+
const mimeType = (await getMimeType(buffer)) || 'image/png';
|
|
314
|
+
const base64Data = buffer.toString('base64');
|
|
315
|
+
return `data:${mimeType};base64,${base64Data}`;
|
|
316
|
+
} catch (error) {
|
|
317
|
+
throw new Error(`Failed to process BinaryInput: ${error.message}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
throw new Error('Unsupported input type');
|
|
322
|
+
}
|