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.
Files changed (42) hide show
  1. package/README.md +117 -370
  2. package/copy-dts.js +59 -0
  3. package/dist/auth/index.js +6 -1
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/auth/index.mjs +6 -1
  6. package/dist/auth/index.mjs.map +1 -1
  7. package/dist/config/index.js +6 -1
  8. package/dist/config/index.js.map +1 -1
  9. package/dist/config/index.mjs +6 -1
  10. package/dist/config/index.mjs.map +1 -1
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.js +184 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +183 -2
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/logger/index.js +6 -1
  17. package/dist/logger/index.js.map +1 -1
  18. package/dist/logger/index.mjs +6 -1
  19. package/dist/logger/index.mjs.map +1 -1
  20. package/dist/notifications/index.js +6 -1
  21. package/dist/notifications/index.js.map +1 -1
  22. package/dist/notifications/index.mjs +6 -1
  23. package/dist/notifications/index.mjs.map +1 -1
  24. package/dist/queue/index.js +6 -1
  25. package/dist/queue/index.js.map +1 -1
  26. package/dist/queue/index.mjs +6 -1
  27. package/dist/queue/index.mjs.map +1 -1
  28. package/dist/rate-limit/index.js +6 -1
  29. package/dist/rate-limit/index.js.map +1 -1
  30. package/dist/rate-limit/index.mjs +6 -1
  31. package/dist/rate-limit/index.mjs.map +1 -1
  32. package/dist/upload/index.d.ts +57 -0
  33. package/dist/upload/index.js +344 -0
  34. package/dist/upload/index.js.map +1 -0
  35. package/dist/upload/index.mjs +334 -0
  36. package/dist/upload/index.mjs.map +1 -0
  37. package/package.json +12 -2
  38. package/saas-banner.svg +239 -0
  39. package/src/config/index.ts +5 -0
  40. package/src/index.ts +2 -0
  41. package/src/upload/index.ts +268 -0
  42. 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