@exyconn/common 2.3.2 → 2.3.3
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 -12
- package/dist/client/http/index.d.mts +217 -49
- package/dist/client/http/index.d.ts +217 -49
- package/dist/client/http/index.js +473 -94
- package/dist/client/http/index.js.map +1 -1
- package/dist/client/http/index.mjs +441 -84
- package/dist/client/http/index.mjs.map +1 -1
- package/dist/client/index.d.mts +3 -3
- package/dist/client/index.d.ts +3 -3
- package/dist/client/index.js +481 -319
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +449 -290
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/utils/index.d.mts +3 -279
- package/dist/client/utils/index.d.ts +3 -279
- package/dist/{index-DuxL84IW.d.mts → index-BZf42T3R.d.mts} +39 -39
- package/dist/{index-D9a9oxQy.d.ts → index-CF0D8PGE.d.ts} +39 -39
- package/dist/{index-D3yCCjBZ.d.mts → index-Ckhm_HaX.d.mts} +21 -2
- package/dist/{index-01hoqibP.d.ts → index-br6POSyA.d.ts} +21 -2
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1122 -329
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1134 -341
- package/dist/index.mjs.map +1 -1
- package/dist/packageCheck-B_qfsD6R.d.ts +280 -0
- package/dist/packageCheck-C2_FT_Rl.d.mts +280 -0
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +631 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +625 -2
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/middleware/index.d.mts +283 -2
- package/dist/server/middleware/index.d.ts +283 -2
- package/dist/server/middleware/index.js +761 -0
- package/dist/server/middleware/index.js.map +1 -1
- package/dist/server/middleware/index.mjs +751 -1
- package/dist/server/middleware/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import winston from 'winston';
|
|
2
2
|
import DailyRotateFile from 'winston-daily-rotate-file';
|
|
3
3
|
import path, { resolve } from 'path';
|
|
4
|
-
import mongoose from 'mongoose';
|
|
4
|
+
import mongoose, { Types } from 'mongoose';
|
|
5
5
|
import jwt from 'jsonwebtoken';
|
|
6
6
|
import { existsSync, readFileSync } from 'fs';
|
|
7
7
|
import rateLimit from 'express-rate-limit';
|
|
@@ -10,7 +10,7 @@ import { createContext, useState, useCallback, useMemo, useRef, useEffect, useCo
|
|
|
10
10
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
11
11
|
import * as Yup from 'yup';
|
|
12
12
|
import { Formik, Form, Field, ErrorMessage } from 'formik';
|
|
13
|
-
import { subYears, subWeeks, subMonths, subMinutes, subHours, subDays, startOfYear, startOfWeek, startOfMonth, startOfDay
|
|
13
|
+
import { subYears, subWeeks, subMonths, subMinutes, subHours, subDays, startOfYear, startOfWeek, startOfMonth, startOfDay, setSeconds, setMinutes, setHours, parseISO, isYesterday, isValid, isTomorrow, isToday, isThisYear, isThisWeek, isThisMonth, isSameYear, isSameWeek, isSameMonth, isSameDay, isPast, isFuture, isEqual, isBefore, isAfter, intervalToDuration, getYear, getSeconds, getMonth, getMinutes, getHours, getDay, getDate, formatRelative, formatDuration, formatDistanceToNow, formatDistance, format, endOfYear, endOfWeek, endOfMonth, endOfDay, eachWeekOfInterval, eachMonthOfInterval, eachDayOfInterval, differenceInYears, differenceInWeeks, differenceInSeconds, differenceInMonths, differenceInMinutes, differenceInHours, differenceInDays, addYears, addWeeks, addMonths, addMinutes, addHours, addDays } from 'date-fns';
|
|
14
14
|
import { toZonedTime, fromZonedTime, formatInTimeZone } from 'date-fns-tz';
|
|
15
15
|
|
|
16
16
|
var __defProp = Object.defineProperty;
|
|
@@ -42,6 +42,7 @@ __export(server_exports, {
|
|
|
42
42
|
authenticateJWT: () => authenticateJWT,
|
|
43
43
|
badRequestResponse: () => badRequestResponse,
|
|
44
44
|
buildConfig: () => buildConfig,
|
|
45
|
+
buildDeleteFilter: () => buildDeleteFilter,
|
|
45
46
|
buildFilter: () => buildFilter,
|
|
46
47
|
buildPagination: () => buildPagination,
|
|
47
48
|
buildPaginationMeta: () => buildPaginationMeta,
|
|
@@ -52,12 +53,15 @@ __export(server_exports, {
|
|
|
52
53
|
createApiKeyGenerator: () => createApiKeyGenerator,
|
|
53
54
|
createApiRateLimiter: () => createApiRateLimiter,
|
|
54
55
|
createBrandCorsOptions: () => createBrandCorsOptions,
|
|
56
|
+
createBulkDeleteHandler: () => createBulkDeleteHandler,
|
|
55
57
|
createConfig: () => createConfig,
|
|
56
58
|
createCorsOptions: () => createCorsOptions,
|
|
59
|
+
createCrudControllers: () => createCrudControllers,
|
|
57
60
|
createDdosRateLimiter: () => createDdosRateLimiter,
|
|
58
61
|
createLogger: () => createLogger,
|
|
59
62
|
createMorganStream: () => createMorganStream,
|
|
60
63
|
createMultiBrandCorsOptions: () => createMultiBrandCorsOptions,
|
|
64
|
+
createPaginationMiddleware: () => createPaginationMiddleware,
|
|
61
65
|
createPrefixedKeyGenerator: () => createPrefixedKeyGenerator,
|
|
62
66
|
createRateLimiter: () => createRateLimiter,
|
|
63
67
|
createStandardRateLimiter: () => createStandardRateLimiter,
|
|
@@ -70,6 +74,7 @@ __export(server_exports, {
|
|
|
70
74
|
errorResponse: () => errorResponse,
|
|
71
75
|
extractColumns: () => extractColumns,
|
|
72
76
|
extractOrganization: () => extractOrganization,
|
|
77
|
+
extractSchemaMeta: () => extractSchemaMeta,
|
|
73
78
|
forbiddenResponse: () => forbiddenResponse,
|
|
74
79
|
formatPackageCheckResult: () => formatPackageCheckResult,
|
|
75
80
|
generateNcuCommand: () => generateNcuCommand,
|
|
@@ -84,8 +89,11 @@ __export(server_exports, {
|
|
|
84
89
|
omitFields: () => omitFields,
|
|
85
90
|
optionalAuthenticateJWT: () => optionalAuthenticateJWT,
|
|
86
91
|
packageCheckServer: () => packageCheckServer,
|
|
92
|
+
parseBulkDelete: () => parseBulkDelete,
|
|
87
93
|
pickFields: () => pickFields,
|
|
88
94
|
printPackageCheckSummary: () => printPackageCheckSummary,
|
|
95
|
+
queryPagination: () => queryPagination,
|
|
96
|
+
queryParser: () => queryParser,
|
|
89
97
|
rateLimitResponse: () => rateLimitResponse,
|
|
90
98
|
rateLimiter: () => rateLimiter,
|
|
91
99
|
requireOrganization: () => requireOrganization,
|
|
@@ -379,37 +387,37 @@ var defaultOptions = {
|
|
|
379
387
|
retryReads: true,
|
|
380
388
|
w: "majority"
|
|
381
389
|
};
|
|
382
|
-
var connectDB = async (mongoUri, options = {},
|
|
390
|
+
var connectDB = async (mongoUri, options = {}, logger3) => {
|
|
383
391
|
if (mongoose.connection.readyState === 1) {
|
|
384
|
-
|
|
392
|
+
logger3?.info("Database already connected, reusing connection");
|
|
385
393
|
return mongoose;
|
|
386
394
|
}
|
|
387
395
|
const finalOptions = { ...defaultOptions, ...options };
|
|
388
396
|
try {
|
|
389
397
|
await mongoose.connect(mongoUri, finalOptions);
|
|
390
|
-
|
|
398
|
+
logger3?.info("MongoDB connected successfully");
|
|
391
399
|
mongoose.connection.on("error", (err) => {
|
|
392
|
-
|
|
400
|
+
logger3?.error("MongoDB connection error", err);
|
|
393
401
|
});
|
|
394
402
|
mongoose.connection.on("disconnected", () => {
|
|
395
|
-
|
|
403
|
+
logger3?.info("MongoDB disconnected");
|
|
396
404
|
});
|
|
397
405
|
mongoose.connection.on("reconnected", () => {
|
|
398
|
-
|
|
406
|
+
logger3?.info("MongoDB reconnected");
|
|
399
407
|
});
|
|
400
408
|
return mongoose;
|
|
401
409
|
} catch (error) {
|
|
402
410
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
403
|
-
|
|
411
|
+
logger3?.error("MongoDB connection failed", { error: errorMessage });
|
|
404
412
|
throw error;
|
|
405
413
|
}
|
|
406
414
|
};
|
|
407
|
-
var disconnectDB = async (
|
|
415
|
+
var disconnectDB = async (logger3) => {
|
|
408
416
|
try {
|
|
409
417
|
await mongoose.disconnect();
|
|
410
|
-
|
|
418
|
+
logger3?.info("MongoDB disconnected successfully");
|
|
411
419
|
} catch (error) {
|
|
412
|
-
|
|
420
|
+
logger3?.error("Error disconnecting from MongoDB", error);
|
|
413
421
|
throw error;
|
|
414
422
|
}
|
|
415
423
|
};
|
|
@@ -514,6 +522,629 @@ var requireOrganization = (req, res, next) => {
|
|
|
514
522
|
next();
|
|
515
523
|
};
|
|
516
524
|
|
|
525
|
+
// src/server/middleware/queryParser.middleware.ts
|
|
526
|
+
var queryParser = (req, _, next) => {
|
|
527
|
+
const { page, limit, sort, sortBy, sortOrder, search, filter, ...otherParams } = req.query;
|
|
528
|
+
const parsed = {
|
|
529
|
+
page: Math.max(Number(page) || 1, 1),
|
|
530
|
+
limit: Math.min(Number(limit) || 10, 100),
|
|
531
|
+
filter: {}
|
|
532
|
+
};
|
|
533
|
+
if (typeof sort === "string") {
|
|
534
|
+
const [field, order] = sort.split(":");
|
|
535
|
+
parsed.sort = {
|
|
536
|
+
field,
|
|
537
|
+
order: order === "asc" ? "asc" : "desc"
|
|
538
|
+
};
|
|
539
|
+
} else if (typeof sortBy === "string") {
|
|
540
|
+
parsed.sort = {
|
|
541
|
+
field: sortBy,
|
|
542
|
+
order: sortOrder === "asc" ? "asc" : "desc"
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
if (typeof search === "string") {
|
|
546
|
+
parsed.search = search;
|
|
547
|
+
}
|
|
548
|
+
if (typeof filter === "object" && filter !== null) {
|
|
549
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
550
|
+
if (value !== "all") {
|
|
551
|
+
parsed.filter[key] = value;
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
Object.entries(otherParams).forEach(([key, value]) => {
|
|
556
|
+
if (typeof value === "string" && value !== "all" && !["page", "limit", "sort", "sortBy", "sortOrder", "search"].includes(key)) {
|
|
557
|
+
parsed.filter[key] = value;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
req.parsedQuery = parsed;
|
|
561
|
+
next();
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// src/server/middleware/utils/schemaMeta.util.ts
|
|
565
|
+
var getZodTypeName = (schema) => {
|
|
566
|
+
const typeName = schema._def?.typeName;
|
|
567
|
+
switch (typeName) {
|
|
568
|
+
case "ZodString":
|
|
569
|
+
return "string";
|
|
570
|
+
case "ZodNumber":
|
|
571
|
+
return "number";
|
|
572
|
+
case "ZodBoolean":
|
|
573
|
+
return "boolean";
|
|
574
|
+
case "ZodDate":
|
|
575
|
+
return "date";
|
|
576
|
+
case "ZodArray":
|
|
577
|
+
return "array";
|
|
578
|
+
case "ZodObject":
|
|
579
|
+
return "object";
|
|
580
|
+
case "ZodOptional":
|
|
581
|
+
case "ZodNullable":
|
|
582
|
+
return schema._def?.innerType ? getZodTypeName(schema._def.innerType) : "unknown";
|
|
583
|
+
case "ZodDefault":
|
|
584
|
+
return schema._def?.innerType ? getZodTypeName(schema._def.innerType) : "unknown";
|
|
585
|
+
case "ZodEnum":
|
|
586
|
+
return "enum";
|
|
587
|
+
case "ZodUnion":
|
|
588
|
+
return "union";
|
|
589
|
+
default:
|
|
590
|
+
return "unknown";
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
var isZodRequired = (schema) => {
|
|
594
|
+
const typeName = schema._def?.typeName;
|
|
595
|
+
return typeName !== "ZodOptional" && typeName !== "ZodNullable";
|
|
596
|
+
};
|
|
597
|
+
var extractSchemaMeta = (model, zodSchema) => {
|
|
598
|
+
const columns = [];
|
|
599
|
+
if (zodSchema && zodSchema.shape) {
|
|
600
|
+
const shape = zodSchema.shape;
|
|
601
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
602
|
+
if (key.startsWith("_")) continue;
|
|
603
|
+
columns.push({
|
|
604
|
+
name: key,
|
|
605
|
+
datatype: getZodTypeName(value),
|
|
606
|
+
required: isZodRequired(value)
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
return columns;
|
|
610
|
+
}
|
|
611
|
+
try {
|
|
612
|
+
const schema = model.schema;
|
|
613
|
+
const paths = schema.paths;
|
|
614
|
+
for (const [key, pathInfo] of Object.entries(paths)) {
|
|
615
|
+
if (key.startsWith("_") || key === "__v") continue;
|
|
616
|
+
const schemaType = pathInfo;
|
|
617
|
+
columns.push({
|
|
618
|
+
name: key,
|
|
619
|
+
datatype: (schemaType.instance || "unknown").toLowerCase(),
|
|
620
|
+
required: schemaType.isRequired || false
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
} catch {
|
|
624
|
+
}
|
|
625
|
+
return columns;
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
// src/server/middleware/pagination.middleware.ts
|
|
629
|
+
var queryPagination = (model, options = {}, withOrgId = true) => {
|
|
630
|
+
return async (req, res, next) => {
|
|
631
|
+
try {
|
|
632
|
+
const { page, limit, sort, search, filter } = req.parsedQuery;
|
|
633
|
+
const query = {};
|
|
634
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
635
|
+
if (options.regexFilterFields?.includes(key)) {
|
|
636
|
+
query[key] = { $regex: value, $options: "i" };
|
|
637
|
+
} else {
|
|
638
|
+
query[key] = value;
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
const organizationId = req.headers["x-organization-id"];
|
|
642
|
+
if (organizationId && typeof organizationId === "string" && withOrgId) {
|
|
643
|
+
query.organizationId = organizationId;
|
|
644
|
+
}
|
|
645
|
+
if (search && options.searchFields?.length) {
|
|
646
|
+
query.$or = options.searchFields.map((field) => ({
|
|
647
|
+
[field]: { $regex: search, $options: "i" }
|
|
648
|
+
}));
|
|
649
|
+
}
|
|
650
|
+
const sortQuery = sort ? { [sort.field]: sort.order } : { createdAt: "desc" };
|
|
651
|
+
const skip = (page - 1) * limit;
|
|
652
|
+
const [data, total] = await Promise.all([
|
|
653
|
+
model.find(query).sort(sortQuery).skip(skip).limit(limit),
|
|
654
|
+
model.countDocuments(query)
|
|
655
|
+
]);
|
|
656
|
+
res.paginatedResult = {
|
|
657
|
+
data,
|
|
658
|
+
meta: {
|
|
659
|
+
page,
|
|
660
|
+
limit,
|
|
661
|
+
total,
|
|
662
|
+
totalPages: Math.ceil(total / limit)
|
|
663
|
+
},
|
|
664
|
+
columns: extractSchemaMeta(model, options.validatorSchema)
|
|
665
|
+
};
|
|
666
|
+
next();
|
|
667
|
+
} catch (error) {
|
|
668
|
+
next(error);
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
var isZodError = (error) => {
|
|
673
|
+
return error !== null && typeof error === "object" && "errors" in error && Array.isArray(error.errors);
|
|
674
|
+
};
|
|
675
|
+
var getOrgId = (req, orgField = "organizationId") => {
|
|
676
|
+
const orgReq = req;
|
|
677
|
+
return orgReq.organizationId || req.headers["x-organization-id"] || req.query[orgField];
|
|
678
|
+
};
|
|
679
|
+
var buildOrgFilter = (req, config) => {
|
|
680
|
+
const filter = {};
|
|
681
|
+
if (config.withOrganization !== false) {
|
|
682
|
+
const orgId = getOrgId(req, config.orgField);
|
|
683
|
+
if (orgId) {
|
|
684
|
+
filter[config.orgField || "organizationId"] = orgId;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return filter;
|
|
688
|
+
};
|
|
689
|
+
var formatZodError = (error) => {
|
|
690
|
+
return error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
691
|
+
};
|
|
692
|
+
function createCrudControllers(config) {
|
|
693
|
+
const {
|
|
694
|
+
model,
|
|
695
|
+
resourceName,
|
|
696
|
+
createSchema,
|
|
697
|
+
updateSchema,
|
|
698
|
+
searchFields = [],
|
|
699
|
+
regexFilterFields = [],
|
|
700
|
+
withOrganization = true,
|
|
701
|
+
orgField = "organizationId",
|
|
702
|
+
transformCreate,
|
|
703
|
+
transformUpdate,
|
|
704
|
+
afterCreate,
|
|
705
|
+
afterUpdate,
|
|
706
|
+
afterDelete,
|
|
707
|
+
excludeFields = [],
|
|
708
|
+
populateFields = [],
|
|
709
|
+
buildQuery
|
|
710
|
+
} = config;
|
|
711
|
+
const getAll = async (req, res, _next) => {
|
|
712
|
+
try {
|
|
713
|
+
const paginatedRes = res;
|
|
714
|
+
if (paginatedRes.paginatedResult) {
|
|
715
|
+
successResponse(res, paginatedRes.paginatedResult, `${resourceName} list fetched successfully`);
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const page = parseInt(req.query.page) || 1;
|
|
719
|
+
const limit = parseInt(req.query.limit) || 10;
|
|
720
|
+
const sortField = req.query.sortBy || "createdAt";
|
|
721
|
+
const sortOrder = req.query.sortOrder || "desc";
|
|
722
|
+
const search = req.query.search;
|
|
723
|
+
let query = {};
|
|
724
|
+
if (withOrganization) {
|
|
725
|
+
const orgId = getOrgId(req, orgField);
|
|
726
|
+
if (orgId) {
|
|
727
|
+
query[orgField] = orgId;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (search && searchFields.length > 0) {
|
|
731
|
+
query.$or = searchFields.map((field) => ({
|
|
732
|
+
[field]: { $regex: search, $options: "i" }
|
|
733
|
+
}));
|
|
734
|
+
}
|
|
735
|
+
const filterableParams = Object.keys(req.query).filter(
|
|
736
|
+
(key) => !["page", "limit", "sortBy", "sortOrder", "search"].includes(key)
|
|
737
|
+
);
|
|
738
|
+
filterableParams.forEach((key) => {
|
|
739
|
+
const value = req.query[key];
|
|
740
|
+
if (value !== void 0 && value !== "" && value !== "all") {
|
|
741
|
+
if (regexFilterFields.includes(key)) {
|
|
742
|
+
query[key] = { $regex: value, $options: "i" };
|
|
743
|
+
} else {
|
|
744
|
+
query[key] = value;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
if (buildQuery) {
|
|
749
|
+
query = buildQuery(req, query);
|
|
750
|
+
}
|
|
751
|
+
const sortQuery = { [sortField]: sortOrder };
|
|
752
|
+
const skip = (page - 1) * limit;
|
|
753
|
+
let projection = {};
|
|
754
|
+
if (excludeFields.length > 0) {
|
|
755
|
+
projection = excludeFields.reduce(
|
|
756
|
+
(acc, field) => ({ ...acc, [field]: 0 }),
|
|
757
|
+
{}
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
let dbQuery = model.find(query, projection);
|
|
761
|
+
if (populateFields.length > 0) {
|
|
762
|
+
populateFields.forEach((field) => {
|
|
763
|
+
dbQuery = dbQuery.populate(field);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
const [data, total] = await Promise.all([
|
|
767
|
+
dbQuery.sort(sortQuery).skip(skip).limit(limit),
|
|
768
|
+
model.countDocuments(query)
|
|
769
|
+
]);
|
|
770
|
+
successResponse(
|
|
771
|
+
res,
|
|
772
|
+
{
|
|
773
|
+
data,
|
|
774
|
+
meta: {
|
|
775
|
+
page,
|
|
776
|
+
limit,
|
|
777
|
+
total,
|
|
778
|
+
totalPages: Math.ceil(total / limit)
|
|
779
|
+
},
|
|
780
|
+
columns: extractSchemaMeta(model, createSchema)
|
|
781
|
+
},
|
|
782
|
+
`${resourceName} list fetched successfully`
|
|
783
|
+
);
|
|
784
|
+
} catch (error) {
|
|
785
|
+
logger.error(`Error in getAll ${resourceName}`, {
|
|
786
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
787
|
+
});
|
|
788
|
+
errorResponse(res, `Failed to fetch ${resourceName.toLowerCase()} list`);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
const getById = async (req, res, _next) => {
|
|
792
|
+
try {
|
|
793
|
+
const { id } = req.params;
|
|
794
|
+
if (!id || !Types.ObjectId.isValid(id)) {
|
|
795
|
+
badRequestResponse(res, "Invalid ID format");
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const query = {
|
|
799
|
+
_id: new Types.ObjectId(id),
|
|
800
|
+
...buildOrgFilter(req, { ...config, withOrganization, orgField })
|
|
801
|
+
};
|
|
802
|
+
let dbQuery = model.findOne(query);
|
|
803
|
+
if (populateFields.length > 0) {
|
|
804
|
+
populateFields.forEach((field) => {
|
|
805
|
+
dbQuery = dbQuery.populate(field);
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
const doc = await dbQuery;
|
|
809
|
+
if (!doc) {
|
|
810
|
+
notFoundResponse(res, `${resourceName} not found`);
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
successResponse(res, doc, `${resourceName} fetched successfully`);
|
|
814
|
+
} catch (error) {
|
|
815
|
+
logger.error(`Error in getById ${resourceName}`, {
|
|
816
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
817
|
+
id: req.params.id
|
|
818
|
+
});
|
|
819
|
+
errorResponse(res, `Failed to fetch ${resourceName.toLowerCase()}`);
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
const create = async (req, res, _next) => {
|
|
823
|
+
try {
|
|
824
|
+
let input = req.body;
|
|
825
|
+
if (createSchema) {
|
|
826
|
+
try {
|
|
827
|
+
input = createSchema.parse(input);
|
|
828
|
+
} catch (error) {
|
|
829
|
+
if (isZodError(error)) {
|
|
830
|
+
badRequestResponse(res, formatZodError(error));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
throw error;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (transformCreate) {
|
|
837
|
+
input = transformCreate(input, req);
|
|
838
|
+
}
|
|
839
|
+
if (withOrganization) {
|
|
840
|
+
const orgId = getOrgId(req, orgField);
|
|
841
|
+
if (orgId) {
|
|
842
|
+
input[orgField] = orgId;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
const doc = new model(input);
|
|
846
|
+
await doc.save();
|
|
847
|
+
if (afterCreate) {
|
|
848
|
+
await afterCreate(doc, req);
|
|
849
|
+
}
|
|
850
|
+
logger.info(`${resourceName} created successfully`, {
|
|
851
|
+
id: doc._id,
|
|
852
|
+
[orgField]: input[orgField]
|
|
853
|
+
});
|
|
854
|
+
createdResponse(res, doc, `${resourceName} created successfully`);
|
|
855
|
+
} catch (error) {
|
|
856
|
+
logger.error(`Error in create ${resourceName}`, {
|
|
857
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
858
|
+
});
|
|
859
|
+
if (error.code === 11e3) {
|
|
860
|
+
badRequestResponse(res, `A ${resourceName.toLowerCase()} with this data already exists`);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
errorResponse(res, `Failed to create ${resourceName.toLowerCase()}`);
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
const update = async (req, res, _next) => {
|
|
867
|
+
try {
|
|
868
|
+
const { id } = req.params;
|
|
869
|
+
if (!id || !Types.ObjectId.isValid(id)) {
|
|
870
|
+
badRequestResponse(res, "Invalid ID format");
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
let input = req.body;
|
|
874
|
+
if (updateSchema) {
|
|
875
|
+
try {
|
|
876
|
+
input = updateSchema.parse(input);
|
|
877
|
+
} catch (error) {
|
|
878
|
+
if (isZodError(error)) {
|
|
879
|
+
badRequestResponse(res, formatZodError(error));
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
throw error;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
if (transformUpdate) {
|
|
886
|
+
input = transformUpdate(input, req);
|
|
887
|
+
}
|
|
888
|
+
const query = {
|
|
889
|
+
_id: new Types.ObjectId(id),
|
|
890
|
+
...buildOrgFilter(req, { ...config, withOrganization, orgField })
|
|
891
|
+
};
|
|
892
|
+
const doc = await model.findOneAndUpdate(query, { $set: input }, { new: true });
|
|
893
|
+
if (!doc) {
|
|
894
|
+
notFoundResponse(res, `${resourceName} not found`);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
if (afterUpdate) {
|
|
898
|
+
await afterUpdate(doc, req);
|
|
899
|
+
}
|
|
900
|
+
logger.info(`${resourceName} updated successfully`, { id });
|
|
901
|
+
successResponse(res, doc, `${resourceName} updated successfully`);
|
|
902
|
+
} catch (error) {
|
|
903
|
+
logger.error(`Error in update ${resourceName}`, {
|
|
904
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
905
|
+
id: req.params.id
|
|
906
|
+
});
|
|
907
|
+
errorResponse(res, `Failed to update ${resourceName.toLowerCase()}`);
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
const deleteOne = async (req, res, _next) => {
|
|
911
|
+
try {
|
|
912
|
+
const { id } = req.params;
|
|
913
|
+
if (!id || !Types.ObjectId.isValid(id)) {
|
|
914
|
+
badRequestResponse(res, "Invalid ID format");
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const query = {
|
|
918
|
+
_id: new Types.ObjectId(id),
|
|
919
|
+
...buildOrgFilter(req, { ...config, withOrganization, orgField })
|
|
920
|
+
};
|
|
921
|
+
const result = await model.deleteOne(query);
|
|
922
|
+
if (result.deletedCount === 0) {
|
|
923
|
+
notFoundResponse(res, `${resourceName} not found`);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (afterDelete) {
|
|
927
|
+
await afterDelete(id, req);
|
|
928
|
+
}
|
|
929
|
+
logger.info(`${resourceName} deleted successfully`, { id });
|
|
930
|
+
noContentResponse(res, null, `${resourceName} deleted successfully`);
|
|
931
|
+
} catch (error) {
|
|
932
|
+
logger.error(`Error in delete ${resourceName}`, {
|
|
933
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
934
|
+
id: req.params.id
|
|
935
|
+
});
|
|
936
|
+
errorResponse(res, `Failed to delete ${resourceName.toLowerCase()}`);
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
const bulkDelete = async (req, res, _next) => {
|
|
940
|
+
try {
|
|
941
|
+
const bulkReq = req;
|
|
942
|
+
const { deleteIds = [], deleteAll = false } = bulkReq;
|
|
943
|
+
const baseFilter = buildOrgFilter(req, { ...config, withOrganization, orgField });
|
|
944
|
+
let filter;
|
|
945
|
+
if (deleteAll) {
|
|
946
|
+
filter = baseFilter;
|
|
947
|
+
} else if (deleteIds.length > 0) {
|
|
948
|
+
filter = {
|
|
949
|
+
...baseFilter,
|
|
950
|
+
_id: { $in: deleteIds.map((id) => new Types.ObjectId(id)) }
|
|
951
|
+
};
|
|
952
|
+
} else {
|
|
953
|
+
badRequestResponse(res, "No IDs provided for deletion");
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const result = await model.deleteMany(filter);
|
|
957
|
+
if (afterDelete && deleteIds.length > 0) {
|
|
958
|
+
await Promise.all(deleteIds.map((id) => afterDelete(id, req)));
|
|
959
|
+
}
|
|
960
|
+
logger.info(`${resourceName}(s) bulk deleted successfully`, {
|
|
961
|
+
deletedCount: result.deletedCount,
|
|
962
|
+
deleteAll
|
|
963
|
+
});
|
|
964
|
+
successResponse(
|
|
965
|
+
res,
|
|
966
|
+
{ deletedCount: result.deletedCount },
|
|
967
|
+
`${result.deletedCount} ${resourceName.toLowerCase()}(s) deleted successfully`
|
|
968
|
+
);
|
|
969
|
+
} catch (error) {
|
|
970
|
+
logger.error(`Error in bulkDelete ${resourceName}`, {
|
|
971
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
972
|
+
});
|
|
973
|
+
errorResponse(res, `Failed to delete ${resourceName.toLowerCase()}(s)`);
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
return {
|
|
977
|
+
getAll,
|
|
978
|
+
getById,
|
|
979
|
+
create,
|
|
980
|
+
update,
|
|
981
|
+
deleteOne,
|
|
982
|
+
bulkDelete
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
function createPaginationMiddleware(model, config = {}) {
|
|
986
|
+
const {
|
|
987
|
+
searchFields = [],
|
|
988
|
+
regexFilterFields = [],
|
|
989
|
+
withOrganization = true,
|
|
990
|
+
orgField = "organizationId"
|
|
991
|
+
} = config;
|
|
992
|
+
return async (req, res, next) => {
|
|
993
|
+
try {
|
|
994
|
+
const page = parseInt(req.query.page) || 1;
|
|
995
|
+
const limit = parseInt(req.query.limit) || 10;
|
|
996
|
+
const sortField = req.query.sortBy || "createdAt";
|
|
997
|
+
const sortOrder = req.query.sortOrder || "desc";
|
|
998
|
+
const search = req.query.search;
|
|
999
|
+
const query = {};
|
|
1000
|
+
if (withOrganization) {
|
|
1001
|
+
const orgId = getOrgId(req, orgField);
|
|
1002
|
+
if (orgId) {
|
|
1003
|
+
query[orgField] = orgId;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (search && searchFields.length > 0) {
|
|
1007
|
+
query.$or = searchFields.map((field) => ({
|
|
1008
|
+
[field]: { $regex: search, $options: "i" }
|
|
1009
|
+
}));
|
|
1010
|
+
}
|
|
1011
|
+
const filterableParams = Object.keys(req.query).filter(
|
|
1012
|
+
(key) => !["page", "limit", "sortBy", "sortOrder", "search"].includes(key)
|
|
1013
|
+
);
|
|
1014
|
+
filterableParams.forEach((key) => {
|
|
1015
|
+
const value = req.query[key];
|
|
1016
|
+
if (value !== void 0 && value !== "" && value !== "all") {
|
|
1017
|
+
if (regexFilterFields.includes(key)) {
|
|
1018
|
+
query[key] = { $regex: value, $options: "i" };
|
|
1019
|
+
} else {
|
|
1020
|
+
query[key] = value;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
const sortQuery = { [sortField]: sortOrder };
|
|
1025
|
+
const skip = (page - 1) * limit;
|
|
1026
|
+
const [data, total] = await Promise.all([
|
|
1027
|
+
model.find(query).sort(sortQuery).skip(skip).limit(limit),
|
|
1028
|
+
model.countDocuments(query)
|
|
1029
|
+
]);
|
|
1030
|
+
const paginatedRes = res;
|
|
1031
|
+
paginatedRes.paginatedResult = {
|
|
1032
|
+
data,
|
|
1033
|
+
meta: {
|
|
1034
|
+
page,
|
|
1035
|
+
limit,
|
|
1036
|
+
total,
|
|
1037
|
+
totalPages: Math.ceil(total / limit)
|
|
1038
|
+
},
|
|
1039
|
+
columns: extractSchemaMeta(model, config.createSchema)
|
|
1040
|
+
};
|
|
1041
|
+
next();
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
next(error);
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
var parseBulkDelete = (req, res, next) => {
|
|
1048
|
+
try {
|
|
1049
|
+
const bulkReq = req;
|
|
1050
|
+
let ids = [];
|
|
1051
|
+
if (Array.isArray(req.body)) {
|
|
1052
|
+
ids = req.body;
|
|
1053
|
+
} else if (req.body && Array.isArray(req.body.ids)) {
|
|
1054
|
+
ids = req.body.ids;
|
|
1055
|
+
} else if (req.body && typeof req.body === "object") {
|
|
1056
|
+
if (Array.isArray(req.body.data)) {
|
|
1057
|
+
ids = req.body.data;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
if (ids.length === 0) {
|
|
1061
|
+
return badRequestResponse(
|
|
1062
|
+
res,
|
|
1063
|
+
'Request body must contain an array of IDs. Use ["*"] to delete all records or ["id1", "id2"] to delete specific records.'
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
if (ids.length === 1 && ids[0] === "*") {
|
|
1067
|
+
bulkReq.deleteAll = true;
|
|
1068
|
+
bulkReq.deleteIds = [];
|
|
1069
|
+
logger.info("Bulk delete: Deleting all records");
|
|
1070
|
+
return next();
|
|
1071
|
+
}
|
|
1072
|
+
const validIds = [];
|
|
1073
|
+
const invalidIds = [];
|
|
1074
|
+
for (const id of ids) {
|
|
1075
|
+
if (typeof id === "string" && Types.ObjectId.isValid(id)) {
|
|
1076
|
+
validIds.push(id);
|
|
1077
|
+
} else {
|
|
1078
|
+
invalidIds.push(id);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
if (invalidIds.length > 0) {
|
|
1082
|
+
return badRequestResponse(
|
|
1083
|
+
res,
|
|
1084
|
+
`Invalid ID format(s): ${invalidIds.slice(0, 5).join(", ")}${invalidIds.length > 5 ? "..." : ""}. All IDs must be valid MongoDB ObjectIds.`
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
1087
|
+
if (validIds.length === 0) {
|
|
1088
|
+
return badRequestResponse(res, "No valid IDs provided for deletion.");
|
|
1089
|
+
}
|
|
1090
|
+
bulkReq.deleteAll = false;
|
|
1091
|
+
bulkReq.deleteIds = validIds;
|
|
1092
|
+
logger.info(`Bulk delete: Deleting ${validIds.length} record(s)`);
|
|
1093
|
+
next();
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
logger.error("Error in parseBulkDelete middleware", error);
|
|
1096
|
+
return badRequestResponse(res, "Failed to parse delete request");
|
|
1097
|
+
}
|
|
1098
|
+
};
|
|
1099
|
+
var buildDeleteFilter = (req, organizationId) => {
|
|
1100
|
+
const filter = {
|
|
1101
|
+
organizationId: new Types.ObjectId(organizationId)
|
|
1102
|
+
};
|
|
1103
|
+
if (!req.deleteAll && req.deleteIds && req.deleteIds.length > 0) {
|
|
1104
|
+
filter._id = {
|
|
1105
|
+
$in: req.deleteIds.map((id) => new Types.ObjectId(id))
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
return filter;
|
|
1109
|
+
};
|
|
1110
|
+
var createBulkDeleteHandler = (Model2, modelName) => {
|
|
1111
|
+
return async (req, res) => {
|
|
1112
|
+
const bulkReq = req;
|
|
1113
|
+
const organizationId = req.headers["x-organization-id"];
|
|
1114
|
+
if (!organizationId) {
|
|
1115
|
+
return badRequestResponse(res, "Organization ID is required");
|
|
1116
|
+
}
|
|
1117
|
+
try {
|
|
1118
|
+
const filter = buildDeleteFilter(bulkReq, organizationId);
|
|
1119
|
+
const result = await Model2.deleteMany(filter);
|
|
1120
|
+
const deletedCount = result.deletedCount || 0;
|
|
1121
|
+
logger.info(`Bulk delete completed: ${deletedCount} ${modelName}(s) deleted`, {
|
|
1122
|
+
organizationId,
|
|
1123
|
+
deleteAll: bulkReq.deleteAll,
|
|
1124
|
+
requestedIds: bulkReq.deleteIds?.length || "all",
|
|
1125
|
+
deletedCount
|
|
1126
|
+
});
|
|
1127
|
+
return res.status(200).json({
|
|
1128
|
+
message: `Successfully deleted ${deletedCount} ${modelName}(s)`,
|
|
1129
|
+
data: {
|
|
1130
|
+
deletedCount,
|
|
1131
|
+
deleteAll: bulkReq.deleteAll
|
|
1132
|
+
},
|
|
1133
|
+
status: "success",
|
|
1134
|
+
statusCode: 200
|
|
1135
|
+
});
|
|
1136
|
+
} catch (error) {
|
|
1137
|
+
logger.error(`Error in bulk delete ${modelName}`, error);
|
|
1138
|
+
return res.status(500).json({
|
|
1139
|
+
message: `Failed to delete ${modelName}(s)`,
|
|
1140
|
+
data: null,
|
|
1141
|
+
status: "error",
|
|
1142
|
+
statusCode: 500
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
};
|
|
1147
|
+
|
|
517
1148
|
// src/server/utils/filter-builder.ts
|
|
518
1149
|
var buildFilter = (options) => {
|
|
519
1150
|
const {
|
|
@@ -1471,34 +2102,32 @@ var getDatabaseOptions = (config) => {
|
|
|
1471
2102
|
// src/client/index.ts
|
|
1472
2103
|
var client_exports = {};
|
|
1473
2104
|
__export(client_exports, {
|
|
1474
|
-
|
|
2105
|
+
API_BASE_URL: () => API_BASE_URL,
|
|
2106
|
+
API_PREFIX: () => API_PREFIX,
|
|
1475
2107
|
ClientLogger: () => ClientLogger,
|
|
1476
2108
|
ContactForm: () => ContactForm,
|
|
1477
|
-
|
|
2109
|
+
ERROR_CODES: () => ERROR_CODES,
|
|
1478
2110
|
LoginForm: () => LoginForm,
|
|
1479
2111
|
NewsletterForm: () => NewsletterForm,
|
|
1480
2112
|
RegisterForm: () => RegisterForm,
|
|
2113
|
+
STATUS_CODES: () => STATUS_CODES,
|
|
2114
|
+
STATUS_MESSAGES: () => STATUS_MESSAGES,
|
|
2115
|
+
SUCCESS_CODES: () => SUCCESS_CODES,
|
|
1481
2116
|
ThemeContext: () => ThemeContext,
|
|
1482
2117
|
ThemeProvider: () => ThemeProvider,
|
|
1483
2118
|
ThemeToggle: () => ThemeToggle,
|
|
1484
2119
|
VALIDATION_MESSAGES: () => VALIDATION_MESSAGES,
|
|
1485
|
-
addDays: () => addDays,
|
|
1486
2120
|
adjustColor: () => adjustColor,
|
|
1487
|
-
|
|
2121
|
+
axios: () => axiosInstance,
|
|
1488
2122
|
camelToKebab: () => camelToKebab,
|
|
1489
2123
|
capitalize: () => capitalize,
|
|
1490
2124
|
capitalizeWords: () => capitalizeWords,
|
|
1491
|
-
checkPackage: () => checkPackage,
|
|
1492
2125
|
clientLogger: () => clientLogger,
|
|
1493
2126
|
contactFormSchema: () => contactFormSchema,
|
|
1494
2127
|
copyToClipboard: () => copyToClipboard,
|
|
1495
|
-
createApiEndpoints: () => createApiEndpoints,
|
|
1496
|
-
createApiUrlBuilder: () => createApiUrlBuilder,
|
|
1497
2128
|
createClientLogger: () => createClientLogger,
|
|
1498
2129
|
createEmptyPaginationMeta: () => createEmptyPaginationMeta,
|
|
1499
2130
|
createErrorResponse: () => createErrorResponse,
|
|
1500
|
-
createEventEmitter: () => createEventEmitter,
|
|
1501
|
-
createHttpClient: () => createHttpClient,
|
|
1502
2131
|
createRegisterFormSchema: () => createRegisterFormSchema,
|
|
1503
2132
|
createSuccessResponse: () => createSuccessResponse,
|
|
1504
2133
|
createTheme: () => createTheme,
|
|
@@ -1507,6 +2136,7 @@ __export(client_exports, {
|
|
|
1507
2136
|
deepMerge: () => deepMerge2,
|
|
1508
2137
|
defaultDarkTheme: () => defaultDarkTheme,
|
|
1509
2138
|
defaultLightTheme: () => defaultLightTheme,
|
|
2139
|
+
deleteRequest: () => deleteRequest,
|
|
1510
2140
|
dummyBannerData: () => dummyBannerData,
|
|
1511
2141
|
dummyFaqItems: () => dummyFaqItems,
|
|
1512
2142
|
dummyFeatures: () => dummyFeatures,
|
|
@@ -1515,59 +2145,66 @@ __export(client_exports, {
|
|
|
1515
2145
|
dummyImage: () => dummyImage,
|
|
1516
2146
|
dummyPricingPlans: () => dummyPricingPlans,
|
|
1517
2147
|
dummyTestimonials: () => dummyTestimonials,
|
|
1518
|
-
|
|
2148
|
+
extractData: () => extractData,
|
|
2149
|
+
extractMessage: () => extractMessage,
|
|
2150
|
+
extractNestedData: () => extractNestedData,
|
|
2151
|
+
extractPaginatedData: () => extractPaginatedData,
|
|
1519
2152
|
flattenToCssVars: () => flattenToCssVars,
|
|
1520
2153
|
formatDate: () => formatDate,
|
|
1521
|
-
formatDateForInput: () => formatDateForInput,
|
|
1522
2154
|
formatDateTime: () => formatDateTime,
|
|
1523
|
-
formatDateTimeForInput: () => formatDateTimeForInput,
|
|
1524
|
-
formatPackageCheckResult: () => formatPackageCheckResult2,
|
|
1525
2155
|
formatRelativeTime: () => formatRelativeTime,
|
|
1526
2156
|
generateCssVars: () => generateCssVars,
|
|
1527
|
-
|
|
2157
|
+
generateSlug: () => generateSlug,
|
|
2158
|
+
generateSnakeSlug: () => generateSnakeSlug,
|
|
2159
|
+
generateUrlSlug: () => generateUrlSlug,
|
|
1528
2160
|
getContrastColor: () => getContrastColor,
|
|
1529
2161
|
getErrorMessage: () => getErrorMessage,
|
|
1530
2162
|
getNextPage: () => getNextPage,
|
|
1531
2163
|
getPrevPage: () => getPrevPage,
|
|
2164
|
+
getRequest: () => getRequest,
|
|
1532
2165
|
getResponseData: () => getResponseData,
|
|
1533
2166
|
getSystemColorScheme: () => getSystemColorScheme,
|
|
1534
2167
|
hasData: () => hasData,
|
|
1535
2168
|
hasMorePages: () => hasMorePages,
|
|
1536
2169
|
hexToRgba: () => hexToRgba,
|
|
1537
2170
|
injectCssVars: () => injectCssVars,
|
|
1538
|
-
isClipboardAvailable: () => isClipboardAvailable,
|
|
1539
2171
|
isErrorResponse: () => isErrorResponse,
|
|
1540
|
-
isForbidden: () => isForbidden,
|
|
1541
|
-
isFuture: () => isFuture,
|
|
1542
|
-
isNotFound: () => isNotFound,
|
|
1543
|
-
isPast: () => isPast,
|
|
1544
|
-
isServerError: () => isServerError,
|
|
1545
|
-
isStatusError: () => isStatusError,
|
|
1546
2172
|
isSuccess: () => isSuccess,
|
|
1547
2173
|
isSuccessResponse: () => isSuccessResponse,
|
|
1548
|
-
|
|
1549
|
-
|
|
2174
|
+
isUtilErrorResponse: () => isErrorResponse2,
|
|
2175
|
+
isUtilSuccessResponse: () => isSuccessResponse2,
|
|
1550
2176
|
kebabToCamel: () => kebabToCamel,
|
|
1551
2177
|
loadThemeFromUrl: () => loadThemeFromUrl,
|
|
1552
2178
|
loadThemeMode: () => loadThemeMode,
|
|
2179
|
+
logger: () => logger2,
|
|
1553
2180
|
loginFormSchema: () => loginFormSchema,
|
|
1554
2181
|
loremIpsum: () => loremIpsum,
|
|
1555
2182
|
newsletterFormSchema: () => newsletterFormSchema,
|
|
1556
2183
|
packageCheck: () => packageCheck,
|
|
2184
|
+
parseAxiosErrorMessage: () => parseAxiosErrorMessage,
|
|
1557
2185
|
parseError: () => parseError,
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
2186
|
+
parsePaginatedResponse: () => parsePaginatedResponse,
|
|
2187
|
+
parseResponseData: () => parseResponseData,
|
|
2188
|
+
parseResponseMessage: () => parseResponseMessage,
|
|
2189
|
+
parseResponseStatus: () => parseResponseStatus,
|
|
2190
|
+
parseResponseStatusMessage: () => parseResponseStatusMessage,
|
|
2191
|
+
patchRequest: () => patchRequest,
|
|
2192
|
+
postRequest: () => postRequest,
|
|
2193
|
+
putRequest: () => putRequest,
|
|
1561
2194
|
registerFormSchema: () => registerFormSchema,
|
|
1562
2195
|
removeCssVars: () => removeCssVars,
|
|
1563
2196
|
resolveThemeMode: () => resolveThemeMode,
|
|
2197
|
+
safeJsonParse: () => safeJsonParse,
|
|
1564
2198
|
saveThemeMode: () => saveThemeMode,
|
|
2199
|
+
simpleMetaParseResponse: () => simpleMetaParseResponse,
|
|
2200
|
+
simpleParseDualDataResponse: () => simpleParseDualDataResponse,
|
|
2201
|
+
simpleParseResponse: () => simpleParseResponse,
|
|
1565
2202
|
slugify: () => slugify,
|
|
1566
2203
|
slugifyUnique: () => slugifyUnique,
|
|
1567
|
-
startOfDay: () => startOfDay,
|
|
1568
2204
|
truncate: () => truncate,
|
|
1569
2205
|
truncateWords: () => truncateWords,
|
|
1570
2206
|
unslugify: () => unslugify,
|
|
2207
|
+
uploadFile: () => uploadFile,
|
|
1571
2208
|
useBattery: () => useBattery_default,
|
|
1572
2209
|
useClickAway: () => useClickAway_default,
|
|
1573
2210
|
useContinuousRetry: () => useContinuousRetry_default,
|
|
@@ -1627,112 +2264,466 @@ __export(client_exports, {
|
|
|
1627
2264
|
useToggle: () => useToggle_default,
|
|
1628
2265
|
useVisibilityChange: () => useVisibilityChange_default,
|
|
1629
2266
|
useWindowScroll: () => useWindowScroll_default,
|
|
1630
|
-
useWindowSize: () => useWindowSize_default
|
|
1631
|
-
withAbortSignal: () => withAbortSignal,
|
|
1632
|
-
withFormData: () => withFormData,
|
|
1633
|
-
withTimeout: () => withTimeout
|
|
2267
|
+
useWindowSize: () => useWindowSize_default
|
|
1634
2268
|
});
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
headers: {
|
|
1649
|
-
"Content-Type": "application/json"
|
|
2269
|
+
|
|
2270
|
+
// src/client/http/logger.ts
|
|
2271
|
+
var Logger = class {
|
|
2272
|
+
constructor() {
|
|
2273
|
+
this.isDevelopment = typeof window !== "undefined" && window.location.hostname === "localhost";
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Log informational messages
|
|
2277
|
+
*/
|
|
2278
|
+
info(message, data, options) {
|
|
2279
|
+
if (this.isDevelopment) {
|
|
2280
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2281
|
+
console.log(`${prefix} ${message}`, data ?? "");
|
|
1650
2282
|
}
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
2283
|
+
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Log warning messages
|
|
2286
|
+
*/
|
|
2287
|
+
warn(message, data, options) {
|
|
2288
|
+
if (this.isDevelopment) {
|
|
2289
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2290
|
+
console.warn(`${prefix} ${message}`, data ?? "");
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Log error messages
|
|
2295
|
+
*/
|
|
2296
|
+
error(message, error, options) {
|
|
2297
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2298
|
+
if (this.isDevelopment) {
|
|
2299
|
+
console.error(`${prefix} ${message}`, error, options?.metadata || "");
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* Log debug messages (only in development)
|
|
2304
|
+
*/
|
|
2305
|
+
debug(message, data, options) {
|
|
2306
|
+
if (this.isDevelopment) {
|
|
2307
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2308
|
+
console.debug(`${prefix} ${message}`, data || "");
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
/**
|
|
2312
|
+
* Log API errors with structured information
|
|
2313
|
+
*/
|
|
2314
|
+
apiError(endpoint, error, metadata) {
|
|
2315
|
+
this.error(`API Error: ${endpoint}`, error, {
|
|
2316
|
+
context: "API",
|
|
2317
|
+
metadata: {
|
|
2318
|
+
endpoint,
|
|
2319
|
+
...metadata
|
|
1659
2320
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
};
|
|
2324
|
+
var logger2 = new Logger();
|
|
2325
|
+
|
|
2326
|
+
// src/client/http/response-parser.ts
|
|
2327
|
+
var STATUS_CODES = {
|
|
2328
|
+
SUCCESS: 200,
|
|
2329
|
+
CREATED: 201,
|
|
2330
|
+
NO_CONTENT: 204,
|
|
2331
|
+
BAD_REQUEST: 400,
|
|
2332
|
+
UNAUTHORIZED: 401,
|
|
2333
|
+
FORBIDDEN: 403,
|
|
2334
|
+
NOT_FOUND: 404,
|
|
2335
|
+
CONFLICT: 409,
|
|
2336
|
+
ERROR: 500
|
|
2337
|
+
};
|
|
2338
|
+
var STATUS_MESSAGES = {
|
|
2339
|
+
SUCCESS: "success",
|
|
2340
|
+
CREATED: "created",
|
|
2341
|
+
NO_CONTENT: "no_content",
|
|
2342
|
+
BAD_REQUEST: "bad_request",
|
|
2343
|
+
UNAUTHORIZED: "unauthorized",
|
|
2344
|
+
FORBIDDEN: "forbidden",
|
|
2345
|
+
NOT_FOUND: "not_found",
|
|
2346
|
+
CONFLICT: "conflict",
|
|
2347
|
+
ERROR: "error"
|
|
2348
|
+
};
|
|
2349
|
+
var SUCCESS_CODES = [200, 201, 204];
|
|
2350
|
+
var ERROR_CODES = [400, 401, 403, 404, 409, 500];
|
|
2351
|
+
var parseResponseData = (response, fallback = null) => {
|
|
2352
|
+
try {
|
|
2353
|
+
if (!response || typeof response !== "object") {
|
|
2354
|
+
return fallback;
|
|
2355
|
+
}
|
|
2356
|
+
const resp = response;
|
|
2357
|
+
if ("data" in resp) {
|
|
2358
|
+
return resp["data"] ?? fallback;
|
|
2359
|
+
}
|
|
2360
|
+
return response;
|
|
2361
|
+
} catch (error) {
|
|
2362
|
+
logger2.error("Error parsing response data", error);
|
|
2363
|
+
return fallback;
|
|
2364
|
+
}
|
|
2365
|
+
};
|
|
2366
|
+
var parseResponseMessage = (response, fallback = "") => {
|
|
2367
|
+
try {
|
|
2368
|
+
if (!response || typeof response !== "object") {
|
|
2369
|
+
return fallback;
|
|
2370
|
+
}
|
|
2371
|
+
const resp = response;
|
|
2372
|
+
if ("message" in resp && typeof resp["message"] === "string") {
|
|
2373
|
+
return resp["message"];
|
|
2374
|
+
}
|
|
2375
|
+
return fallback;
|
|
2376
|
+
} catch (error) {
|
|
2377
|
+
logger2.error("Error parsing response message", error);
|
|
2378
|
+
return fallback;
|
|
2379
|
+
}
|
|
2380
|
+
};
|
|
2381
|
+
var parseResponseStatus = (response) => {
|
|
2382
|
+
try {
|
|
2383
|
+
if (!response || typeof response !== "object") {
|
|
2384
|
+
return null;
|
|
2385
|
+
}
|
|
2386
|
+
const resp = response;
|
|
2387
|
+
if ("statusCode" in resp && typeof resp["statusCode"] === "number") {
|
|
2388
|
+
return resp["statusCode"];
|
|
2389
|
+
}
|
|
2390
|
+
if ("status" in resp && typeof resp["status"] === "number") {
|
|
2391
|
+
return resp["status"];
|
|
2392
|
+
}
|
|
2393
|
+
return null;
|
|
2394
|
+
} catch (error) {
|
|
2395
|
+
logger2.error("Error parsing response status", error);
|
|
2396
|
+
return null;
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
2399
|
+
var parseResponseStatusMessage = (response, fallback = "") => {
|
|
2400
|
+
try {
|
|
2401
|
+
if (!response || typeof response !== "object") {
|
|
2402
|
+
return fallback;
|
|
2403
|
+
}
|
|
2404
|
+
const resp = response;
|
|
2405
|
+
if ("status" in resp && typeof resp["status"] === "string") {
|
|
2406
|
+
return resp["status"];
|
|
2407
|
+
}
|
|
2408
|
+
return fallback;
|
|
2409
|
+
} catch (error) {
|
|
2410
|
+
logger2.error("Error parsing response status message", error);
|
|
2411
|
+
return fallback;
|
|
2412
|
+
}
|
|
2413
|
+
};
|
|
2414
|
+
var isSuccessResponse = (response) => {
|
|
2415
|
+
try {
|
|
2416
|
+
const statusCode2 = parseResponseStatus(response);
|
|
2417
|
+
if (statusCode2 !== null) {
|
|
2418
|
+
return SUCCESS_CODES.includes(statusCode2);
|
|
2419
|
+
}
|
|
2420
|
+
const status = parseResponseStatusMessage(response);
|
|
2421
|
+
return [STATUS_MESSAGES.SUCCESS, STATUS_MESSAGES.CREATED, STATUS_MESSAGES.NO_CONTENT].includes(
|
|
2422
|
+
status
|
|
2423
|
+
);
|
|
2424
|
+
} catch (error) {
|
|
2425
|
+
logger2.error("Error checking response success", error);
|
|
2426
|
+
return false;
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2429
|
+
var isErrorResponse = (response) => {
|
|
2430
|
+
try {
|
|
2431
|
+
const statusCode2 = parseResponseStatus(response);
|
|
2432
|
+
if (statusCode2 !== null) {
|
|
2433
|
+
return ERROR_CODES.includes(statusCode2);
|
|
2434
|
+
}
|
|
2435
|
+
return false;
|
|
2436
|
+
} catch (error) {
|
|
2437
|
+
logger2.error("Error checking response error", error);
|
|
2438
|
+
return false;
|
|
2439
|
+
}
|
|
2440
|
+
};
|
|
2441
|
+
var parsePaginatedResponse = (response) => {
|
|
2442
|
+
try {
|
|
2443
|
+
if (!response || typeof response !== "object") {
|
|
2444
|
+
return { items: [], total: 0, page: 1, limit: 10 };
|
|
2445
|
+
}
|
|
2446
|
+
const resp = response;
|
|
2447
|
+
let items = [];
|
|
2448
|
+
if ("data" in resp && Array.isArray(resp["data"])) {
|
|
2449
|
+
items = resp["data"];
|
|
2450
|
+
}
|
|
2451
|
+
let total = items.length;
|
|
2452
|
+
let page = 1;
|
|
2453
|
+
let limit = 10;
|
|
2454
|
+
let totalPages;
|
|
2455
|
+
if ("paginationData" in resp && resp["paginationData"] && typeof resp["paginationData"] === "object") {
|
|
2456
|
+
const paginationData = resp["paginationData"];
|
|
2457
|
+
if ("total" in paginationData && typeof paginationData["total"] === "number") {
|
|
2458
|
+
total = paginationData["total"];
|
|
2459
|
+
}
|
|
2460
|
+
if ("page" in paginationData && typeof paginationData["page"] === "number") {
|
|
2461
|
+
page = paginationData["page"];
|
|
2462
|
+
}
|
|
2463
|
+
if ("limit" in paginationData && typeof paginationData["limit"] === "number") {
|
|
2464
|
+
limit = paginationData["limit"];
|
|
2465
|
+
}
|
|
2466
|
+
if ("totalPages" in paginationData && typeof paginationData["totalPages"] === "number") {
|
|
2467
|
+
totalPages = paginationData["totalPages"];
|
|
1675
2468
|
}
|
|
1676
|
-
return Promise.reject(error);
|
|
1677
2469
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
2470
|
+
let columns;
|
|
2471
|
+
if ("columns" in resp && Array.isArray(resp["columns"])) {
|
|
2472
|
+
columns = resp["columns"];
|
|
2473
|
+
}
|
|
2474
|
+
return {
|
|
2475
|
+
items,
|
|
2476
|
+
total,
|
|
2477
|
+
page,
|
|
2478
|
+
limit,
|
|
2479
|
+
...totalPages !== void 0 && { totalPages },
|
|
2480
|
+
...columns !== void 0 && { columns }
|
|
2481
|
+
};
|
|
2482
|
+
} catch (error) {
|
|
2483
|
+
logger2.error("Error parsing paginated response", error);
|
|
2484
|
+
return { items: [], total: 0, page: 1, limit: 10 };
|
|
2485
|
+
}
|
|
1680
2486
|
};
|
|
1681
|
-
var
|
|
1682
|
-
|
|
1683
|
-
|
|
2487
|
+
var extractNestedData = (response, path2, fallback = null) => {
|
|
2488
|
+
try {
|
|
2489
|
+
const keys = path2.split(".");
|
|
2490
|
+
let current = response;
|
|
2491
|
+
for (const key of keys) {
|
|
2492
|
+
if (current && typeof current === "object" && key in current) {
|
|
2493
|
+
current = current[key];
|
|
2494
|
+
} else {
|
|
2495
|
+
return fallback;
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
return current;
|
|
2499
|
+
} catch (error) {
|
|
2500
|
+
logger2.error("Error extracting nested data", error);
|
|
2501
|
+
return fallback;
|
|
1684
2502
|
}
|
|
1685
|
-
}
|
|
1686
|
-
var
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
// src/client/http/response-parser.ts
|
|
1694
|
-
var parseResponse = (response) => {
|
|
1695
|
-
if (response.data?.success && response.data?.data !== void 0) {
|
|
1696
|
-
return response.data.data;
|
|
2503
|
+
};
|
|
2504
|
+
var safeJsonParse = (json, fallback = null) => {
|
|
2505
|
+
try {
|
|
2506
|
+
return JSON.parse(json);
|
|
2507
|
+
} catch (error) {
|
|
2508
|
+
logger2.error("Error parsing JSON", error);
|
|
2509
|
+
return fallback;
|
|
1697
2510
|
}
|
|
1698
|
-
return null;
|
|
1699
2511
|
};
|
|
1700
|
-
var
|
|
1701
|
-
|
|
2512
|
+
var parseAxiosErrorMessage = (error) => {
|
|
2513
|
+
try {
|
|
2514
|
+
if (!error || typeof error !== "object") {
|
|
2515
|
+
return "An unexpected error occurred";
|
|
2516
|
+
}
|
|
2517
|
+
const err = error;
|
|
2518
|
+
if ("response" in err && err["response"] && typeof err["response"] === "object") {
|
|
2519
|
+
const response = err["response"];
|
|
2520
|
+
if ("data" in response && response["data"] && typeof response["data"] === "object") {
|
|
2521
|
+
const data = response["data"];
|
|
2522
|
+
if ("data" in data && data["data"] && typeof data["data"] === "object") {
|
|
2523
|
+
const nestedData = data["data"];
|
|
2524
|
+
if ("message" in nestedData && typeof nestedData["message"] === "string") {
|
|
2525
|
+
return nestedData["message"];
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
if ("message" in data && typeof data["message"] === "string") {
|
|
2529
|
+
return data["message"];
|
|
2530
|
+
}
|
|
2531
|
+
if ("error" in data && typeof data["error"] === "string") {
|
|
2532
|
+
return data["error"];
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
if ("message" in err && typeof err["message"] === "string") {
|
|
2537
|
+
return err["message"];
|
|
2538
|
+
}
|
|
2539
|
+
if (typeof error === "string") {
|
|
2540
|
+
return error;
|
|
2541
|
+
}
|
|
2542
|
+
return "An unexpected error occurred";
|
|
2543
|
+
} catch (parseError2) {
|
|
2544
|
+
logger2.error("Error parsing axios error message", parseError2);
|
|
2545
|
+
return "An unexpected error occurred";
|
|
2546
|
+
}
|
|
1702
2547
|
};
|
|
1703
2548
|
var parseError = (error) => {
|
|
1704
|
-
|
|
1705
|
-
|
|
2549
|
+
try {
|
|
2550
|
+
if (!error || typeof error !== "object") {
|
|
2551
|
+
return {
|
|
2552
|
+
message: "An unexpected error occurred",
|
|
2553
|
+
statusCode: null,
|
|
2554
|
+
data: null
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
const err = error;
|
|
2558
|
+
let statusCode2 = null;
|
|
2559
|
+
let data = null;
|
|
2560
|
+
let status;
|
|
2561
|
+
if ("response" in err && err["response"] && typeof err["response"] === "object") {
|
|
2562
|
+
const response = err["response"];
|
|
2563
|
+
if ("status" in response && typeof response["status"] === "number") {
|
|
2564
|
+
statusCode2 = response["status"];
|
|
2565
|
+
}
|
|
2566
|
+
if ("data" in response && response["data"] !== void 0) {
|
|
2567
|
+
data = response["data"];
|
|
2568
|
+
if (data && typeof data === "object" && "status" in data) {
|
|
2569
|
+
const dataObj = data;
|
|
2570
|
+
if (typeof dataObj["status"] === "string") {
|
|
2571
|
+
status = dataObj["status"];
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
if (statusCode2 === null && "statusCode" in err && typeof err["statusCode"] === "number") {
|
|
2577
|
+
statusCode2 = err["statusCode"];
|
|
2578
|
+
}
|
|
2579
|
+
if (data === null && "data" in err && err["data"] !== void 0) {
|
|
2580
|
+
data = err["data"];
|
|
2581
|
+
}
|
|
2582
|
+
if (!status && "status" in err && typeof err["status"] === "string") {
|
|
2583
|
+
status = err["status"];
|
|
2584
|
+
}
|
|
2585
|
+
return {
|
|
2586
|
+
message: parseAxiosErrorMessage(error),
|
|
2587
|
+
statusCode: statusCode2,
|
|
2588
|
+
data,
|
|
2589
|
+
...status !== void 0 && { status }
|
|
2590
|
+
};
|
|
2591
|
+
} catch (err) {
|
|
2592
|
+
logger2.error("Error parsing error object", err);
|
|
2593
|
+
return {
|
|
2594
|
+
message: "An unexpected error occurred",
|
|
2595
|
+
statusCode: null,
|
|
2596
|
+
data: null
|
|
2597
|
+
};
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2600
|
+
var simpleParseResponse = (response) => {
|
|
2601
|
+
return response?.data?.data?.data;
|
|
2602
|
+
};
|
|
2603
|
+
var simpleMetaParseResponse = (response) => {
|
|
2604
|
+
return response?.data?.data?.meta;
|
|
2605
|
+
};
|
|
2606
|
+
var simpleParseDualDataResponse = (response) => {
|
|
2607
|
+
return response?.data?.data;
|
|
2608
|
+
};
|
|
2609
|
+
|
|
2610
|
+
// src/client/http/http.ts
|
|
2611
|
+
var isDevelopment2 = typeof window !== "undefined" && window.location.hostname === "localhost";
|
|
2612
|
+
var API_BASE_URL = isDevelopment2 ? "http://localhost:4002" : "https://service-api.exyconn.com";
|
|
2613
|
+
var API_PREFIX = "/v1/api";
|
|
2614
|
+
var axiosInstance = axios.create({
|
|
2615
|
+
baseURL: API_BASE_URL,
|
|
2616
|
+
timeout: 3e4,
|
|
2617
|
+
// 30 seconds
|
|
2618
|
+
headers: {
|
|
2619
|
+
"Content-Type": "application/json"
|
|
1706
2620
|
}
|
|
1707
|
-
|
|
1708
|
-
|
|
2621
|
+
});
|
|
2622
|
+
axiosInstance.interceptors.request.use(
|
|
2623
|
+
(config) => {
|
|
2624
|
+
try {
|
|
2625
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
2626
|
+
const selectedOrg = localStorage.getItem("selectedOrganization");
|
|
2627
|
+
if (selectedOrg) {
|
|
2628
|
+
const org = JSON.parse(selectedOrg);
|
|
2629
|
+
if (org && org._id) {
|
|
2630
|
+
config.headers["x-organization-id"] = org._id;
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
} catch (error) {
|
|
2635
|
+
logger2.warn("Failed to read organization from localStorage", error);
|
|
2636
|
+
}
|
|
2637
|
+
return config;
|
|
2638
|
+
},
|
|
2639
|
+
(error) => {
|
|
2640
|
+
return Promise.reject(error);
|
|
1709
2641
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
2642
|
+
);
|
|
2643
|
+
axiosInstance.interceptors.response.use(
|
|
2644
|
+
(response) => response,
|
|
2645
|
+
(error) => {
|
|
2646
|
+
const parsedError = parseError(error);
|
|
2647
|
+
logger2.error("API Error", parsedError);
|
|
2648
|
+
return Promise.reject(parsedError);
|
|
1712
2649
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
2650
|
+
);
|
|
2651
|
+
var buildHeaders = (customHeaders) => {
|
|
2652
|
+
const headers = {
|
|
2653
|
+
"Content-Type": "application/json",
|
|
2654
|
+
...customHeaders
|
|
2655
|
+
};
|
|
2656
|
+
return headers;
|
|
2657
|
+
};
|
|
2658
|
+
var buildConfig2 = (params, customHeaders) => {
|
|
2659
|
+
const config = {
|
|
2660
|
+
headers: buildHeaders(customHeaders)
|
|
2661
|
+
};
|
|
2662
|
+
if (params) {
|
|
2663
|
+
config.params = params;
|
|
1715
2664
|
}
|
|
1716
|
-
return
|
|
2665
|
+
return config;
|
|
1717
2666
|
};
|
|
1718
|
-
var
|
|
1719
|
-
|
|
2667
|
+
var getRequest = async (url, params, customHeaders) => {
|
|
2668
|
+
const config = buildConfig2(params, customHeaders);
|
|
2669
|
+
return axiosInstance.get(url, config);
|
|
2670
|
+
};
|
|
2671
|
+
var postRequest = async (url, data, customHeaders) => {
|
|
2672
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2673
|
+
return axiosInstance.post(url, data, config);
|
|
1720
2674
|
};
|
|
1721
|
-
var
|
|
1722
|
-
|
|
2675
|
+
var putRequest = async (url, data, customHeaders) => {
|
|
2676
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2677
|
+
return axiosInstance.put(url, data, config);
|
|
1723
2678
|
};
|
|
1724
|
-
var
|
|
1725
|
-
|
|
2679
|
+
var patchRequest = async (url, data, customHeaders) => {
|
|
2680
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2681
|
+
return axiosInstance.patch(url, data, config);
|
|
1726
2682
|
};
|
|
1727
|
-
var
|
|
1728
|
-
|
|
2683
|
+
var deleteRequest = async (url, params, customHeaders) => {
|
|
2684
|
+
const config = buildConfig2(params, customHeaders);
|
|
2685
|
+
return axiosInstance.delete(url, config);
|
|
2686
|
+
};
|
|
2687
|
+
var uploadFile = async (url, file, additionalData) => {
|
|
2688
|
+
const formData = new FormData();
|
|
2689
|
+
formData.append("file", file);
|
|
2690
|
+
if (additionalData) {
|
|
2691
|
+
Object.entries(additionalData).forEach(([key, value]) => {
|
|
2692
|
+
formData.append(key, String(value));
|
|
2693
|
+
});
|
|
2694
|
+
}
|
|
2695
|
+
const config = {
|
|
2696
|
+
headers: {
|
|
2697
|
+
"Content-Type": "multipart/form-data"
|
|
2698
|
+
}
|
|
2699
|
+
};
|
|
2700
|
+
return axiosInstance.post(url, formData, config);
|
|
2701
|
+
};
|
|
2702
|
+
var extractData = (response) => {
|
|
2703
|
+
return parseResponseData(response.data);
|
|
2704
|
+
};
|
|
2705
|
+
var extractMessage = (response) => {
|
|
2706
|
+
return parseResponseMessage(response, "");
|
|
2707
|
+
};
|
|
2708
|
+
var isSuccess = (response) => {
|
|
2709
|
+
return response.status >= 200 && response.status < 300;
|
|
2710
|
+
};
|
|
2711
|
+
var extractPaginatedData = (response) => {
|
|
2712
|
+
return parsePaginatedResponse(response.data);
|
|
2713
|
+
};
|
|
2714
|
+
|
|
2715
|
+
// src/client/http/slug.ts
|
|
2716
|
+
var generateSlug = (text) => {
|
|
2717
|
+
if (!text) return "";
|
|
2718
|
+
return text.trim().replace(/[^\w\s]/g, "").replace(/\s+(.)/g, (_, char) => char.toUpperCase()).replace(/\s+/g, "").replace(/^(.)/, (_, char) => char.toLowerCase());
|
|
1729
2719
|
};
|
|
1730
|
-
var
|
|
1731
|
-
|
|
2720
|
+
var generateUrlSlug = (text) => {
|
|
2721
|
+
if (!text) return "";
|
|
2722
|
+
return text.trim().toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
1732
2723
|
};
|
|
1733
|
-
var
|
|
1734
|
-
|
|
1735
|
-
return
|
|
2724
|
+
var generateSnakeSlug = (text) => {
|
|
2725
|
+
if (!text) return "";
|
|
2726
|
+
return text.trim().toLowerCase().replace(/[^\w\s]/g, "").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
1736
2727
|
};
|
|
1737
2728
|
|
|
1738
2729
|
// src/client/logger/client-logger.ts
|
|
@@ -1888,40 +2879,6 @@ var formatRelativeTime = (date) => {
|
|
|
1888
2879
|
}
|
|
1889
2880
|
return "just now";
|
|
1890
2881
|
};
|
|
1891
|
-
var formatDateForInput = (date) => {
|
|
1892
|
-
const dateObj = new Date(date);
|
|
1893
|
-
return dateObj.toISOString().split("T")[0];
|
|
1894
|
-
};
|
|
1895
|
-
var formatDateTimeForInput = (date) => {
|
|
1896
|
-
const dateObj = new Date(date);
|
|
1897
|
-
return dateObj.toISOString().slice(0, 16);
|
|
1898
|
-
};
|
|
1899
|
-
var isToday = (date) => {
|
|
1900
|
-
const dateObj = new Date(date);
|
|
1901
|
-
const today = /* @__PURE__ */ new Date();
|
|
1902
|
-
return dateObj.getDate() === today.getDate() && dateObj.getMonth() === today.getMonth() && dateObj.getFullYear() === today.getFullYear();
|
|
1903
|
-
};
|
|
1904
|
-
var isPast = (date) => {
|
|
1905
|
-
return new Date(date).getTime() < Date.now();
|
|
1906
|
-
};
|
|
1907
|
-
var isFuture = (date) => {
|
|
1908
|
-
return new Date(date).getTime() > Date.now();
|
|
1909
|
-
};
|
|
1910
|
-
var addDays = (date, days) => {
|
|
1911
|
-
const dateObj = new Date(date);
|
|
1912
|
-
dateObj.setDate(dateObj.getDate() + days);
|
|
1913
|
-
return dateObj;
|
|
1914
|
-
};
|
|
1915
|
-
var startOfDay = (date) => {
|
|
1916
|
-
const dateObj = new Date(date);
|
|
1917
|
-
dateObj.setHours(0, 0, 0, 0);
|
|
1918
|
-
return dateObj;
|
|
1919
|
-
};
|
|
1920
|
-
var endOfDay = (date) => {
|
|
1921
|
-
const dateObj = new Date(date);
|
|
1922
|
-
dateObj.setHours(23, 59, 59, 999);
|
|
1923
|
-
return dateObj;
|
|
1924
|
-
};
|
|
1925
2882
|
|
|
1926
2883
|
// src/client/utils/clipboard.ts
|
|
1927
2884
|
var copyToClipboard = async (text) => {
|
|
@@ -1946,20 +2903,6 @@ var copyToClipboard = async (text) => {
|
|
|
1946
2903
|
return false;
|
|
1947
2904
|
}
|
|
1948
2905
|
};
|
|
1949
|
-
var readFromClipboard = async () => {
|
|
1950
|
-
try {
|
|
1951
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
1952
|
-
return await navigator.clipboard.readText();
|
|
1953
|
-
}
|
|
1954
|
-
return null;
|
|
1955
|
-
} catch (error) {
|
|
1956
|
-
console.error("Failed to read from clipboard:", error);
|
|
1957
|
-
return null;
|
|
1958
|
-
}
|
|
1959
|
-
};
|
|
1960
|
-
var isClipboardAvailable = () => {
|
|
1961
|
-
return !!(navigator.clipboard && window.isSecureContext);
|
|
1962
|
-
};
|
|
1963
2906
|
|
|
1964
2907
|
// src/client/utils/slug.ts
|
|
1965
2908
|
var slugify = (text) => {
|
|
@@ -1996,165 +2939,15 @@ var kebabToCamel = (text) => {
|
|
|
1996
2939
|
return text.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
1997
2940
|
};
|
|
1998
2941
|
|
|
1999
|
-
// src/client/utils/events.ts
|
|
2000
|
-
var EventEmitter = class {
|
|
2001
|
-
constructor() {
|
|
2002
|
-
this.handlers = /* @__PURE__ */ new Map();
|
|
2003
|
-
}
|
|
2004
|
-
/**
|
|
2005
|
-
* Subscribe to an event
|
|
2006
|
-
* @returns Unsubscribe function
|
|
2007
|
-
*/
|
|
2008
|
-
on(event, handler) {
|
|
2009
|
-
if (!this.handlers.has(event)) {
|
|
2010
|
-
this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
2011
|
-
}
|
|
2012
|
-
this.handlers.get(event).add(handler);
|
|
2013
|
-
return () => this.off(event, handler);
|
|
2014
|
-
}
|
|
2015
|
-
/**
|
|
2016
|
-
* Subscribe to an event once
|
|
2017
|
-
*/
|
|
2018
|
-
once(event, handler) {
|
|
2019
|
-
const wrappedHandler = (data) => {
|
|
2020
|
-
this.off(event, wrappedHandler);
|
|
2021
|
-
handler(data);
|
|
2022
|
-
};
|
|
2023
|
-
return this.on(event, wrappedHandler);
|
|
2024
|
-
}
|
|
2025
|
-
/**
|
|
2026
|
-
* Unsubscribe from an event
|
|
2027
|
-
*/
|
|
2028
|
-
off(event, handler) {
|
|
2029
|
-
const eventHandlers = this.handlers.get(event);
|
|
2030
|
-
if (eventHandlers) {
|
|
2031
|
-
eventHandlers.delete(handler);
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
/**
|
|
2035
|
-
* Emit an event
|
|
2036
|
-
*/
|
|
2037
|
-
emit(event, data) {
|
|
2038
|
-
const eventHandlers = this.handlers.get(event);
|
|
2039
|
-
if (eventHandlers) {
|
|
2040
|
-
eventHandlers.forEach((handler) => {
|
|
2041
|
-
try {
|
|
2042
|
-
handler(data);
|
|
2043
|
-
} catch (error) {
|
|
2044
|
-
console.error(`Error in event handler for "${String(event)}":`, error);
|
|
2045
|
-
}
|
|
2046
|
-
});
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
/**
|
|
2050
|
-
* Remove all handlers for an event (or all events)
|
|
2051
|
-
*/
|
|
2052
|
-
removeAllListeners(event) {
|
|
2053
|
-
if (event) {
|
|
2054
|
-
this.handlers.delete(event);
|
|
2055
|
-
} else {
|
|
2056
|
-
this.handlers.clear();
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
/**
|
|
2060
|
-
* Get count of listeners for an event
|
|
2061
|
-
*/
|
|
2062
|
-
listenerCount(event) {
|
|
2063
|
-
return this.handlers.get(event)?.size ?? 0;
|
|
2064
|
-
}
|
|
2065
|
-
};
|
|
2066
|
-
var createEventEmitter = () => {
|
|
2067
|
-
return new EventEmitter();
|
|
2068
|
-
};
|
|
2069
|
-
var appEvents = new EventEmitter();
|
|
2070
|
-
|
|
2071
|
-
// src/client/utils/api-urls.ts
|
|
2072
|
-
var ApiUrlBuilder = class {
|
|
2073
|
-
constructor(config) {
|
|
2074
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
2075
|
-
this.version = config.version || "";
|
|
2076
|
-
}
|
|
2077
|
-
/**
|
|
2078
|
-
* Build full URL from path
|
|
2079
|
-
*/
|
|
2080
|
-
build(path2) {
|
|
2081
|
-
const normalizedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
2082
|
-
const versionPath = this.version ? `/${this.version}` : "";
|
|
2083
|
-
return `${this.baseUrl}${versionPath}${normalizedPath}`;
|
|
2084
|
-
}
|
|
2085
|
-
/**
|
|
2086
|
-
* Build URL with query parameters
|
|
2087
|
-
*/
|
|
2088
|
-
buildWithParams(path2, params) {
|
|
2089
|
-
const url = this.build(path2);
|
|
2090
|
-
const filteredParams = Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join("&");
|
|
2091
|
-
return filteredParams ? `${url}?${filteredParams}` : url;
|
|
2092
|
-
}
|
|
2093
|
-
/**
|
|
2094
|
-
* Build URL with path parameters
|
|
2095
|
-
*/
|
|
2096
|
-
buildWithPathParams(template, params) {
|
|
2097
|
-
let path2 = template;
|
|
2098
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
2099
|
-
path2 = path2.replace(`:${key}`, String(value));
|
|
2100
|
-
path2 = path2.replace(`{${key}}`, String(value));
|
|
2101
|
-
});
|
|
2102
|
-
return this.build(path2);
|
|
2103
|
-
}
|
|
2104
|
-
/**
|
|
2105
|
-
* Get base URL
|
|
2106
|
-
*/
|
|
2107
|
-
getBaseUrl() {
|
|
2108
|
-
return this.baseUrl;
|
|
2109
|
-
}
|
|
2110
|
-
/**
|
|
2111
|
-
* Set new base URL
|
|
2112
|
-
*/
|
|
2113
|
-
setBaseUrl(baseUrl) {
|
|
2114
|
-
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
2115
|
-
}
|
|
2116
|
-
};
|
|
2117
|
-
var createApiUrlBuilder = (config) => {
|
|
2118
|
-
return new ApiUrlBuilder(config);
|
|
2119
|
-
};
|
|
2120
|
-
var createApiEndpoints = (builder) => ({
|
|
2121
|
-
// Auth endpoints
|
|
2122
|
-
auth: {
|
|
2123
|
-
login: () => builder.build("/auth/login"),
|
|
2124
|
-
register: () => builder.build("/auth/register"),
|
|
2125
|
-
logout: () => builder.build("/auth/logout"),
|
|
2126
|
-
refresh: () => builder.build("/auth/refresh"),
|
|
2127
|
-
me: () => builder.build("/auth/me"),
|
|
2128
|
-
forgotPassword: () => builder.build("/auth/forgot-password"),
|
|
2129
|
-
resetPassword: () => builder.build("/auth/reset-password")
|
|
2130
|
-
},
|
|
2131
|
-
// User endpoints
|
|
2132
|
-
users: {
|
|
2133
|
-
list: () => builder.build("/users"),
|
|
2134
|
-
get: (id) => builder.buildWithPathParams("/users/:id", { id }),
|
|
2135
|
-
create: () => builder.build("/users"),
|
|
2136
|
-
update: (id) => builder.buildWithPathParams("/users/:id", { id }),
|
|
2137
|
-
delete: (id) => builder.buildWithPathParams("/users/:id", { id })
|
|
2138
|
-
},
|
|
2139
|
-
// Generic CRUD factory
|
|
2140
|
-
crud: (resource) => ({
|
|
2141
|
-
list: () => builder.build(`/${resource}`),
|
|
2142
|
-
get: (id) => builder.buildWithPathParams(`/${resource}/:id`, { id }),
|
|
2143
|
-
create: () => builder.build(`/${resource}`),
|
|
2144
|
-
update: (id) => builder.buildWithPathParams(`/${resource}/:id`, { id }),
|
|
2145
|
-
delete: (id) => builder.buildWithPathParams(`/${resource}/:id`, { id })
|
|
2146
|
-
})
|
|
2147
|
-
});
|
|
2148
|
-
|
|
2149
2942
|
// src/client/utils/response-parser.ts
|
|
2150
|
-
var
|
|
2943
|
+
var isSuccessResponse2 = (response) => {
|
|
2151
2944
|
return response.success === true;
|
|
2152
2945
|
};
|
|
2153
|
-
var
|
|
2946
|
+
var isErrorResponse2 = (response) => {
|
|
2154
2947
|
return response.success === false;
|
|
2155
2948
|
};
|
|
2156
2949
|
var getResponseData = (response, defaultValue) => {
|
|
2157
|
-
if (
|
|
2950
|
+
if (isSuccessResponse2(response) && response.data !== void 0) {
|
|
2158
2951
|
return response.data;
|
|
2159
2952
|
}
|
|
2160
2953
|
return defaultValue;
|
|
@@ -4395,18 +5188,18 @@ function useLogger(componentName, props, options = {}) {
|
|
|
4395
5188
|
const {
|
|
4396
5189
|
logProps = true,
|
|
4397
5190
|
logLifecycle = true,
|
|
4398
|
-
logger:
|
|
5191
|
+
logger: logger3 = console.log
|
|
4399
5192
|
} = options;
|
|
4400
5193
|
const previousProps = useRef(props);
|
|
4401
5194
|
const renderCount = useRef(0);
|
|
4402
5195
|
renderCount.current++;
|
|
4403
5196
|
useEffect(() => {
|
|
4404
5197
|
if (logLifecycle) {
|
|
4405
|
-
|
|
5198
|
+
logger3(`[${componentName}] Mounted`);
|
|
4406
5199
|
}
|
|
4407
5200
|
return () => {
|
|
4408
5201
|
if (logLifecycle) {
|
|
4409
|
-
|
|
5202
|
+
logger3(`[${componentName}] Unmounted (rendered ${renderCount.current} times)`);
|
|
4410
5203
|
}
|
|
4411
5204
|
};
|
|
4412
5205
|
}, []);
|
|
@@ -4438,12 +5231,12 @@ function useLogger(componentName, props, options = {}) {
|
|
|
4438
5231
|
});
|
|
4439
5232
|
}
|
|
4440
5233
|
if (hasChanges) {
|
|
4441
|
-
|
|
5234
|
+
logger3(`[${componentName}] Props changed:`, changedProps);
|
|
4442
5235
|
}
|
|
4443
5236
|
previousProps.current = props;
|
|
4444
|
-
}, [componentName, props, logProps,
|
|
5237
|
+
}, [componentName, props, logProps, logger3]);
|
|
4445
5238
|
if (process.env.NODE_ENV === "development") {
|
|
4446
|
-
|
|
5239
|
+
logger3(`[${componentName}] Render #${renderCount.current}`);
|
|
4447
5240
|
}
|
|
4448
5241
|
}
|
|
4449
5242
|
var useLogger_default = useLogger;
|
|
@@ -7267,7 +8060,7 @@ __export(shared_exports, {
|
|
|
7267
8060
|
VALIDATION_PATTERNS: () => VALIDATION_PATTERNS,
|
|
7268
8061
|
VALIDATION_RULES: () => VALIDATION_RULES,
|
|
7269
8062
|
VISIBILITY: () => VISIBILITY,
|
|
7270
|
-
addDays: () => addDays
|
|
8063
|
+
addDays: () => addDays,
|
|
7271
8064
|
addHours: () => addHours,
|
|
7272
8065
|
addMinutes: () => addMinutes,
|
|
7273
8066
|
addMonths: () => addMonths,
|
|
@@ -7289,7 +8082,7 @@ __export(shared_exports, {
|
|
|
7289
8082
|
eachDayOfInterval: () => eachDayOfInterval,
|
|
7290
8083
|
eachMonthOfInterval: () => eachMonthOfInterval,
|
|
7291
8084
|
eachWeekOfInterval: () => eachWeekOfInterval,
|
|
7292
|
-
endOfDay: () => endOfDay
|
|
8085
|
+
endOfDay: () => endOfDay,
|
|
7293
8086
|
endOfMonth: () => endOfMonth,
|
|
7294
8087
|
endOfWeek: () => endOfWeek,
|
|
7295
8088
|
endOfYear: () => endOfYear,
|
|
@@ -7332,8 +8125,8 @@ __export(shared_exports, {
|
|
|
7332
8125
|
isDateBetween: () => isDateBetween,
|
|
7333
8126
|
isDev: () => isDev,
|
|
7334
8127
|
isEqual: () => isEqual,
|
|
7335
|
-
isFuture: () => isFuture
|
|
7336
|
-
isPast: () => isPast
|
|
8128
|
+
isFuture: () => isFuture,
|
|
8129
|
+
isPast: () => isPast,
|
|
7337
8130
|
isProd: () => isProd,
|
|
7338
8131
|
isSameDay: () => isSameDay,
|
|
7339
8132
|
isSameMonth: () => isSameMonth,
|
|
@@ -7343,7 +8136,7 @@ __export(shared_exports, {
|
|
|
7343
8136
|
isThisMonth: () => isThisMonth,
|
|
7344
8137
|
isThisWeek: () => isThisWeek,
|
|
7345
8138
|
isThisYear: () => isThisYear,
|
|
7346
|
-
isToday: () => isToday
|
|
8139
|
+
isToday: () => isToday,
|
|
7347
8140
|
isTomorrow: () => isTomorrow,
|
|
7348
8141
|
isValid: () => isValid,
|
|
7349
8142
|
isValidDate: () => isValidDate,
|
|
@@ -7363,7 +8156,7 @@ __export(shared_exports, {
|
|
|
7363
8156
|
setMinutes: () => setMinutes,
|
|
7364
8157
|
setSeconds: () => setSeconds,
|
|
7365
8158
|
setTime: () => setTime,
|
|
7366
|
-
startOfDay: () => startOfDay
|
|
8159
|
+
startOfDay: () => startOfDay,
|
|
7367
8160
|
startOfMonth: () => startOfMonth,
|
|
7368
8161
|
startOfWeek: () => startOfWeek,
|
|
7369
8162
|
startOfYear: () => startOfYear,
|
|
@@ -7857,7 +8650,7 @@ var formatRelativeTime2 = (date, baseDate) => {
|
|
|
7857
8650
|
};
|
|
7858
8651
|
var formatSmartDate = (date) => {
|
|
7859
8652
|
const parsed = parseDate(date);
|
|
7860
|
-
if (isToday
|
|
8653
|
+
if (isToday(parsed)) {
|
|
7861
8654
|
return `Today at ${format(parsed, DATE_FORMATS.TIME_SHORT)}`;
|
|
7862
8655
|
}
|
|
7863
8656
|
if (isYesterday(parsed)) {
|
|
@@ -7913,7 +8706,7 @@ var addTime = (date, amount, unit) => {
|
|
|
7913
8706
|
case "hours":
|
|
7914
8707
|
return addHours(parsed, amount);
|
|
7915
8708
|
case "days":
|
|
7916
|
-
return addDays
|
|
8709
|
+
return addDays(parsed, amount);
|
|
7917
8710
|
case "weeks":
|
|
7918
8711
|
return addWeeks(parsed, amount);
|
|
7919
8712
|
case "months":
|
|
@@ -7980,8 +8773,8 @@ var getMonthsInRange = (start, end) => {
|
|
|
7980
8773
|
var getDayBoundaries = (date) => {
|
|
7981
8774
|
const parsed = parseDate(date);
|
|
7982
8775
|
return {
|
|
7983
|
-
start: startOfDay
|
|
7984
|
-
end: endOfDay
|
|
8776
|
+
start: startOfDay(parsed),
|
|
8777
|
+
end: endOfDay(parsed)
|
|
7985
8778
|
};
|
|
7986
8779
|
};
|
|
7987
8780
|
var getWeekBoundaries = (date, weekStartsOn = 0) => {
|