saas-backend-kit 1.0.0 → 1.0.1
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 +117 -370
- package/copy-dts.js +59 -0
- package/dist/auth/index.js +6 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +6 -1
- package/dist/auth/index.mjs.map +1 -1
- package/dist/config/index.js +6 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/index.mjs +6 -1
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +184 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +183 -2
- package/dist/index.mjs.map +1 -1
- package/dist/logger/index.js +6 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/logger/index.mjs +6 -1
- package/dist/logger/index.mjs.map +1 -1
- package/dist/notifications/index.js +6 -1
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/index.mjs +6 -1
- package/dist/notifications/index.mjs.map +1 -1
- package/dist/queue/index.js +6 -1
- package/dist/queue/index.js.map +1 -1
- package/dist/queue/index.mjs +6 -1
- package/dist/queue/index.mjs.map +1 -1
- package/dist/rate-limit/index.js +6 -1
- package/dist/rate-limit/index.js.map +1 -1
- package/dist/rate-limit/index.mjs +6 -1
- package/dist/rate-limit/index.mjs.map +1 -1
- package/dist/upload/index.d.ts +57 -0
- package/dist/upload/index.js +344 -0
- package/dist/upload/index.js.map +1 -0
- package/dist/upload/index.mjs +334 -0
- package/dist/upload/index.mjs.map +1 -0
- package/package.json +12 -2
- package/saas-banner.svg +239 -0
- package/src/config/index.ts +5 -0
- package/src/index.ts +2 -0
- package/src/upload/index.ts +268 -0
- package/tsup.config.ts +2 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@ var jwt = require('jsonwebtoken');
|
|
|
7
7
|
var bcrypt = require('bcryptjs');
|
|
8
8
|
var nodemailer = require('nodemailer');
|
|
9
9
|
var express = require('express');
|
|
10
|
+
var clientS3 = require('@aws-sdk/client-s3');
|
|
11
|
+
var s3RequestPresigner = require('@aws-sdk/s3-request-presigner');
|
|
10
12
|
|
|
11
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
14
|
|
|
@@ -68,7 +70,12 @@ var init_config = __esm({
|
|
|
68
70
|
SLACK_WEBHOOK_URL: zod.z.string().optional(),
|
|
69
71
|
RATE_LIMIT_WINDOW: zod.z.string().default("1m"),
|
|
70
72
|
RATE_LIMIT_LIMIT: zod.z.string().default("100"),
|
|
71
|
-
LOG_LEVEL: zod.z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).default("info")
|
|
73
|
+
LOG_LEVEL: zod.z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).default("info"),
|
|
74
|
+
AWS_REGION: zod.z.string().default("us-east-1"),
|
|
75
|
+
AWS_ACCESS_KEY_ID: zod.z.string().optional(),
|
|
76
|
+
AWS_SECRET_ACCESS_KEY: zod.z.string().optional(),
|
|
77
|
+
AWS_S3_BUCKET: zod.z.string().optional(),
|
|
78
|
+
AWS_ENDPOINT: zod.z.string().optional()
|
|
72
79
|
});
|
|
73
80
|
ConfigManager = class {
|
|
74
81
|
config = null;
|
|
@@ -1154,6 +1161,180 @@ express.Response.prototype.paginated = function(data, page, limit, total) {
|
|
|
1154
1161
|
};
|
|
1155
1162
|
var response = ResponseHelper;
|
|
1156
1163
|
|
|
1164
|
+
// src/upload/index.ts
|
|
1165
|
+
init_config();
|
|
1166
|
+
init_logger();
|
|
1167
|
+
var S3Service = class {
|
|
1168
|
+
client = null;
|
|
1169
|
+
bucket;
|
|
1170
|
+
initialized = false;
|
|
1171
|
+
constructor() {
|
|
1172
|
+
this.bucket = "";
|
|
1173
|
+
}
|
|
1174
|
+
initialize(config2) {
|
|
1175
|
+
this.client = new clientS3.S3Client({
|
|
1176
|
+
region: config2.region || "us-east-1",
|
|
1177
|
+
credentials: config2.accessKeyId && config2.secretAccessKey ? {
|
|
1178
|
+
accessKeyId: config2.accessKeyId,
|
|
1179
|
+
secretAccessKey: config2.secretAccessKey
|
|
1180
|
+
} : void 0,
|
|
1181
|
+
endpoint: config2.endpoint,
|
|
1182
|
+
forcePathStyle: config2.forcePathStyle || false
|
|
1183
|
+
});
|
|
1184
|
+
this.bucket = config2.bucket;
|
|
1185
|
+
this.initialized = true;
|
|
1186
|
+
exports.logger.info("S3 service initialized", { bucket: this.bucket });
|
|
1187
|
+
}
|
|
1188
|
+
isInitialized() {
|
|
1189
|
+
return this.initialized;
|
|
1190
|
+
}
|
|
1191
|
+
ensureInitialized() {
|
|
1192
|
+
if (!this.initialized) {
|
|
1193
|
+
const region = exports.config.get("AWS_REGION") || "us-east-1";
|
|
1194
|
+
const bucket = exports.config.get("AWS_S3_BUCKET") || "";
|
|
1195
|
+
this.initialize({
|
|
1196
|
+
region,
|
|
1197
|
+
accessKeyId: exports.config.get("AWS_ACCESS_KEY_ID"),
|
|
1198
|
+
secretAccessKey: exports.config.get("AWS_SECRET_ACCESS_KEY"),
|
|
1199
|
+
bucket,
|
|
1200
|
+
endpoint: exports.config.get("AWS_ENDPOINT")
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
async upload(file, options = {}) {
|
|
1205
|
+
this.ensureInitialized();
|
|
1206
|
+
const key = options.key || this.generateKey();
|
|
1207
|
+
const contentType = options.contentType || this.guessContentType(key);
|
|
1208
|
+
const command = new clientS3.PutObjectCommand({
|
|
1209
|
+
Bucket: this.bucket,
|
|
1210
|
+
Key: key,
|
|
1211
|
+
Body: file,
|
|
1212
|
+
ContentType: contentType,
|
|
1213
|
+
Metadata: options.metadata
|
|
1214
|
+
});
|
|
1215
|
+
await this.client.send(command);
|
|
1216
|
+
const url = await this.getSignedUrl(key, { expiresIn: options.expiresIn || 3600 });
|
|
1217
|
+
exports.logger.info("File uploaded to S3", { key, bucket: this.bucket, contentType });
|
|
1218
|
+
return {
|
|
1219
|
+
key,
|
|
1220
|
+
url,
|
|
1221
|
+
bucket: this.bucket,
|
|
1222
|
+
contentType
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
async uploadImage(file, filename, options = {}) {
|
|
1226
|
+
const key = options.key || `images/${Date.now()}-${filename}`;
|
|
1227
|
+
return this.upload(file, {
|
|
1228
|
+
...options,
|
|
1229
|
+
key,
|
|
1230
|
+
contentType: options.contentType || this.getImageContentType(filename)
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
async uploadVideo(file, filename, options = {}) {
|
|
1234
|
+
const key = options.key || `videos/${Date.now()}-${filename}`;
|
|
1235
|
+
return this.upload(file, {
|
|
1236
|
+
...options,
|
|
1237
|
+
key,
|
|
1238
|
+
contentType: options.contentType || this.getVideoContentType(filename)
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
async delete(key) {
|
|
1242
|
+
this.ensureInitialized();
|
|
1243
|
+
const command = new clientS3.DeleteObjectCommand({
|
|
1244
|
+
Bucket: this.bucket,
|
|
1245
|
+
Key: key
|
|
1246
|
+
});
|
|
1247
|
+
await this.client.send(command);
|
|
1248
|
+
exports.logger.info("File deleted from S3", { key, bucket: this.bucket });
|
|
1249
|
+
}
|
|
1250
|
+
async getSignedUrl(key, options = {}) {
|
|
1251
|
+
this.ensureInitialized();
|
|
1252
|
+
const command = new clientS3.GetObjectCommand({
|
|
1253
|
+
Bucket: this.bucket,
|
|
1254
|
+
Key: key
|
|
1255
|
+
});
|
|
1256
|
+
return s3RequestPresigner.getSignedUrl(this.client, command, {
|
|
1257
|
+
expiresIn: options.expiresIn || 3600
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
async getPublicUrl(key) {
|
|
1261
|
+
return `https://${this.bucket}.s3.${exports.config.get("AWS_REGION") || "us-east-1"}.amazonaws.com/${key}`;
|
|
1262
|
+
}
|
|
1263
|
+
async listFiles(prefix, maxKeys = 1e3) {
|
|
1264
|
+
this.ensureInitialized();
|
|
1265
|
+
const command = new clientS3.ListObjectsV2Command({
|
|
1266
|
+
Bucket: this.bucket,
|
|
1267
|
+
Prefix: prefix,
|
|
1268
|
+
MaxKeys: maxKeys
|
|
1269
|
+
});
|
|
1270
|
+
const response2 = await this.client.send(command);
|
|
1271
|
+
return (response2.Contents || []).map((item) => ({
|
|
1272
|
+
key: item.Key || "",
|
|
1273
|
+
lastModified: item.LastModified,
|
|
1274
|
+
size: item.Size
|
|
1275
|
+
}));
|
|
1276
|
+
}
|
|
1277
|
+
generateKey() {
|
|
1278
|
+
const timestamp = Date.now();
|
|
1279
|
+
const random = Math.random().toString(36).substring(2, 15);
|
|
1280
|
+
return `uploads/${timestamp}-${random}`;
|
|
1281
|
+
}
|
|
1282
|
+
guessContentType(key) {
|
|
1283
|
+
const ext = key.split(".").pop()?.toLowerCase();
|
|
1284
|
+
const contentTypes = {
|
|
1285
|
+
jpg: "image/jpeg",
|
|
1286
|
+
jpeg: "image/jpeg",
|
|
1287
|
+
png: "image/png",
|
|
1288
|
+
gif: "image/gif",
|
|
1289
|
+
webp: "image/webp",
|
|
1290
|
+
svg: "image/svg+xml",
|
|
1291
|
+
mp4: "video/mp4",
|
|
1292
|
+
webm: "video/webm",
|
|
1293
|
+
mov: "video/quicktime",
|
|
1294
|
+
avi: "video/x-msvideo",
|
|
1295
|
+
pdf: "application/pdf",
|
|
1296
|
+
json: "application/json",
|
|
1297
|
+
txt: "text/plain"
|
|
1298
|
+
};
|
|
1299
|
+
return contentTypes[ext || ""] || "application/octet-stream";
|
|
1300
|
+
}
|
|
1301
|
+
getImageContentType(filename) {
|
|
1302
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
1303
|
+
const imageTypes = {
|
|
1304
|
+
jpg: "image/jpeg",
|
|
1305
|
+
jpeg: "image/jpeg",
|
|
1306
|
+
png: "image/png",
|
|
1307
|
+
gif: "image/gif",
|
|
1308
|
+
webp: "image/webp",
|
|
1309
|
+
svg: "image/svg+xml"
|
|
1310
|
+
};
|
|
1311
|
+
return imageTypes[ext || ""] || "image/jpeg";
|
|
1312
|
+
}
|
|
1313
|
+
getVideoContentType(filename) {
|
|
1314
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
1315
|
+
const videoTypes = {
|
|
1316
|
+
mp4: "video/mp4",
|
|
1317
|
+
webm: "video/webm",
|
|
1318
|
+
mov: "video/quicktime",
|
|
1319
|
+
avi: "video/x-msvideo",
|
|
1320
|
+
mkv: "video/x-matroska",
|
|
1321
|
+
ogv: "video/ogg"
|
|
1322
|
+
};
|
|
1323
|
+
return videoTypes[ext || ""] || "video/mp4";
|
|
1324
|
+
}
|
|
1325
|
+
};
|
|
1326
|
+
var s3Service = new S3Service();
|
|
1327
|
+
var upload = {
|
|
1328
|
+
initialize: (config2) => s3Service.initialize(config2),
|
|
1329
|
+
file: (file, options) => s3Service.upload(file, options),
|
|
1330
|
+
image: (file, filename, options) => s3Service.uploadImage(file, filename, options),
|
|
1331
|
+
video: (file, filename, options) => s3Service.uploadVideo(file, filename, options),
|
|
1332
|
+
delete: (key) => s3Service.delete(key),
|
|
1333
|
+
getSignedUrl: (key, options) => s3Service.getSignedUrl(key, options),
|
|
1334
|
+
getPublicUrl: (key) => s3Service.getPublicUrl(key),
|
|
1335
|
+
listFiles: (prefix, maxKeys) => s3Service.listFiles(prefix, maxKeys)
|
|
1336
|
+
};
|
|
1337
|
+
|
|
1157
1338
|
// src/plugin.ts
|
|
1158
1339
|
init_logger();
|
|
1159
1340
|
init_config();
|
|
@@ -1299,5 +1480,7 @@ exports.notification = notification;
|
|
|
1299
1480
|
exports.notify = notify;
|
|
1300
1481
|
exports.rateLimit = rateLimit;
|
|
1301
1482
|
exports.response = response;
|
|
1483
|
+
exports.s3Service = s3Service;
|
|
1484
|
+
exports.upload = upload;
|
|
1302
1485
|
//# sourceMappingURL=index.js.map
|
|
1303
1486
|
//# sourceMappingURL=index.js.map
|