@arkyn/server 2.2.15 → 3.0.1-beta.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/README.md +1 -1
- package/dist/api/arkynLogRequest.d.ts +55 -0
- package/dist/api/arkynLogRequest.d.ts.map +1 -0
- package/dist/api/arkynLogRequest.js +82 -0
- package/dist/api/deleteRequest.d.ts +1 -1
- package/dist/api/deleteRequest.d.ts.map +1 -1
- package/dist/api/getRequest.d.ts +1 -1
- package/dist/api/getRequest.d.ts.map +1 -1
- package/dist/api/makeRequest.d.ts +2 -2
- package/dist/api/makeRequest.d.ts.map +1 -1
- package/dist/api/makeRequest.js +18 -18
- package/dist/api/patchRequest.d.ts +1 -1
- package/dist/api/patchRequest.d.ts.map +1 -1
- package/dist/api/postRequest.d.ts +1 -1
- package/dist/api/postRequest.d.ts.map +1 -1
- package/dist/api/putRequest.d.ts +1 -1
- package/dist/api/putRequest.d.ts.map +1 -1
- package/dist/config/apiInstance.d.ts +5 -5
- package/dist/config/arkynLogInstance.d.ts +44 -0
- package/dist/config/arkynLogInstance.d.ts.map +1 -0
- package/dist/config/arkynLogInstance.js +49 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/mapper/arkynLogRequestMapper.d.ts +30 -0
- package/dist/mapper/arkynLogRequestMapper.d.ts.map +1 -0
- package/dist/mapper/arkynLogRequestMapper.js +44 -0
- package/dist/services/decodeRequestBody.d.ts +1 -1
- package/dist/services/decodeRequestBody.d.ts.map +1 -1
- package/dist/services/formParse.d.ts +18 -1
- package/dist/services/formParse.d.ts.map +1 -1
- package/dist/services/getCaller.d.ts.map +1 -1
- package/dist/services/getCaller.js +41 -15
- package/dist/services/getScopedParams.d.ts +1 -1
- package/dist/services/getScopedParams.d.ts.map +1 -1
- package/dist/services/httpDebug.d.ts.map +1 -1
- package/dist/services/httpDebug.js +0 -1
- package/dist/types/ApiResponseDTO.d.ts +17 -0
- package/dist/types/ApiResponseDTO.d.ts.map +1 -0
- package/dist/types/ApiResponseDTO.js +1 -0
- package/package.json +2 -5
- package/src/api/arkynLogRequest.ts +118 -0
- package/src/api/deleteRequest.ts +1 -1
- package/src/api/getRequest.ts +1 -1
- package/src/api/makeRequest.ts +21 -20
- package/src/api/patchRequest.ts +1 -1
- package/src/api/postRequest.ts +1 -1
- package/src/api/putRequest.ts +1 -1
- package/src/config/arkynLogInstance.ts +70 -0
- package/src/index.ts +1 -2
- package/src/mapper/arkynLogRequestMapper.ts +73 -0
- package/src/services/decodeRequestBody.ts +2 -1
- package/src/services/formParse.ts +18 -1
- package/src/services/getCaller.ts +54 -20
- package/src/services/getScopedParams.ts +4 -2
- package/src/services/httpDebug.ts +0 -1
- package/src/types/ApiResponseDTO.ts +19 -0
- package/dist/api/inboxFlowRequest.d.ts +0 -40
- package/dist/api/inboxFlowRequest.d.ts.map +0 -1
- package/dist/api/inboxFlowRequest.js +0 -63
- package/dist/config/inboxFlowInstance.d.ts +0 -44
- package/dist/config/inboxFlowInstance.d.ts.map +0 -1
- package/dist/config/inboxFlowInstance.js +0 -46
- package/dist/services/sendFileToS3.d.ts +0 -4
- package/dist/services/sendFileToS3.d.ts.map +0 -1
- package/dist/services/sendFileToS3.js +0 -105
- package/src/api/inboxFlowRequest.ts +0 -76
- package/src/config/inboxFlowInstance.ts +0 -65
- package/src/services/sendFileToS3.ts +0 -131
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type ApiSuccessResponse<T = any> = {
|
|
2
|
+
success: true;
|
|
3
|
+
status: number;
|
|
4
|
+
message: string;
|
|
5
|
+
response: T;
|
|
6
|
+
cause: null;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type ApiFailedResponse = {
|
|
10
|
+
success: false;
|
|
11
|
+
status: number;
|
|
12
|
+
message: string;
|
|
13
|
+
response: any;
|
|
14
|
+
cause: string | Error | null;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type ApiResponseDTO<T = any> = ApiSuccessResponse<T> | ApiFailedResponse;
|
|
18
|
+
|
|
19
|
+
export type { ApiResponseDTO };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
type ConfigProps = {
|
|
2
|
-
status: number;
|
|
3
|
-
method: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "ERROR";
|
|
4
|
-
request: string;
|
|
5
|
-
response: string;
|
|
6
|
-
token: string;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Sends a request to the inbox flow API with the provided configuration.
|
|
10
|
-
*
|
|
11
|
-
* @param config - The configuration object for the request.
|
|
12
|
-
* @param config.status - The HTTP status code associated with the request.
|
|
13
|
-
* @param config.method - The HTTP method used for the request. Can be "POST", "GET", "PUT", "DELETE", "PATCH", or "ERROR".
|
|
14
|
-
* @param config.request - The request payload or details as a string.
|
|
15
|
-
* @param config.response - The response payload or details as a string.
|
|
16
|
-
* @param config.token - The token associated with the request for authentication or identification.
|
|
17
|
-
*
|
|
18
|
-
* @remarks
|
|
19
|
-
* - This function retrieves the inbox flow configuration using `InboxFlowInstance.getInboxConfig()`.
|
|
20
|
-
* - If the configuration is not available, the function will return early without performing any action.
|
|
21
|
-
* - In a development environment (`NODE_ENV === "development"`), the function will also return early.
|
|
22
|
-
* - The request is sent as a POST request to the inbox API URL with the provided configuration details.
|
|
23
|
-
* - If an error occurs during the request, it will be logged using the `httpDebug` service.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* const config = {
|
|
28
|
-
* status: 200,
|
|
29
|
-
* method: "POST",
|
|
30
|
-
* request: JSON.stringify({ key: "value" }),
|
|
31
|
-
* response: JSON.stringify({ success: true }),
|
|
32
|
-
* token: "example-token",
|
|
33
|
-
* };
|
|
34
|
-
*
|
|
35
|
-
* await inboxFlowRequest(config);
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
declare function inboxFlowRequest(config: ConfigProps): Promise<void>;
|
|
39
|
-
export { inboxFlowRequest };
|
|
40
|
-
//# sourceMappingURL=inboxFlowRequest.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inboxFlowRequest.d.ts","sourceRoot":"","sources":["../../src/api/inboxFlowRequest.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,iBAAe,gBAAgB,CAAC,MAAM,EAAE,WAAW,iBA+BlD;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { InboxFlowInstance } from "../config/inboxFlowInstance";
|
|
2
|
-
import { httpDebug } from "../services/httpDebug";
|
|
3
|
-
/**
|
|
4
|
-
* Sends a request to the inbox flow API with the provided configuration.
|
|
5
|
-
*
|
|
6
|
-
* @param config - The configuration object for the request.
|
|
7
|
-
* @param config.status - The HTTP status code associated with the request.
|
|
8
|
-
* @param config.method - The HTTP method used for the request. Can be "POST", "GET", "PUT", "DELETE", "PATCH", or "ERROR".
|
|
9
|
-
* @param config.request - The request payload or details as a string.
|
|
10
|
-
* @param config.response - The response payload or details as a string.
|
|
11
|
-
* @param config.token - The token associated with the request for authentication or identification.
|
|
12
|
-
*
|
|
13
|
-
* @remarks
|
|
14
|
-
* - This function retrieves the inbox flow configuration using `InboxFlowInstance.getInboxConfig()`.
|
|
15
|
-
* - If the configuration is not available, the function will return early without performing any action.
|
|
16
|
-
* - In a development environment (`NODE_ENV === "development"`), the function will also return early.
|
|
17
|
-
* - The request is sent as a POST request to the inbox API URL with the provided configuration details.
|
|
18
|
-
* - If an error occurs during the request, it will be logged using the `httpDebug` service.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```typescript
|
|
22
|
-
* const config = {
|
|
23
|
-
* status: 200,
|
|
24
|
-
* method: "POST",
|
|
25
|
-
* request: JSON.stringify({ key: "value" }),
|
|
26
|
-
* response: JSON.stringify({ success: true }),
|
|
27
|
-
* token: "example-token",
|
|
28
|
-
* };
|
|
29
|
-
*
|
|
30
|
-
* await inboxFlowRequest(config);
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
async function inboxFlowRequest(config) {
|
|
34
|
-
const inboxFlowInstance = InboxFlowInstance.getInboxConfig();
|
|
35
|
-
if (!inboxFlowInstance)
|
|
36
|
-
return;
|
|
37
|
-
const { inboxChannelId, inboxUserToken, inboxApiUrl } = inboxFlowInstance;
|
|
38
|
-
const { status, method, request, response, token } = config;
|
|
39
|
-
if (process.env.NODE_ENV === "development")
|
|
40
|
-
return;
|
|
41
|
-
try {
|
|
42
|
-
const body = JSON.stringify({
|
|
43
|
-
status,
|
|
44
|
-
channelId: inboxChannelId,
|
|
45
|
-
method,
|
|
46
|
-
token,
|
|
47
|
-
request,
|
|
48
|
-
response,
|
|
49
|
-
});
|
|
50
|
-
await fetch(inboxApiUrl, {
|
|
51
|
-
method: "POST",
|
|
52
|
-
body,
|
|
53
|
-
headers: {
|
|
54
|
-
"Content-Type": "application/json",
|
|
55
|
-
Authorization: `Bearer ${inboxUserToken}`,
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
httpDebug("inboxFlowRequest", "Error sending inbox flow request", err);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
export { inboxFlowRequest };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
type InboxConfigProps = {
|
|
2
|
-
inboxChannelId: string;
|
|
3
|
-
inboxUserToken: string;
|
|
4
|
-
inboxApiUrl: string;
|
|
5
|
-
};
|
|
6
|
-
type SetInboxConfigProps = {
|
|
7
|
-
inboxChannelId: string;
|
|
8
|
-
inboxUserToken: string;
|
|
9
|
-
inboxApiUrl?: string;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* The `InboxFlowInstance` class manages the configuration for the inbox flow.
|
|
13
|
-
* It allows you to set and retrieve the inbox configuration, including the channel ID,
|
|
14
|
-
* user token, and API URL.
|
|
15
|
-
*/
|
|
16
|
-
declare class InboxFlowInstance {
|
|
17
|
-
private static inboxConfig?;
|
|
18
|
-
/**
|
|
19
|
-
* Sets the configuration for the inbox. This method initializes the inbox configuration
|
|
20
|
-
* with the provided `inboxConfig` values. If the configuration has already been set,
|
|
21
|
-
* the method will return early without making any changes.
|
|
22
|
-
*
|
|
23
|
-
* @param inboxConfig - An object containing the inbox configuration properties.
|
|
24
|
-
* @param inboxConfig.inboxChannelId - The key used to identify the inbox.
|
|
25
|
-
* @param inboxConfig.inboxUserToken - The user token for authenticating with the inbox.
|
|
26
|
-
* @param inboxConfig.inboxApiUrl - (Optional) The API URL for the inbox. If not provided,
|
|
27
|
-
* a default URL will be used.
|
|
28
|
-
*/
|
|
29
|
-
static setInboxConfig(inboxConfig: SetInboxConfigProps): void;
|
|
30
|
-
/**
|
|
31
|
-
* Retrieves the current inbox configuration for the InboxFlowInstance.
|
|
32
|
-
*
|
|
33
|
-
* @returns {InboxConfigProps | undefined} The current inbox configuration if set,
|
|
34
|
-
* or `undefined` if no configuration has been initialized.
|
|
35
|
-
*/
|
|
36
|
-
static getInboxConfig(): InboxConfigProps | undefined;
|
|
37
|
-
/**
|
|
38
|
-
* Resets the inbox configuration to `undefined`.
|
|
39
|
-
* This method can be used to clear the current configuration.
|
|
40
|
-
*/
|
|
41
|
-
static resetInboxConfig(): void;
|
|
42
|
-
}
|
|
43
|
-
export { InboxFlowInstance };
|
|
44
|
-
//# sourceMappingURL=inboxFlowInstance.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inboxFlowInstance.d.ts","sourceRoot":"","sources":["../../src/config/inboxFlowInstance.ts"],"names":[],"mappings":"AAAA,KAAK,gBAAgB,GAAG;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AAEH,cAAM,iBAAiB;IACrB,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAmB;IAE9C;;;;;;;;;;OAUG;IAEH,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,mBAAmB;IAWtD;;;;;OAKG;IACH,MAAM,CAAC,cAAc,IAAI,gBAAgB,GAAG,SAAS;IAIrD;;;OAGG;IAEH,MAAM,CAAC,gBAAgB;CAGxB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `InboxFlowInstance` class manages the configuration for the inbox flow.
|
|
3
|
-
* It allows you to set and retrieve the inbox configuration, including the channel ID,
|
|
4
|
-
* user token, and API URL.
|
|
5
|
-
*/
|
|
6
|
-
class InboxFlowInstance {
|
|
7
|
-
static inboxConfig;
|
|
8
|
-
/**
|
|
9
|
-
* Sets the configuration for the inbox. This method initializes the inbox configuration
|
|
10
|
-
* with the provided `inboxConfig` values. If the configuration has already been set,
|
|
11
|
-
* the method will return early without making any changes.
|
|
12
|
-
*
|
|
13
|
-
* @param inboxConfig - An object containing the inbox configuration properties.
|
|
14
|
-
* @param inboxConfig.inboxChannelId - The key used to identify the inbox.
|
|
15
|
-
* @param inboxConfig.inboxUserToken - The user token for authenticating with the inbox.
|
|
16
|
-
* @param inboxConfig.inboxApiUrl - (Optional) The API URL for the inbox. If not provided,
|
|
17
|
-
* a default URL will be used.
|
|
18
|
-
*/
|
|
19
|
-
static setInboxConfig(inboxConfig) {
|
|
20
|
-
const defaultInboxURL = `https://logs-inbox-flow-logs.vw6wo7.easypanel.host/api/call`;
|
|
21
|
-
if (!!this.inboxConfig)
|
|
22
|
-
return;
|
|
23
|
-
this.inboxConfig = {
|
|
24
|
-
inboxChannelId: inboxConfig.inboxChannelId,
|
|
25
|
-
inboxUserToken: inboxConfig.inboxUserToken,
|
|
26
|
-
inboxApiUrl: inboxConfig.inboxApiUrl || defaultInboxURL,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Retrieves the current inbox configuration for the InboxFlowInstance.
|
|
31
|
-
*
|
|
32
|
-
* @returns {InboxConfigProps | undefined} The current inbox configuration if set,
|
|
33
|
-
* or `undefined` if no configuration has been initialized.
|
|
34
|
-
*/
|
|
35
|
-
static getInboxConfig() {
|
|
36
|
-
return this.inboxConfig;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Resets the inbox configuration to `undefined`.
|
|
40
|
-
* This method can be used to clear the current configuration.
|
|
41
|
-
*/
|
|
42
|
-
static resetInboxConfig() {
|
|
43
|
-
this.inboxConfig = undefined;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
export { InboxFlowInstance };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sendFileToS3.d.ts","sourceRoot":"","sources":["../../src/services/sendFileToS3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,oBAAoB,EAAE,MAAM,cAAc,CAAC;AA0CpE,QAAA,MAAM,YAAY,EAAE,oBAqFnB,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { generateId } from "@arkyn/shared";
|
|
2
|
-
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
3
|
-
import { MultipartParseError, parseMultipartRequest, } from "@mjackson/multipart-parser";
|
|
4
|
-
import fs from "fs";
|
|
5
|
-
import sharp from "sharp";
|
|
6
|
-
import { BadRequest } from "../http/badResponses/badRequest";
|
|
7
|
-
import { getScopedParams } from "./getScopedParams";
|
|
8
|
-
async function s3Upload(fileStream, contentType, awsConfig) {
|
|
9
|
-
const Key = `uploads/${generateId("text", "v4")}`;
|
|
10
|
-
const uploadParams = {
|
|
11
|
-
Bucket: awsConfig.AWS_S3_BUCKET,
|
|
12
|
-
Key,
|
|
13
|
-
Body: fileStream,
|
|
14
|
-
ContentType: contentType,
|
|
15
|
-
};
|
|
16
|
-
const s3Client = new S3Client({
|
|
17
|
-
region: awsConfig.AWS_REGION,
|
|
18
|
-
credentials: {
|
|
19
|
-
accessKeyId: awsConfig.AWS_ACCESS_KEY_ID,
|
|
20
|
-
secretAccessKey: awsConfig.AWS_SECRET_ACCESS_KEY,
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
await s3Client.send(new PutObjectCommand(uploadParams));
|
|
24
|
-
return {
|
|
25
|
-
location: `https://${awsConfig.AWS_S3_BUCKET}.s3.amazonaws.com/${Key}`,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const sendFileToS3 = async (request, awsS3Config, config) => {
|
|
29
|
-
const fileName = config?.fileName ?? "file";
|
|
30
|
-
const reduceImageQuality = config?.reduceImageQuality ?? 100;
|
|
31
|
-
const validateImageSize = config?.validateImageSize ?? false;
|
|
32
|
-
const validateImageMessage = config?.validateImageMessage ??
|
|
33
|
-
"Invalid dimensions {{width}}px x {{height}}px";
|
|
34
|
-
let saved = {
|
|
35
|
-
tempPath: "",
|
|
36
|
-
mediaType: "",
|
|
37
|
-
};
|
|
38
|
-
try {
|
|
39
|
-
await parseMultipartRequest(request, async (part) => {
|
|
40
|
-
if (part.isFile && part.name === fileName) {
|
|
41
|
-
const bytes = await part.bytes();
|
|
42
|
-
const tempPath = `/tmp/${generateId("text", "v4")}-${part.filename}`;
|
|
43
|
-
await Bun.write(tempPath, bytes);
|
|
44
|
-
if (!part.mediaType)
|
|
45
|
-
throw new Error("mediaType is undefined");
|
|
46
|
-
saved = {
|
|
47
|
-
tempPath,
|
|
48
|
-
mediaType: part.mediaType,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
catch (err) {
|
|
54
|
-
if (err instanceof MultipartParseError) {
|
|
55
|
-
throw new BadRequest(`Falha ao processar upload: ${err.message}`);
|
|
56
|
-
}
|
|
57
|
-
throw err;
|
|
58
|
-
}
|
|
59
|
-
if (saved.mediaType === "")
|
|
60
|
-
throw new BadRequest("mediaType é indefinido");
|
|
61
|
-
if (saved.tempPath === "")
|
|
62
|
-
throw new BadRequest("tempPath é indefinido");
|
|
63
|
-
const filterParams = getScopedParams(request);
|
|
64
|
-
const width = filterParams.get("w");
|
|
65
|
-
const height = filterParams.get("h");
|
|
66
|
-
const quality = filterParams.get("reduceQuality") !== null
|
|
67
|
-
? +filterParams.get("reduceQuality")
|
|
68
|
-
: reduceImageQuality;
|
|
69
|
-
const isImage = saved.mediaType.startsWith("image/");
|
|
70
|
-
if (isImage && width && height && validateImageSize) {
|
|
71
|
-
const meta = await sharp(saved.tempPath).metadata();
|
|
72
|
-
if (meta.width && meta.height) {
|
|
73
|
-
const dw = Math.abs(meta.width - +width);
|
|
74
|
-
const dh = Math.abs(meta.height - +height);
|
|
75
|
-
if (dw > 10 || dh > 10) {
|
|
76
|
-
fs.unlink(saved.tempPath, () => { });
|
|
77
|
-
return {
|
|
78
|
-
error: validateImageMessage
|
|
79
|
-
.replace("{{width}}", width)
|
|
80
|
-
.replace("{{height}}", height),
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
let uploadPath = saved.tempPath;
|
|
86
|
-
if (isImage) {
|
|
87
|
-
const ext = saved.mediaType.split("/")[1];
|
|
88
|
-
const compressed = `${saved.tempPath}_cmp.${ext}`;
|
|
89
|
-
let img = sharp(saved.tempPath);
|
|
90
|
-
if (ext === "jpeg" || ext === "jpg")
|
|
91
|
-
img = img.jpeg({ quality });
|
|
92
|
-
else if (ext === "png")
|
|
93
|
-
img = img.png({ quality });
|
|
94
|
-
else if (ext === "webp")
|
|
95
|
-
img = img.webp({ quality });
|
|
96
|
-
await img.toFile(compressed);
|
|
97
|
-
fs.unlink(saved.tempPath, () => { });
|
|
98
|
-
uploadPath = compressed;
|
|
99
|
-
}
|
|
100
|
-
const stream = fs.createReadStream(uploadPath);
|
|
101
|
-
const { location } = await s3Upload(stream, saved.mediaType, awsS3Config);
|
|
102
|
-
fs.unlink(uploadPath, () => { });
|
|
103
|
-
return { url: location };
|
|
104
|
-
};
|
|
105
|
-
export { sendFileToS3 };
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { InboxFlowInstance } from "../config/inboxFlowInstance";
|
|
2
|
-
import { httpDebug } from "../services/httpDebug";
|
|
3
|
-
|
|
4
|
-
type ConfigProps = {
|
|
5
|
-
status: number;
|
|
6
|
-
method: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "ERROR";
|
|
7
|
-
request: string;
|
|
8
|
-
response: string;
|
|
9
|
-
token: string;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Sends a request to the inbox flow API with the provided configuration.
|
|
14
|
-
*
|
|
15
|
-
* @param config - The configuration object for the request.
|
|
16
|
-
* @param config.status - The HTTP status code associated with the request.
|
|
17
|
-
* @param config.method - The HTTP method used for the request. Can be "POST", "GET", "PUT", "DELETE", "PATCH", or "ERROR".
|
|
18
|
-
* @param config.request - The request payload or details as a string.
|
|
19
|
-
* @param config.response - The response payload or details as a string.
|
|
20
|
-
* @param config.token - The token associated with the request for authentication or identification.
|
|
21
|
-
*
|
|
22
|
-
* @remarks
|
|
23
|
-
* - This function retrieves the inbox flow configuration using `InboxFlowInstance.getInboxConfig()`.
|
|
24
|
-
* - If the configuration is not available, the function will return early without performing any action.
|
|
25
|
-
* - In a development environment (`NODE_ENV === "development"`), the function will also return early.
|
|
26
|
-
* - The request is sent as a POST request to the inbox API URL with the provided configuration details.
|
|
27
|
-
* - If an error occurs during the request, it will be logged using the `httpDebug` service.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```typescript
|
|
31
|
-
* const config = {
|
|
32
|
-
* status: 200,
|
|
33
|
-
* method: "POST",
|
|
34
|
-
* request: JSON.stringify({ key: "value" }),
|
|
35
|
-
* response: JSON.stringify({ success: true }),
|
|
36
|
-
* token: "example-token",
|
|
37
|
-
* };
|
|
38
|
-
*
|
|
39
|
-
* await inboxFlowRequest(config);
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
async function inboxFlowRequest(config: ConfigProps) {
|
|
44
|
-
const inboxFlowInstance = InboxFlowInstance.getInboxConfig();
|
|
45
|
-
if (!inboxFlowInstance) return;
|
|
46
|
-
|
|
47
|
-
const { inboxChannelId, inboxUserToken, inboxApiUrl } = inboxFlowInstance;
|
|
48
|
-
|
|
49
|
-
const { status, method, request, response, token } = config;
|
|
50
|
-
|
|
51
|
-
if (process.env.NODE_ENV === "development") return;
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
const body = JSON.stringify({
|
|
55
|
-
status,
|
|
56
|
-
channelId: inboxChannelId,
|
|
57
|
-
method,
|
|
58
|
-
token,
|
|
59
|
-
request,
|
|
60
|
-
response,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
await fetch(inboxApiUrl, {
|
|
64
|
-
method: "POST",
|
|
65
|
-
body,
|
|
66
|
-
headers: {
|
|
67
|
-
"Content-Type": "application/json",
|
|
68
|
-
Authorization: `Bearer ${inboxUserToken}`,
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
} catch (err) {
|
|
72
|
-
httpDebug("inboxFlowRequest", "Error sending inbox flow request", err);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export { inboxFlowRequest };
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
type InboxConfigProps = {
|
|
2
|
-
inboxChannelId: string;
|
|
3
|
-
inboxUserToken: string;
|
|
4
|
-
inboxApiUrl: string;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
type SetInboxConfigProps = {
|
|
8
|
-
inboxChannelId: string;
|
|
9
|
-
inboxUserToken: string;
|
|
10
|
-
inboxApiUrl?: string;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The `InboxFlowInstance` class manages the configuration for the inbox flow.
|
|
15
|
-
* It allows you to set and retrieve the inbox configuration, including the channel ID,
|
|
16
|
-
* user token, and API URL.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
class InboxFlowInstance {
|
|
20
|
-
private static inboxConfig?: InboxConfigProps;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Sets the configuration for the inbox. This method initializes the inbox configuration
|
|
24
|
-
* with the provided `inboxConfig` values. If the configuration has already been set,
|
|
25
|
-
* the method will return early without making any changes.
|
|
26
|
-
*
|
|
27
|
-
* @param inboxConfig - An object containing the inbox configuration properties.
|
|
28
|
-
* @param inboxConfig.inboxChannelId - The key used to identify the inbox.
|
|
29
|
-
* @param inboxConfig.inboxUserToken - The user token for authenticating with the inbox.
|
|
30
|
-
* @param inboxConfig.inboxApiUrl - (Optional) The API URL for the inbox. If not provided,
|
|
31
|
-
* a default URL will be used.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
static setInboxConfig(inboxConfig: SetInboxConfigProps) {
|
|
35
|
-
const defaultInboxURL = `https://logs-inbox-flow-logs.vw6wo7.easypanel.host/api/call`;
|
|
36
|
-
if (!!this.inboxConfig) return;
|
|
37
|
-
|
|
38
|
-
this.inboxConfig = {
|
|
39
|
-
inboxChannelId: inboxConfig.inboxChannelId,
|
|
40
|
-
inboxUserToken: inboxConfig.inboxUserToken,
|
|
41
|
-
inboxApiUrl: inboxConfig.inboxApiUrl || defaultInboxURL,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Retrieves the current inbox configuration for the InboxFlowInstance.
|
|
47
|
-
*
|
|
48
|
-
* @returns {InboxConfigProps | undefined} The current inbox configuration if set,
|
|
49
|
-
* or `undefined` if no configuration has been initialized.
|
|
50
|
-
*/
|
|
51
|
-
static getInboxConfig(): InboxConfigProps | undefined {
|
|
52
|
-
return this.inboxConfig;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Resets the inbox configuration to `undefined`.
|
|
57
|
-
* This method can be used to clear the current configuration.
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
static resetInboxConfig() {
|
|
61
|
-
this.inboxConfig = undefined;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export { InboxFlowInstance };
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { generateId } from "@arkyn/shared";
|
|
2
|
-
import type { AwsConfig, SendFileToS3Function } from "@arkyn/types";
|
|
3
|
-
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
4
|
-
import {
|
|
5
|
-
MultipartParseError,
|
|
6
|
-
parseMultipartRequest,
|
|
7
|
-
} from "@mjackson/multipart-parser";
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import sharp from "sharp";
|
|
10
|
-
import { BadRequest } from "../http/badResponses/badRequest";
|
|
11
|
-
import { getScopedParams } from "./getScopedParams";
|
|
12
|
-
|
|
13
|
-
type Saved = {
|
|
14
|
-
tempPath: string;
|
|
15
|
-
mediaType: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
async function s3Upload(
|
|
19
|
-
fileStream: fs.ReadStream,
|
|
20
|
-
contentType: string,
|
|
21
|
-
awsConfig: AwsConfig
|
|
22
|
-
) {
|
|
23
|
-
const Key = `uploads/${generateId("text", "v4")}`;
|
|
24
|
-
const uploadParams = {
|
|
25
|
-
Bucket: awsConfig.AWS_S3_BUCKET,
|
|
26
|
-
Key,
|
|
27
|
-
Body: fileStream,
|
|
28
|
-
ContentType: contentType,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const s3Client = new S3Client({
|
|
32
|
-
region: awsConfig.AWS_REGION,
|
|
33
|
-
credentials: {
|
|
34
|
-
accessKeyId: awsConfig.AWS_ACCESS_KEY_ID,
|
|
35
|
-
secretAccessKey: awsConfig.AWS_SECRET_ACCESS_KEY,
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
await s3Client.send(new PutObjectCommand(uploadParams));
|
|
39
|
-
return {
|
|
40
|
-
location: `https://${awsConfig.AWS_S3_BUCKET}.s3.amazonaws.com/${Key}`,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const sendFileToS3: SendFileToS3Function = async (
|
|
45
|
-
request,
|
|
46
|
-
awsS3Config,
|
|
47
|
-
config
|
|
48
|
-
) => {
|
|
49
|
-
const fileName = config?.fileName ?? "file";
|
|
50
|
-
const reduceImageQuality = config?.reduceImageQuality ?? 100;
|
|
51
|
-
const validateImageSize = config?.validateImageSize ?? false;
|
|
52
|
-
const validateImageMessage =
|
|
53
|
-
config?.validateImageMessage ??
|
|
54
|
-
"Invalid dimensions {{width}}px x {{height}}px";
|
|
55
|
-
|
|
56
|
-
let saved: Saved = {
|
|
57
|
-
tempPath: "",
|
|
58
|
-
mediaType: "",
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
await parseMultipartRequest(request, async (part) => {
|
|
63
|
-
if (part.isFile && part.name === fileName) {
|
|
64
|
-
const bytes = await part.bytes();
|
|
65
|
-
const tempPath = `/tmp/${generateId("text", "v4")}-${part.filename}`;
|
|
66
|
-
await Bun.write(tempPath, bytes);
|
|
67
|
-
if (!part.mediaType) throw new Error("mediaType is undefined");
|
|
68
|
-
|
|
69
|
-
saved = {
|
|
70
|
-
tempPath,
|
|
71
|
-
mediaType: part.mediaType,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
} catch (err) {
|
|
76
|
-
if (err instanceof MultipartParseError) {
|
|
77
|
-
throw new BadRequest(`Falha ao processar upload: ${err.message}`);
|
|
78
|
-
}
|
|
79
|
-
throw err;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (saved.mediaType === "") throw new BadRequest("mediaType é indefinido");
|
|
83
|
-
if (saved.tempPath === "") throw new BadRequest("tempPath é indefinido");
|
|
84
|
-
|
|
85
|
-
const filterParams = getScopedParams(request);
|
|
86
|
-
const width = filterParams.get("w");
|
|
87
|
-
const height = filterParams.get("h");
|
|
88
|
-
const quality =
|
|
89
|
-
filterParams.get("reduceQuality") !== null
|
|
90
|
-
? +filterParams.get("reduceQuality")!
|
|
91
|
-
: reduceImageQuality;
|
|
92
|
-
|
|
93
|
-
const isImage = saved.mediaType.startsWith("image/");
|
|
94
|
-
|
|
95
|
-
if (isImage && width && height && validateImageSize) {
|
|
96
|
-
const meta = await sharp(saved.tempPath).metadata();
|
|
97
|
-
if (meta.width && meta.height) {
|
|
98
|
-
const dw = Math.abs(meta.width - +width);
|
|
99
|
-
const dh = Math.abs(meta.height - +height);
|
|
100
|
-
if (dw > 10 || dh > 10) {
|
|
101
|
-
fs.unlink(saved.tempPath, () => {});
|
|
102
|
-
return {
|
|
103
|
-
error: validateImageMessage
|
|
104
|
-
.replace("{{width}}", width)
|
|
105
|
-
.replace("{{height}}", height),
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let uploadPath = saved.tempPath;
|
|
112
|
-
if (isImage) {
|
|
113
|
-
const ext = saved.mediaType.split("/")[1];
|
|
114
|
-
const compressed = `${saved.tempPath}_cmp.${ext}`;
|
|
115
|
-
let img = sharp(saved.tempPath);
|
|
116
|
-
if (ext === "jpeg" || ext === "jpg") img = img.jpeg({ quality });
|
|
117
|
-
else if (ext === "png") img = img.png({ quality });
|
|
118
|
-
else if (ext === "webp") img = img.webp({ quality });
|
|
119
|
-
await img.toFile(compressed);
|
|
120
|
-
fs.unlink(saved.tempPath, () => {});
|
|
121
|
-
uploadPath = compressed;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const stream = fs.createReadStream(uploadPath);
|
|
125
|
-
const { location } = await s3Upload(stream, saved.mediaType, awsS3Config);
|
|
126
|
-
|
|
127
|
-
fs.unlink(uploadPath, () => {});
|
|
128
|
-
return { url: location };
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
export { sendFileToS3 };
|