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