@ccci/micro-server 1.0.243 → 1.1.5
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/decorators/Endpoints.d.ts +12 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +308159 -0
- package/dist/test/Uploader.integration.test.d.ts +2 -0
- package/dist/types/ApplicationOptionType.d.ts +37 -0
- package/dist/types/AttachmentMetadataTypes.d.ts +23 -0
- package/dist/types/BaseControllerTypes.d.ts +42 -0
- package/dist/types/BaseModelTypes.d.ts +41 -0
- package/dist/types/BaseRouterTypes.d.ts +9 -0
- package/dist/types/BaseSocketType.d.ts +6 -0
- package/dist/types/BrokerType.d.ts +13 -0
- package/dist/types/NotificationTypes.d.ts +9 -0
- package/dist/types/UploadedFileType.d.ts +68 -0
- package/dist/utils/ApplicationServer.d.ts +30 -0
- package/dist/utils/BaseAuthenticatorModel.d.ts +7 -0
- package/dist/utils/BaseConsumer.d.ts +44 -0
- package/dist/utils/BaseController.d.ts +97 -0
- package/dist/utils/BaseControllerHelper.d.ts +27 -0
- package/dist/utils/BaseKafka.d.ts +37 -0
- package/dist/utils/BaseModel.d.ts +44 -0
- package/dist/utils/BaseProducer.d.ts +42 -0
- package/dist/utils/BaseRedis.d.ts +36 -0
- package/dist/utils/BaseRedisConnector.d.ts +10 -0
- package/dist/utils/BaseRouter.d.ts +91 -0
- package/dist/utils/BaseSocketHandler.d.ts +37 -0
- package/dist/utils/DatabaseConnector.d.ts +26 -0
- package/dist/utils/ErrorHandler.d.ts +5 -0
- package/dist/utils/IBaseModel.d.ts +9 -0
- package/dist/utils/Logger.d.ts +8 -0
- package/dist/utils/Mailer.d.ts +23 -0
- package/dist/utils/Mixins.d.ts +72 -0
- package/dist/utils/PushNotifier.d.ts +19 -0
- package/dist/utils/RedisQueryHelper.d.ts +38 -0
- package/dist/utils/RouterFactory.d.ts +12 -0
- package/dist/utils/ServeKafka.d.ts +16 -0
- package/dist/utils/TokenGenerator.d.ts +11 -0
- package/dist/utils/Uploader.d.ts +127 -0
- package/dist/utils/WebSocketServer.d.ts +29 -0
- package/dist/utils/uploader-s3.d.ts +68 -0
- package/package.json +7 -2
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Request, Response, NextFunction, Router } from 'express';
|
|
2
|
+
import BaseController from './BaseController';
|
|
3
|
+
import { Mappings } from '../types/BaseRouterTypes';
|
|
4
|
+
export default class BaseRouter<T extends BaseController> {
|
|
5
|
+
grantPublicAccess: boolean;
|
|
6
|
+
controller: T;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {Controller} controller
|
|
10
|
+
*/
|
|
11
|
+
constructor(controller: T);
|
|
12
|
+
/**
|
|
13
|
+
* @description GET route
|
|
14
|
+
* @param {Request} req
|
|
15
|
+
* @param {Response} res
|
|
16
|
+
* @param {NextFunction} next
|
|
17
|
+
*/
|
|
18
|
+
get(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* @description GET ARCHIVES route
|
|
21
|
+
* @param {Request} req
|
|
22
|
+
* @param {Response} res
|
|
23
|
+
* @param {NextFunction} next
|
|
24
|
+
*/
|
|
25
|
+
archives(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* @description POST route
|
|
28
|
+
* @param {Request} req
|
|
29
|
+
* @param {Response} res
|
|
30
|
+
* @param {NextFunction} next
|
|
31
|
+
*/
|
|
32
|
+
post(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* @description GET route (/:id)
|
|
35
|
+
* @param {HttpRequest} req
|
|
36
|
+
* @param {HttpResponse} res
|
|
37
|
+
* @param {*} next
|
|
38
|
+
*/
|
|
39
|
+
getId(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* @description PUT route (/:id)
|
|
42
|
+
* @param {HttpRequest} req
|
|
43
|
+
* @param {HttpResponse} res
|
|
44
|
+
* @param {*} next
|
|
45
|
+
*/
|
|
46
|
+
update(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @param req
|
|
50
|
+
* @param res
|
|
51
|
+
* @param next
|
|
52
|
+
*/
|
|
53
|
+
delete(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @param req
|
|
57
|
+
* @param res
|
|
58
|
+
* @param next
|
|
59
|
+
*/
|
|
60
|
+
restore(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* /count route
|
|
63
|
+
* @param req
|
|
64
|
+
* @param res
|
|
65
|
+
* @param next
|
|
66
|
+
*/
|
|
67
|
+
count(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* /stats get count by group
|
|
70
|
+
* @param req
|
|
71
|
+
* @param res
|
|
72
|
+
* @param next
|
|
73
|
+
*/
|
|
74
|
+
stats(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* @description default mappings that will be inherited across all router class
|
|
77
|
+
* @returns {Array} mappings
|
|
78
|
+
*/
|
|
79
|
+
getMapping: () => Mappings[];
|
|
80
|
+
/**
|
|
81
|
+
* @description additional mappings placeholder, designed to be overriden
|
|
82
|
+
* @returns {Array} mappings
|
|
83
|
+
*/
|
|
84
|
+
getAdditionalMapping: () => Mappings[];
|
|
85
|
+
/**
|
|
86
|
+
* @description create the express router
|
|
87
|
+
* @returns {Router} router
|
|
88
|
+
*/
|
|
89
|
+
getRoutes(): Router;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=BaseRouter.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="bun-types" />
|
|
4
|
+
import type { Server, ServerWebSocket } from 'bun';
|
|
5
|
+
export default class BaseSocketHandler {
|
|
6
|
+
static channel: string;
|
|
7
|
+
static server: Server;
|
|
8
|
+
static websocket: ServerWebSocket;
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param req {Request}
|
|
12
|
+
* @param server {Server}
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
upgrade(req: Request, server: Server): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @param ws {ServerWebSocket}
|
|
19
|
+
* @param message {String}
|
|
20
|
+
*/
|
|
21
|
+
accept(ws: ServerWebSocket, message: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param ws {ServerWebSocket}
|
|
25
|
+
*/
|
|
26
|
+
connect(ws: ServerWebSocket): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param ws {ServerWebSocket}
|
|
30
|
+
* @param code {number}
|
|
31
|
+
* @param reason {reason}
|
|
32
|
+
*/
|
|
33
|
+
disconnect(ws: ServerWebSocket, code: number, reason: string): Promise<void>;
|
|
34
|
+
getInstance(): ServerWebSocket;
|
|
35
|
+
static parse(url: String): any;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=BaseSocketHandler.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Model, ModelStatic, Sequelize } from "sequelize";
|
|
2
|
+
export default class DatabaseConnector {
|
|
3
|
+
private static connections;
|
|
4
|
+
private static connection;
|
|
5
|
+
private static rootDir;
|
|
6
|
+
constructor(path: string);
|
|
7
|
+
/**
|
|
8
|
+
* Initializes the database connection
|
|
9
|
+
* @param path
|
|
10
|
+
*/
|
|
11
|
+
static init(): Promise<Array<Sequelize>>;
|
|
12
|
+
static checkConnection(connection: Sequelize): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param path root dir (__dirname)
|
|
16
|
+
*/
|
|
17
|
+
initializeModels(): Promise<void>;
|
|
18
|
+
getConnections(): Array<Sequelize>;
|
|
19
|
+
static getConnection(): Sequelize;
|
|
20
|
+
connect(connection: Sequelize): Promise<void>;
|
|
21
|
+
static getModel(modelName: string): ModelStatic<Model>;
|
|
22
|
+
static sync(modelName: string, force?: boolean, alter?: boolean): Promise<void>;
|
|
23
|
+
static syncAll(force?: boolean, alter?: boolean): Promise<void>;
|
|
24
|
+
static disconnect(): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=DatabaseConnector.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default class Logger {
|
|
2
|
+
static info(message: string, details?: any): void;
|
|
3
|
+
static error(error: Error): void;
|
|
4
|
+
static warn(message: string): void;
|
|
5
|
+
static debug(message: string, details?: any): void;
|
|
6
|
+
static table(data: object[]): void;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=Logger.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ApplicationOptionType } from '..';
|
|
2
|
+
interface MailInterface {
|
|
3
|
+
from?: string;
|
|
4
|
+
to: string | string[];
|
|
5
|
+
cc?: string | string[];
|
|
6
|
+
bcc?: string | string[];
|
|
7
|
+
subject: string;
|
|
8
|
+
text?: string;
|
|
9
|
+
html: string;
|
|
10
|
+
}
|
|
11
|
+
export default class Mailer {
|
|
12
|
+
private static instance;
|
|
13
|
+
private transporter;
|
|
14
|
+
private sender;
|
|
15
|
+
private LOCAL_DIR;
|
|
16
|
+
static getInstance(): Mailer;
|
|
17
|
+
connect(options: ApplicationOptionType): Promise<void>;
|
|
18
|
+
hasValidConfig(options: ApplicationOptionType): boolean;
|
|
19
|
+
sendMail(options: MailInterface, template?: string, values?: any): Promise<void>;
|
|
20
|
+
findTemplate(name: string): Promise<unknown>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=Mailer.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves the MIME type for a given file name based on its extension.
|
|
4
|
+
* @param fileName - The name of the file to extract the MIME type for.
|
|
5
|
+
* @returns The MIME type if found, or null if not found.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getMimeType: (fileName: string) => string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Extracts numeric IDs from a string in the format [Name:ID].
|
|
10
|
+
* @param input - The input string containing IDs in the format [Name:ID].
|
|
11
|
+
* @returns An array of extracted numeric IDs.
|
|
12
|
+
*/
|
|
13
|
+
export declare const extractIds: (input: string) => number[];
|
|
14
|
+
/**
|
|
15
|
+
* Decrypts an encoded string using a salt.
|
|
16
|
+
* @param salt - The salt used for decryption.
|
|
17
|
+
* @param encoded - The encoded string to decrypt.
|
|
18
|
+
* @returns The decrypted string.
|
|
19
|
+
*/
|
|
20
|
+
export declare const decrypt: (salt: string, encoded: string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Encrypts a plain text string using a salt.
|
|
23
|
+
* @param salt - The salt used for encryption.
|
|
24
|
+
* @param text - The plain text string to encrypt.
|
|
25
|
+
* @returns The encrypted string in hexadecimal format.
|
|
26
|
+
*/
|
|
27
|
+
export declare const encrypt: (salt: string, text: string) => string;
|
|
28
|
+
/**
|
|
29
|
+
* Returns the start and end dates of the current week.
|
|
30
|
+
* The week starts on Monday (00:00:00.000) and ends on Sunday (23:59:59.999).
|
|
31
|
+
*
|
|
32
|
+
* @returns An object containing:
|
|
33
|
+
* - `startOfWeek`: Date representing the beginning of the current week (Monday at midnight).
|
|
34
|
+
* - `endOfWeek`: Date representing the end of the current week (Sunday at 23:59:59.999).
|
|
35
|
+
*/
|
|
36
|
+
export declare const getCurrentWeek: () => {
|
|
37
|
+
startOfWeek: Date;
|
|
38
|
+
endOfWeek: Date;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Consumes a readable stream and aggregates all data chunks into a single Buffer.
|
|
42
|
+
* * @param {stream.Readable} res - The incoming data stream.
|
|
43
|
+
* @returns {Promise<Buffer>} A promise that resolves to the complete binary data.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readAsBuffer(res: any): Promise<Buffer>;
|
|
46
|
+
/**
|
|
47
|
+
* Reads an HTTP response body in its entirety and converts it to a string.
|
|
48
|
+
* Useful for parsing XML error messages or small metadata responses.
|
|
49
|
+
* * @param {http.IncomingMessage} res - The HTTP response object.
|
|
50
|
+
* @returns {Promise<string>} The body content decoded as a string.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readAsString(res: any): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Parses an XML string into a JavaScript object using fast-xml-parser.
|
|
55
|
+
* * @throws {S3XmlError} If the XML contains an <Error> tag, it throws the error body.
|
|
56
|
+
*/
|
|
57
|
+
export declare const parseXml: (xml: string) => any;
|
|
58
|
+
/**
|
|
59
|
+
* Specifically extracts the CopyPartResult from an S3 XML response.
|
|
60
|
+
* Used during multipart copy operations or part uploads that return XML.
|
|
61
|
+
*/
|
|
62
|
+
export declare const uploadPartParser: (xml: string) => any;
|
|
63
|
+
/**
|
|
64
|
+
* Removes various encodings of double quotes from the start and end of an ETag.
|
|
65
|
+
* * @description
|
|
66
|
+
* S3-compatible storage often returns ETags wrapped in literal quotes or
|
|
67
|
+
* HTML entities. This regex-based sanitizer ensures only the raw hash remains.
|
|
68
|
+
* @param {string} [etag=''] - The raw ETag string from headers or XML.
|
|
69
|
+
* @returns {string} The cleaned ETag.
|
|
70
|
+
*/
|
|
71
|
+
export declare const sanitizeETag: (etag: string) => string;
|
|
72
|
+
//# sourceMappingURL=Mixins.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { NotificationType, NotificationOptions } from '@/types/NotificationTypes';
|
|
2
|
+
import admin from 'firebase-admin';
|
|
3
|
+
import { BatchResponse } from 'firebase-admin/lib/messaging/messaging-api';
|
|
4
|
+
export default class PushNotifier {
|
|
5
|
+
static FirebaseAdmin: typeof admin;
|
|
6
|
+
static instance: number;
|
|
7
|
+
private static rootDir;
|
|
8
|
+
constructor(path: string);
|
|
9
|
+
/**
|
|
10
|
+
* Initiate sending push notifications
|
|
11
|
+
* @param tokens firebase user tokens
|
|
12
|
+
* @param message message to send
|
|
13
|
+
* @param metadata
|
|
14
|
+
* @param options
|
|
15
|
+
*/
|
|
16
|
+
static sendNotifications(tokens: Array<string>, message: NotificationType, metadata?: any, options?: NotificationOptions): Promise<BatchResponse | undefined>;
|
|
17
|
+
static sendNotification(token: string, message: NotificationType, metadata?: any, options?: NotificationOptions): Promise<string | undefined>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=PushNotifier.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type QueryOptions = {
|
|
2
|
+
forceRefresh?: boolean;
|
|
3
|
+
paginate?: boolean;
|
|
4
|
+
limit?: number;
|
|
5
|
+
page?: number;
|
|
6
|
+
sort?: string;
|
|
7
|
+
search?: string;
|
|
8
|
+
fulltext?: boolean;
|
|
9
|
+
defaultSearchFields?: string[];
|
|
10
|
+
};
|
|
11
|
+
export type PaginatedResult<T> = {
|
|
12
|
+
rows: T[];
|
|
13
|
+
count: number;
|
|
14
|
+
meta: {
|
|
15
|
+
total: number;
|
|
16
|
+
limit: number;
|
|
17
|
+
page: number;
|
|
18
|
+
totalPages: number;
|
|
19
|
+
hasNextPage: boolean;
|
|
20
|
+
hasPrevPage: boolean;
|
|
21
|
+
sort: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
type SearchOptions = {
|
|
25
|
+
fulltext?: boolean;
|
|
26
|
+
defaultFields?: string[];
|
|
27
|
+
};
|
|
28
|
+
export declare class QueryHelper {
|
|
29
|
+
private static getFieldValue;
|
|
30
|
+
private static buildHaystack;
|
|
31
|
+
private static matchesSearch;
|
|
32
|
+
static filterBySearch<T>(items: T[], search: string, options?: SearchOptions): T[];
|
|
33
|
+
static sort<T>(items: T[], sort: string): T[];
|
|
34
|
+
static paginate<T>(items: T[], limit: number, page: number, sort: string): PaginatedResult<T>;
|
|
35
|
+
static applyQuery<T>(items: T[], options?: QueryOptions): T[] | PaginatedResult<T>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=RedisQueryHelper.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Application, Request, Response, NextFunction } from 'express';
|
|
2
|
+
export default class RouterFactory {
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param app express application instance
|
|
6
|
+
* @param pathName root path of the application
|
|
7
|
+
* @param folderName path of the routers (default: routes)
|
|
8
|
+
*/
|
|
9
|
+
static init(app: Application, pathName: string, folderName?: string, context?: string): Promise<void>;
|
|
10
|
+
static authenticate(req: Request, res: Response, next: NextFunction, grantPublicAccess?: boolean): Response<any, Record<string, any>> | undefined;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=RouterFactory.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { KafkaConfig } from "kafkajs";
|
|
2
|
+
export declare class ServeKafka {
|
|
3
|
+
private consumerPath;
|
|
4
|
+
private producerPath;
|
|
5
|
+
private config;
|
|
6
|
+
constructor(config: KafkaConfig, consumerPath?: string, producerPath?: string);
|
|
7
|
+
/**
|
|
8
|
+
* Starts all consumers by dynamically importing and initializing consumer classes.
|
|
9
|
+
*/
|
|
10
|
+
startConsumers(): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Starts all producers by dynamically importing and initializing producer classes.
|
|
13
|
+
*/
|
|
14
|
+
startProducers(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=ServeKafka.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
import { RequestUserType } from '../types/BaseModelTypes';
|
|
3
|
+
/**
|
|
4
|
+
* generate jwt token from the payload
|
|
5
|
+
* @param payload
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export declare function generate(payload: object): string;
|
|
9
|
+
export declare function verify(token: string, secret?: string): RequestUserType;
|
|
10
|
+
export declare function decode(val: string | Request): RequestUserType;
|
|
11
|
+
//# sourceMappingURL=TokenGenerator.d.ts.map
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { UploadedFile } from 'express-fileupload';
|
|
3
|
+
import * as minio from 'minio';
|
|
4
|
+
import { ApplicationOptionType } from '..';
|
|
5
|
+
import { UploadedFileType, InitUpload, UploadChunk, CompleteUploadResult, UploadTypes, UploadPart } from '@/types/UploadedFileType';
|
|
6
|
+
import { RemoveOptions } from 'minio';
|
|
7
|
+
export default class Uploader {
|
|
8
|
+
static client: minio.Client;
|
|
9
|
+
static clientEndpoint: string;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Initializes the minIO client instance
|
|
13
|
+
*/
|
|
14
|
+
static init(options: ApplicationOptionType): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* checks .env variables if properly configured
|
|
17
|
+
*/
|
|
18
|
+
static hasValidConfig(options: ApplicationOptionType): boolean;
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param bucket {string} The bucket name in minIO
|
|
22
|
+
* @param dir {string} The directory where the files are stored
|
|
23
|
+
* @param uploads {Array<UploadedFile> | UploadedFile} file(s) to be uploaded
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
static upload(bucket: string, dir: string, uploads: Array<UploadedFile> | UploadedFile): Promise<Array<UploadedFileType> | UploadedFileType>;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param bucket {string} bucket name
|
|
30
|
+
* @param file {string} file directory
|
|
31
|
+
*/
|
|
32
|
+
preview(bucket: string, file: string): Promise<void>;
|
|
33
|
+
static delete(bucketName: string, objectName: string, removeOpts?: RemoveOptions): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Permanently cancels all pending multipart uploads within a specified S3/MinIO bucket.
|
|
36
|
+
* @description
|
|
37
|
+
* This is a cleanup utility. Incomplete multipart uploads occupy storage space but are not visible as objects. This method iterates through the bucket's "incomplete" stream and issues an abort command for each. Use this to recover storage or clear stuck uploads after a service interruption.
|
|
38
|
+
* @param {string} bucketName - The unique identifier of the target MinIO bucket.
|
|
39
|
+
* @returns {Promise<void>} Resolves when the stream has finished processing all abort requests.
|
|
40
|
+
* @throws {Error} If the bucket is inaccessible or the list operation fails.
|
|
41
|
+
* @example
|
|
42
|
+
* await Uploader.clearAllMultipartUploads('temp-uploads');
|
|
43
|
+
*/
|
|
44
|
+
static clearAllMultipartUploads(bucketName: string): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Starts a new multipart upload session and registers it in the local session cache.
|
|
47
|
+
* @description
|
|
48
|
+
* This method performs two actions:
|
|
49
|
+
* 1. Requests a new Multipart Upload ID from the MinIO/S3 server.
|
|
50
|
+
* 2. Initializes an internal tracking session in `uploadSessions` for part management.
|
|
51
|
+
* @param {string} bucket - Target bucket name.
|
|
52
|
+
* @param {string} fileName - The final destination filename/path.
|
|
53
|
+
* @param {Record<string, string>} [metadata={}] - Key-value pairs for S3 metadata.
|
|
54
|
+
* - Standard headers: `Content-Type`, `Cache-Control`, etc.
|
|
55
|
+
* - Custom tags: Use `X-Amz-meta-` prefix for custom attributes.
|
|
56
|
+
* @returns {Promise<InitUpload>}
|
|
57
|
+
* Returns the internal session ID and the provider's upload ID.
|
|
58
|
+
* @throws {Error} If the connection to MinIO fails or the bucket does not exist.
|
|
59
|
+
*/
|
|
60
|
+
static initiateUpload(bucket: string, fileName: string, metadata?: Record<string, string>): Promise<InitUpload>;
|
|
61
|
+
/**
|
|
62
|
+
* Processes and uploads a single data part to an active multipart session.
|
|
63
|
+
* @description
|
|
64
|
+
* This method normalizes various input formats (Buffer, string, or Uint8Array) into a binary Buffer, dispatches the upload to MinIO via `uploadPart`, and updates the internal session state with the returned ETag.
|
|
65
|
+
* @param {string} uploadSessionId - The internal UUID generated during `initiateUpload`.
|
|
66
|
+
* @param {number} chunkNumber - The 1-based index of the part.
|
|
67
|
+
* @param {Buffer | string | Uint8Array} chunkData - The raw binary data or encoded string.
|
|
68
|
+
* @returns {Promise<UploadChunk>} Returns metadata about the uploaded part, including:
|
|
69
|
+
* - `etag`: The S3 identifier for this specific part (required for completion).
|
|
70
|
+
* - `uploadedPart`: The total count of parts successfully tracked in this session so far.
|
|
71
|
+
*/
|
|
72
|
+
static uploadChunk(uploadSessionId: string, chunkNumber: number, chunkData: Buffer | string | Uint8Array): Promise<UploadChunk>;
|
|
73
|
+
/**
|
|
74
|
+
* Finalizes the multipart upload by assembling all uploaded parts into a single object.
|
|
75
|
+
* @description
|
|
76
|
+
* This method performs the final handshake with MinIO/S3. It:
|
|
77
|
+
* 1. Retrieves and sorts the accumulated ETags by part number (mandatory for S3 compliance).
|
|
78
|
+
* 2. Signals the storage server to merge the data parts.
|
|
79
|
+
* 3. Extracts file metadata (size, mime-type) from the session.
|
|
80
|
+
* 4. Purges the internal `uploadSessions` cache to prevent memory leaks.
|
|
81
|
+
* @param {string} uploadSessionId - The internal tracking ID of the session to be closed.
|
|
82
|
+
* @returns {Promise<Object>} A curated result object containing:
|
|
83
|
+
* - `etag`: The final entity tag for the completed object.
|
|
84
|
+
* - `location`: The public/internal URL of the uploaded file.
|
|
85
|
+
* - `fileSize`: Parsed size from the 'X-Amz-meta-filesize' metadata.
|
|
86
|
+
* @throws {Error} If parts are missing, the session is not found, or S3 assembly fails.
|
|
87
|
+
*/
|
|
88
|
+
static completeUpload(uploadSessionId: string): Promise<CompleteUploadResult>;
|
|
89
|
+
/**
|
|
90
|
+
* Streams an object from storage directly to an HTTP response.
|
|
91
|
+
* @description
|
|
92
|
+
* Fetches object metadata (stat) to populate necessary download headers before
|
|
93
|
+
* piping the data stream to the client. This avoids loading the entire file
|
|
94
|
+
* into memory, making it efficient for large file transfers.
|
|
95
|
+
* * @param {Response} res - The Express/Node.js response object.
|
|
96
|
+
* @param {UploadTypes} options - Configuration object containing:
|
|
97
|
+
* - `bucket`: Target bucket name.
|
|
98
|
+
* - `objectKey`: The internal storage path (e.g., 'stream/123').
|
|
99
|
+
* - `objectName`: The "friendly" filename for the user's browser.
|
|
100
|
+
* @returns {Promise<void>} Resolves once the stream has been successfully piped.
|
|
101
|
+
* @throws {Error} If the object does not exist or metadata cannot be retrieved.
|
|
102
|
+
*/
|
|
103
|
+
static streamDownload(res: any, { bucket, objectKey, objectName }: UploadTypes): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Executes a low-level Multipart Upload Part request.
|
|
106
|
+
* * @description
|
|
107
|
+
* This is a custom wrapper around the S3/MinIO PUT Object Part API. It manually constructs the query parameters and headers required for a part upload. Crucially, it handles inconsistent server responses by attempting to extract the ETag from both the response XML body and the HTTP headers.
|
|
108
|
+
* @param {Object} partConfig - Configuration for the specific part.
|
|
109
|
+
* @param {string} partConfig.bucketName - Target bucket.
|
|
110
|
+
* @param {string} partConfig.objectName - The internal path/key of the object.
|
|
111
|
+
* @param {string} partConfig.uploadID - The ID generated by `initiateNewMultipartUpload`.
|
|
112
|
+
* @param {number} partConfig.partNumber - 1-based index of the part.
|
|
113
|
+
* @param {unknown} partConfig.headers - HTTP headers (e.g., Content-Length, Content-MD5).
|
|
114
|
+
* @param {any} [payload] - The binary data buffer for this part.
|
|
115
|
+
* @returns {Promise<UploadPart>}
|
|
116
|
+
* Returns a sanitized ETag required for the final `completeUpload` call.
|
|
117
|
+
* @throws {Error} If no ETag is found in the response or the network request fails.
|
|
118
|
+
*/
|
|
119
|
+
static uploadPart: (partConfig: {
|
|
120
|
+
bucketName: string;
|
|
121
|
+
objectName: string;
|
|
122
|
+
uploadID: string;
|
|
123
|
+
partNumber: number;
|
|
124
|
+
headers: unknown;
|
|
125
|
+
}, payload?: any) => Promise<UploadPart>;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=Uploader.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
/// <reference types="bun-types" />
|
|
3
|
+
import { ServerWebSocket } from 'bun';
|
|
4
|
+
import BaseSocketHandler from './BaseSocketHandler';
|
|
5
|
+
export default class WebSocketServer {
|
|
6
|
+
static socketHandlers: Array<{
|
|
7
|
+
path: string;
|
|
8
|
+
handler: BaseSocketHandler;
|
|
9
|
+
}>;
|
|
10
|
+
static init(port: number | undefined, dir: string, folder?: string): Array<{
|
|
11
|
+
path: string;
|
|
12
|
+
handler: BaseSocketHandler;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
static getSocketHandlers(): Array<{
|
|
19
|
+
path: string;
|
|
20
|
+
handler: BaseSocketHandler;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param path
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
static getHandler(path: string): ServerWebSocket | null;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=WebSocketServer.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ApplicationOptionType } from "@/types/ApplicationOptionType";
|
|
3
|
+
import { S3, DeleteObjectRequest } from "@aws-sdk/client-s3";
|
|
4
|
+
import { AttachmentMetadataType } from "@/types/AttachmentMetadataTypes";
|
|
5
|
+
export default class UploaderS3 {
|
|
6
|
+
static client: S3;
|
|
7
|
+
static uploadSessions: Record<string, string>;
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the S3 client instance
|
|
10
|
+
*/
|
|
11
|
+
static init(options: ApplicationOptionType): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Validates configuration options
|
|
14
|
+
*/
|
|
15
|
+
static hasValidConfig(options: ApplicationOptionType): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Lists all available S3 buckets
|
|
18
|
+
*/
|
|
19
|
+
static listBuckets(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Starts a new multipart upload session
|
|
22
|
+
* @param bucketName S3 bucket name
|
|
23
|
+
* @param key Key for the object in S3
|
|
24
|
+
*/
|
|
25
|
+
static startMultipartUpload(bucketName: string, key: string): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Uploads a file part to S3
|
|
28
|
+
* @param bucketName S3 bucket name
|
|
29
|
+
* @param key Key for the object in S3
|
|
30
|
+
* @param uploadId Multipart upload session ID
|
|
31
|
+
* @param partNumber Part number for the upload
|
|
32
|
+
* @param chunk Chunk of the file to upload
|
|
33
|
+
*/
|
|
34
|
+
static uploadPart(bucketName: string, key: string, uploadId: string, partNumber: number, chunk: Buffer): Promise<string | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Completes a multipart upload
|
|
37
|
+
* @param bucketName S3 bucket name
|
|
38
|
+
* @param key Key for the object in S3
|
|
39
|
+
* @param uploadId Multipart upload session ID
|
|
40
|
+
* @param parts List of uploaded parts
|
|
41
|
+
*/
|
|
42
|
+
static completeMultipartUpload(bucketName: string, key: string, uploadId: string, parts: {
|
|
43
|
+
PartNumber: number;
|
|
44
|
+
ETag: string;
|
|
45
|
+
}[]): Promise<AttachmentMetadataType>;
|
|
46
|
+
/**
|
|
47
|
+
* Aborts a multipart upload
|
|
48
|
+
* @param bucketName S3 bucket name
|
|
49
|
+
* @param key Key for the object in S3
|
|
50
|
+
* @param uploadId Multipart upload session ID
|
|
51
|
+
*/
|
|
52
|
+
static abortMultipartUpload(bucketName: string, key: string, uploadId: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Directly uploads a file to S3 without chunking
|
|
55
|
+
* @param bucketName S3 bucket name
|
|
56
|
+
* @param key Key for the object in S3
|
|
57
|
+
* @param fileContent The content of the file to upload
|
|
58
|
+
* @param contentType The MIME type of the file
|
|
59
|
+
*/
|
|
60
|
+
static uploadFile(bucketName: string, key: string, fileContent: Buffer | Uint8Array | Blob | string, contentType: string): Promise<AttachmentMetadataType>;
|
|
61
|
+
/**
|
|
62
|
+
* Deletes all incomplete multipart uploads in the specified bucket
|
|
63
|
+
* @param bucketName S3 bucket name
|
|
64
|
+
*/
|
|
65
|
+
static deleteIncompleteUploads(bucketName: string): Promise<void>;
|
|
66
|
+
static deleteFile(request: DeleteObjectRequest): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=uploader-s3.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ccci/micro-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
"@types/nodemailer": "^6.4.15",
|
|
24
24
|
"prettier": "^3.0.3",
|
|
25
25
|
"rimraf": "^5.0.5",
|
|
26
|
-
"typescript": "^5.2.2"
|
|
26
|
+
"typescript": "^5.2.2",
|
|
27
|
+
"vite": "^5.0.10",
|
|
28
|
+
"vite-tsconfig-paths": "^6.1.0",
|
|
29
|
+
"vitest": "^1.1.0"
|
|
27
30
|
},
|
|
28
31
|
"peerDependencies": {
|
|
29
32
|
"typescript": "^5.0.0"
|
|
@@ -45,6 +48,7 @@
|
|
|
45
48
|
"express": "^4.19.2",
|
|
46
49
|
"express-fileupload": "^1.5.0",
|
|
47
50
|
"express-list-endpoints": "^7.1.1",
|
|
51
|
+
"fast-xml-parser": "^5.3.4",
|
|
48
52
|
"firebase": "^10.13.1",
|
|
49
53
|
"firebase-admin": "^12.4.0",
|
|
50
54
|
"handlebars": "^4.7.8",
|
|
@@ -55,6 +59,7 @@
|
|
|
55
59
|
"nodemailer": "^6.9.13",
|
|
56
60
|
"pg": "^8.11.5",
|
|
57
61
|
"pg-hstore": "^2.3.4",
|
|
62
|
+
"redis": "^5.11.0",
|
|
58
63
|
"sequelize": "^6.37.3",
|
|
59
64
|
"socket.io": "^4.7.5",
|
|
60
65
|
"winston": "^3.13.0"
|