@exyconn/common 2.3.2 → 2.3.4
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 +280 -49
- package/dist/client/http/index.d.ts +280 -49
- package/dist/client/http/index.js +564 -90
- package/dist/client/http/index.js.map +1 -1
- package/dist/client/http/index.mjs +520 -80
- 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 +573 -316
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +529 -287
- 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-D9a9oxQy.d.ts → index-CdbQ8YPt.d.ts} +51 -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-DuxL84IW.d.mts → index-guYdqefq.d.mts} +51 -39
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1214 -326
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1226 -338
- 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.js
CHANGED
|
@@ -73,6 +73,7 @@ __export(server_exports, {
|
|
|
73
73
|
authenticateJWT: () => authenticateJWT,
|
|
74
74
|
badRequestResponse: () => badRequestResponse,
|
|
75
75
|
buildConfig: () => buildConfig,
|
|
76
|
+
buildDeleteFilter: () => buildDeleteFilter,
|
|
76
77
|
buildFilter: () => buildFilter,
|
|
77
78
|
buildPagination: () => buildPagination,
|
|
78
79
|
buildPaginationMeta: () => buildPaginationMeta,
|
|
@@ -83,12 +84,15 @@ __export(server_exports, {
|
|
|
83
84
|
createApiKeyGenerator: () => createApiKeyGenerator,
|
|
84
85
|
createApiRateLimiter: () => createApiRateLimiter,
|
|
85
86
|
createBrandCorsOptions: () => createBrandCorsOptions,
|
|
87
|
+
createBulkDeleteHandler: () => createBulkDeleteHandler,
|
|
86
88
|
createConfig: () => createConfig,
|
|
87
89
|
createCorsOptions: () => createCorsOptions,
|
|
90
|
+
createCrudControllers: () => createCrudControllers,
|
|
88
91
|
createDdosRateLimiter: () => createDdosRateLimiter,
|
|
89
92
|
createLogger: () => createLogger,
|
|
90
93
|
createMorganStream: () => createMorganStream,
|
|
91
94
|
createMultiBrandCorsOptions: () => createMultiBrandCorsOptions,
|
|
95
|
+
createPaginationMiddleware: () => createPaginationMiddleware,
|
|
92
96
|
createPrefixedKeyGenerator: () => createPrefixedKeyGenerator,
|
|
93
97
|
createRateLimiter: () => createRateLimiter,
|
|
94
98
|
createStandardRateLimiter: () => createStandardRateLimiter,
|
|
@@ -101,6 +105,7 @@ __export(server_exports, {
|
|
|
101
105
|
errorResponse: () => errorResponse,
|
|
102
106
|
extractColumns: () => extractColumns,
|
|
103
107
|
extractOrganization: () => extractOrganization,
|
|
108
|
+
extractSchemaMeta: () => extractSchemaMeta,
|
|
104
109
|
forbiddenResponse: () => forbiddenResponse,
|
|
105
110
|
formatPackageCheckResult: () => formatPackageCheckResult,
|
|
106
111
|
generateNcuCommand: () => generateNcuCommand,
|
|
@@ -115,8 +120,11 @@ __export(server_exports, {
|
|
|
115
120
|
omitFields: () => omitFields,
|
|
116
121
|
optionalAuthenticateJWT: () => optionalAuthenticateJWT,
|
|
117
122
|
packageCheckServer: () => packageCheckServer,
|
|
123
|
+
parseBulkDelete: () => parseBulkDelete,
|
|
118
124
|
pickFields: () => pickFields,
|
|
119
125
|
printPackageCheckSummary: () => printPackageCheckSummary,
|
|
126
|
+
queryPagination: () => queryPagination,
|
|
127
|
+
queryParser: () => queryParser,
|
|
120
128
|
rateLimitResponse: () => rateLimitResponse,
|
|
121
129
|
rateLimiter: () => rateLimiter,
|
|
122
130
|
requireOrganization: () => requireOrganization,
|
|
@@ -410,37 +418,37 @@ var defaultOptions = {
|
|
|
410
418
|
retryReads: true,
|
|
411
419
|
w: "majority"
|
|
412
420
|
};
|
|
413
|
-
var connectDB = async (mongoUri, options = {},
|
|
421
|
+
var connectDB = async (mongoUri, options = {}, logger3) => {
|
|
414
422
|
if (mongoose__default.default.connection.readyState === 1) {
|
|
415
|
-
|
|
423
|
+
logger3?.info("Database already connected, reusing connection");
|
|
416
424
|
return mongoose__default.default;
|
|
417
425
|
}
|
|
418
426
|
const finalOptions = { ...defaultOptions, ...options };
|
|
419
427
|
try {
|
|
420
428
|
await mongoose__default.default.connect(mongoUri, finalOptions);
|
|
421
|
-
|
|
429
|
+
logger3?.info("MongoDB connected successfully");
|
|
422
430
|
mongoose__default.default.connection.on("error", (err) => {
|
|
423
|
-
|
|
431
|
+
logger3?.error("MongoDB connection error", err);
|
|
424
432
|
});
|
|
425
433
|
mongoose__default.default.connection.on("disconnected", () => {
|
|
426
|
-
|
|
434
|
+
logger3?.info("MongoDB disconnected");
|
|
427
435
|
});
|
|
428
436
|
mongoose__default.default.connection.on("reconnected", () => {
|
|
429
|
-
|
|
437
|
+
logger3?.info("MongoDB reconnected");
|
|
430
438
|
});
|
|
431
439
|
return mongoose__default.default;
|
|
432
440
|
} catch (error) {
|
|
433
441
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
434
|
-
|
|
442
|
+
logger3?.error("MongoDB connection failed", { error: errorMessage });
|
|
435
443
|
throw error;
|
|
436
444
|
}
|
|
437
445
|
};
|
|
438
|
-
var disconnectDB = async (
|
|
446
|
+
var disconnectDB = async (logger3) => {
|
|
439
447
|
try {
|
|
440
448
|
await mongoose__default.default.disconnect();
|
|
441
|
-
|
|
449
|
+
logger3?.info("MongoDB disconnected successfully");
|
|
442
450
|
} catch (error) {
|
|
443
|
-
|
|
451
|
+
logger3?.error("Error disconnecting from MongoDB", error);
|
|
444
452
|
throw error;
|
|
445
453
|
}
|
|
446
454
|
};
|
|
@@ -545,6 +553,629 @@ var requireOrganization = (req, res, next) => {
|
|
|
545
553
|
next();
|
|
546
554
|
};
|
|
547
555
|
|
|
556
|
+
// src/server/middleware/queryParser.middleware.ts
|
|
557
|
+
var queryParser = (req, _, next) => {
|
|
558
|
+
const { page, limit, sort, sortBy, sortOrder, search, filter, ...otherParams } = req.query;
|
|
559
|
+
const parsed = {
|
|
560
|
+
page: Math.max(Number(page) || 1, 1),
|
|
561
|
+
limit: Math.min(Number(limit) || 10, 100),
|
|
562
|
+
filter: {}
|
|
563
|
+
};
|
|
564
|
+
if (typeof sort === "string") {
|
|
565
|
+
const [field, order] = sort.split(":");
|
|
566
|
+
parsed.sort = {
|
|
567
|
+
field,
|
|
568
|
+
order: order === "asc" ? "asc" : "desc"
|
|
569
|
+
};
|
|
570
|
+
} else if (typeof sortBy === "string") {
|
|
571
|
+
parsed.sort = {
|
|
572
|
+
field: sortBy,
|
|
573
|
+
order: sortOrder === "asc" ? "asc" : "desc"
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
if (typeof search === "string") {
|
|
577
|
+
parsed.search = search;
|
|
578
|
+
}
|
|
579
|
+
if (typeof filter === "object" && filter !== null) {
|
|
580
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
581
|
+
if (value !== "all") {
|
|
582
|
+
parsed.filter[key] = value;
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
Object.entries(otherParams).forEach(([key, value]) => {
|
|
587
|
+
if (typeof value === "string" && value !== "all" && !["page", "limit", "sort", "sortBy", "sortOrder", "search"].includes(key)) {
|
|
588
|
+
parsed.filter[key] = value;
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
req.parsedQuery = parsed;
|
|
592
|
+
next();
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// src/server/middleware/utils/schemaMeta.util.ts
|
|
596
|
+
var getZodTypeName = (schema) => {
|
|
597
|
+
const typeName = schema._def?.typeName;
|
|
598
|
+
switch (typeName) {
|
|
599
|
+
case "ZodString":
|
|
600
|
+
return "string";
|
|
601
|
+
case "ZodNumber":
|
|
602
|
+
return "number";
|
|
603
|
+
case "ZodBoolean":
|
|
604
|
+
return "boolean";
|
|
605
|
+
case "ZodDate":
|
|
606
|
+
return "date";
|
|
607
|
+
case "ZodArray":
|
|
608
|
+
return "array";
|
|
609
|
+
case "ZodObject":
|
|
610
|
+
return "object";
|
|
611
|
+
case "ZodOptional":
|
|
612
|
+
case "ZodNullable":
|
|
613
|
+
return schema._def?.innerType ? getZodTypeName(schema._def.innerType) : "unknown";
|
|
614
|
+
case "ZodDefault":
|
|
615
|
+
return schema._def?.innerType ? getZodTypeName(schema._def.innerType) : "unknown";
|
|
616
|
+
case "ZodEnum":
|
|
617
|
+
return "enum";
|
|
618
|
+
case "ZodUnion":
|
|
619
|
+
return "union";
|
|
620
|
+
default:
|
|
621
|
+
return "unknown";
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
var isZodRequired = (schema) => {
|
|
625
|
+
const typeName = schema._def?.typeName;
|
|
626
|
+
return typeName !== "ZodOptional" && typeName !== "ZodNullable";
|
|
627
|
+
};
|
|
628
|
+
var extractSchemaMeta = (model, zodSchema) => {
|
|
629
|
+
const columns = [];
|
|
630
|
+
if (zodSchema && zodSchema.shape) {
|
|
631
|
+
const shape = zodSchema.shape;
|
|
632
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
633
|
+
if (key.startsWith("_")) continue;
|
|
634
|
+
columns.push({
|
|
635
|
+
name: key,
|
|
636
|
+
datatype: getZodTypeName(value),
|
|
637
|
+
required: isZodRequired(value)
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
return columns;
|
|
641
|
+
}
|
|
642
|
+
try {
|
|
643
|
+
const schema = model.schema;
|
|
644
|
+
const paths = schema.paths;
|
|
645
|
+
for (const [key, pathInfo] of Object.entries(paths)) {
|
|
646
|
+
if (key.startsWith("_") || key === "__v") continue;
|
|
647
|
+
const schemaType = pathInfo;
|
|
648
|
+
columns.push({
|
|
649
|
+
name: key,
|
|
650
|
+
datatype: (schemaType.instance || "unknown").toLowerCase(),
|
|
651
|
+
required: schemaType.isRequired || false
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
} catch {
|
|
655
|
+
}
|
|
656
|
+
return columns;
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// src/server/middleware/pagination.middleware.ts
|
|
660
|
+
var queryPagination = (model, options = {}, withOrgId = true) => {
|
|
661
|
+
return async (req, res, next) => {
|
|
662
|
+
try {
|
|
663
|
+
const { page, limit, sort, search, filter } = req.parsedQuery;
|
|
664
|
+
const query = {};
|
|
665
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
666
|
+
if (options.regexFilterFields?.includes(key)) {
|
|
667
|
+
query[key] = { $regex: value, $options: "i" };
|
|
668
|
+
} else {
|
|
669
|
+
query[key] = value;
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
const organizationId = req.headers["x-organization-id"];
|
|
673
|
+
if (organizationId && typeof organizationId === "string" && withOrgId) {
|
|
674
|
+
query.organizationId = organizationId;
|
|
675
|
+
}
|
|
676
|
+
if (search && options.searchFields?.length) {
|
|
677
|
+
query.$or = options.searchFields.map((field) => ({
|
|
678
|
+
[field]: { $regex: search, $options: "i" }
|
|
679
|
+
}));
|
|
680
|
+
}
|
|
681
|
+
const sortQuery = sort ? { [sort.field]: sort.order } : { createdAt: "desc" };
|
|
682
|
+
const skip = (page - 1) * limit;
|
|
683
|
+
const [data, total] = await Promise.all([
|
|
684
|
+
model.find(query).sort(sortQuery).skip(skip).limit(limit),
|
|
685
|
+
model.countDocuments(query)
|
|
686
|
+
]);
|
|
687
|
+
res.paginatedResult = {
|
|
688
|
+
data,
|
|
689
|
+
meta: {
|
|
690
|
+
page,
|
|
691
|
+
limit,
|
|
692
|
+
total,
|
|
693
|
+
totalPages: Math.ceil(total / limit)
|
|
694
|
+
},
|
|
695
|
+
columns: extractSchemaMeta(model, options.validatorSchema)
|
|
696
|
+
};
|
|
697
|
+
next();
|
|
698
|
+
} catch (error) {
|
|
699
|
+
next(error);
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
};
|
|
703
|
+
var isZodError = (error) => {
|
|
704
|
+
return error !== null && typeof error === "object" && "errors" in error && Array.isArray(error.errors);
|
|
705
|
+
};
|
|
706
|
+
var getOrgId = (req, orgField = "organizationId") => {
|
|
707
|
+
const orgReq = req;
|
|
708
|
+
return orgReq.organizationId || req.headers["x-organization-id"] || req.query[orgField];
|
|
709
|
+
};
|
|
710
|
+
var buildOrgFilter = (req, config) => {
|
|
711
|
+
const filter = {};
|
|
712
|
+
if (config.withOrganization !== false) {
|
|
713
|
+
const orgId = getOrgId(req, config.orgField);
|
|
714
|
+
if (orgId) {
|
|
715
|
+
filter[config.orgField || "organizationId"] = orgId;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return filter;
|
|
719
|
+
};
|
|
720
|
+
var formatZodError = (error) => {
|
|
721
|
+
return error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
722
|
+
};
|
|
723
|
+
function createCrudControllers(config) {
|
|
724
|
+
const {
|
|
725
|
+
model,
|
|
726
|
+
resourceName,
|
|
727
|
+
createSchema,
|
|
728
|
+
updateSchema,
|
|
729
|
+
searchFields = [],
|
|
730
|
+
regexFilterFields = [],
|
|
731
|
+
withOrganization = true,
|
|
732
|
+
orgField = "organizationId",
|
|
733
|
+
transformCreate,
|
|
734
|
+
transformUpdate,
|
|
735
|
+
afterCreate,
|
|
736
|
+
afterUpdate,
|
|
737
|
+
afterDelete,
|
|
738
|
+
excludeFields = [],
|
|
739
|
+
populateFields = [],
|
|
740
|
+
buildQuery
|
|
741
|
+
} = config;
|
|
742
|
+
const getAll = async (req, res, _next) => {
|
|
743
|
+
try {
|
|
744
|
+
const paginatedRes = res;
|
|
745
|
+
if (paginatedRes.paginatedResult) {
|
|
746
|
+
successResponse(res, paginatedRes.paginatedResult, `${resourceName} list fetched successfully`);
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
const page = parseInt(req.query.page) || 1;
|
|
750
|
+
const limit = parseInt(req.query.limit) || 10;
|
|
751
|
+
const sortField = req.query.sortBy || "createdAt";
|
|
752
|
+
const sortOrder = req.query.sortOrder || "desc";
|
|
753
|
+
const search = req.query.search;
|
|
754
|
+
let query = {};
|
|
755
|
+
if (withOrganization) {
|
|
756
|
+
const orgId = getOrgId(req, orgField);
|
|
757
|
+
if (orgId) {
|
|
758
|
+
query[orgField] = orgId;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
if (search && searchFields.length > 0) {
|
|
762
|
+
query.$or = searchFields.map((field) => ({
|
|
763
|
+
[field]: { $regex: search, $options: "i" }
|
|
764
|
+
}));
|
|
765
|
+
}
|
|
766
|
+
const filterableParams = Object.keys(req.query).filter(
|
|
767
|
+
(key) => !["page", "limit", "sortBy", "sortOrder", "search"].includes(key)
|
|
768
|
+
);
|
|
769
|
+
filterableParams.forEach((key) => {
|
|
770
|
+
const value = req.query[key];
|
|
771
|
+
if (value !== void 0 && value !== "" && value !== "all") {
|
|
772
|
+
if (regexFilterFields.includes(key)) {
|
|
773
|
+
query[key] = { $regex: value, $options: "i" };
|
|
774
|
+
} else {
|
|
775
|
+
query[key] = value;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
if (buildQuery) {
|
|
780
|
+
query = buildQuery(req, query);
|
|
781
|
+
}
|
|
782
|
+
const sortQuery = { [sortField]: sortOrder };
|
|
783
|
+
const skip = (page - 1) * limit;
|
|
784
|
+
let projection = {};
|
|
785
|
+
if (excludeFields.length > 0) {
|
|
786
|
+
projection = excludeFields.reduce(
|
|
787
|
+
(acc, field) => ({ ...acc, [field]: 0 }),
|
|
788
|
+
{}
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
let dbQuery = model.find(query, projection);
|
|
792
|
+
if (populateFields.length > 0) {
|
|
793
|
+
populateFields.forEach((field) => {
|
|
794
|
+
dbQuery = dbQuery.populate(field);
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
const [data, total] = await Promise.all([
|
|
798
|
+
dbQuery.sort(sortQuery).skip(skip).limit(limit),
|
|
799
|
+
model.countDocuments(query)
|
|
800
|
+
]);
|
|
801
|
+
successResponse(
|
|
802
|
+
res,
|
|
803
|
+
{
|
|
804
|
+
data,
|
|
805
|
+
meta: {
|
|
806
|
+
page,
|
|
807
|
+
limit,
|
|
808
|
+
total,
|
|
809
|
+
totalPages: Math.ceil(total / limit)
|
|
810
|
+
},
|
|
811
|
+
columns: extractSchemaMeta(model, createSchema)
|
|
812
|
+
},
|
|
813
|
+
`${resourceName} list fetched successfully`
|
|
814
|
+
);
|
|
815
|
+
} catch (error) {
|
|
816
|
+
logger.error(`Error in getAll ${resourceName}`, {
|
|
817
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
818
|
+
});
|
|
819
|
+
errorResponse(res, `Failed to fetch ${resourceName.toLowerCase()} list`);
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
const getById = async (req, res, _next) => {
|
|
823
|
+
try {
|
|
824
|
+
const { id } = req.params;
|
|
825
|
+
if (!id || !mongoose.Types.ObjectId.isValid(id)) {
|
|
826
|
+
badRequestResponse(res, "Invalid ID format");
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
const query = {
|
|
830
|
+
_id: new mongoose.Types.ObjectId(id),
|
|
831
|
+
...buildOrgFilter(req, { ...config, withOrganization, orgField })
|
|
832
|
+
};
|
|
833
|
+
let dbQuery = model.findOne(query);
|
|
834
|
+
if (populateFields.length > 0) {
|
|
835
|
+
populateFields.forEach((field) => {
|
|
836
|
+
dbQuery = dbQuery.populate(field);
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
const doc = await dbQuery;
|
|
840
|
+
if (!doc) {
|
|
841
|
+
notFoundResponse(res, `${resourceName} not found`);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
successResponse(res, doc, `${resourceName} fetched successfully`);
|
|
845
|
+
} catch (error) {
|
|
846
|
+
logger.error(`Error in getById ${resourceName}`, {
|
|
847
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
848
|
+
id: req.params.id
|
|
849
|
+
});
|
|
850
|
+
errorResponse(res, `Failed to fetch ${resourceName.toLowerCase()}`);
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
const create = async (req, res, _next) => {
|
|
854
|
+
try {
|
|
855
|
+
let input = req.body;
|
|
856
|
+
if (createSchema) {
|
|
857
|
+
try {
|
|
858
|
+
input = createSchema.parse(input);
|
|
859
|
+
} catch (error) {
|
|
860
|
+
if (isZodError(error)) {
|
|
861
|
+
badRequestResponse(res, formatZodError(error));
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
throw error;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
if (transformCreate) {
|
|
868
|
+
input = transformCreate(input, req);
|
|
869
|
+
}
|
|
870
|
+
if (withOrganization) {
|
|
871
|
+
const orgId = getOrgId(req, orgField);
|
|
872
|
+
if (orgId) {
|
|
873
|
+
input[orgField] = orgId;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
const doc = new model(input);
|
|
877
|
+
await doc.save();
|
|
878
|
+
if (afterCreate) {
|
|
879
|
+
await afterCreate(doc, req);
|
|
880
|
+
}
|
|
881
|
+
logger.info(`${resourceName} created successfully`, {
|
|
882
|
+
id: doc._id,
|
|
883
|
+
[orgField]: input[orgField]
|
|
884
|
+
});
|
|
885
|
+
createdResponse(res, doc, `${resourceName} created successfully`);
|
|
886
|
+
} catch (error) {
|
|
887
|
+
logger.error(`Error in create ${resourceName}`, {
|
|
888
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
889
|
+
});
|
|
890
|
+
if (error.code === 11e3) {
|
|
891
|
+
badRequestResponse(res, `A ${resourceName.toLowerCase()} with this data already exists`);
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
errorResponse(res, `Failed to create ${resourceName.toLowerCase()}`);
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
const update = async (req, res, _next) => {
|
|
898
|
+
try {
|
|
899
|
+
const { id } = req.params;
|
|
900
|
+
if (!id || !mongoose.Types.ObjectId.isValid(id)) {
|
|
901
|
+
badRequestResponse(res, "Invalid ID format");
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
let input = req.body;
|
|
905
|
+
if (updateSchema) {
|
|
906
|
+
try {
|
|
907
|
+
input = updateSchema.parse(input);
|
|
908
|
+
} catch (error) {
|
|
909
|
+
if (isZodError(error)) {
|
|
910
|
+
badRequestResponse(res, formatZodError(error));
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
throw error;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
if (transformUpdate) {
|
|
917
|
+
input = transformUpdate(input, req);
|
|
918
|
+
}
|
|
919
|
+
const query = {
|
|
920
|
+
_id: new mongoose.Types.ObjectId(id),
|
|
921
|
+
...buildOrgFilter(req, { ...config, withOrganization, orgField })
|
|
922
|
+
};
|
|
923
|
+
const doc = await model.findOneAndUpdate(query, { $set: input }, { new: true });
|
|
924
|
+
if (!doc) {
|
|
925
|
+
notFoundResponse(res, `${resourceName} not found`);
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
if (afterUpdate) {
|
|
929
|
+
await afterUpdate(doc, req);
|
|
930
|
+
}
|
|
931
|
+
logger.info(`${resourceName} updated successfully`, { id });
|
|
932
|
+
successResponse(res, doc, `${resourceName} updated successfully`);
|
|
933
|
+
} catch (error) {
|
|
934
|
+
logger.error(`Error in update ${resourceName}`, {
|
|
935
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
936
|
+
id: req.params.id
|
|
937
|
+
});
|
|
938
|
+
errorResponse(res, `Failed to update ${resourceName.toLowerCase()}`);
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
const deleteOne = async (req, res, _next) => {
|
|
942
|
+
try {
|
|
943
|
+
const { id } = req.params;
|
|
944
|
+
if (!id || !mongoose.Types.ObjectId.isValid(id)) {
|
|
945
|
+
badRequestResponse(res, "Invalid ID format");
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const query = {
|
|
949
|
+
_id: new mongoose.Types.ObjectId(id),
|
|
950
|
+
...buildOrgFilter(req, { ...config, withOrganization, orgField })
|
|
951
|
+
};
|
|
952
|
+
const result = await model.deleteOne(query);
|
|
953
|
+
if (result.deletedCount === 0) {
|
|
954
|
+
notFoundResponse(res, `${resourceName} not found`);
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
if (afterDelete) {
|
|
958
|
+
await afterDelete(id, req);
|
|
959
|
+
}
|
|
960
|
+
logger.info(`${resourceName} deleted successfully`, { id });
|
|
961
|
+
noContentResponse(res, null, `${resourceName} deleted successfully`);
|
|
962
|
+
} catch (error) {
|
|
963
|
+
logger.error(`Error in delete ${resourceName}`, {
|
|
964
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
965
|
+
id: req.params.id
|
|
966
|
+
});
|
|
967
|
+
errorResponse(res, `Failed to delete ${resourceName.toLowerCase()}`);
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
const bulkDelete = async (req, res, _next) => {
|
|
971
|
+
try {
|
|
972
|
+
const bulkReq = req;
|
|
973
|
+
const { deleteIds = [], deleteAll = false } = bulkReq;
|
|
974
|
+
const baseFilter = buildOrgFilter(req, { ...config, withOrganization, orgField });
|
|
975
|
+
let filter;
|
|
976
|
+
if (deleteAll) {
|
|
977
|
+
filter = baseFilter;
|
|
978
|
+
} else if (deleteIds.length > 0) {
|
|
979
|
+
filter = {
|
|
980
|
+
...baseFilter,
|
|
981
|
+
_id: { $in: deleteIds.map((id) => new mongoose.Types.ObjectId(id)) }
|
|
982
|
+
};
|
|
983
|
+
} else {
|
|
984
|
+
badRequestResponse(res, "No IDs provided for deletion");
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
const result = await model.deleteMany(filter);
|
|
988
|
+
if (afterDelete && deleteIds.length > 0) {
|
|
989
|
+
await Promise.all(deleteIds.map((id) => afterDelete(id, req)));
|
|
990
|
+
}
|
|
991
|
+
logger.info(`${resourceName}(s) bulk deleted successfully`, {
|
|
992
|
+
deletedCount: result.deletedCount,
|
|
993
|
+
deleteAll
|
|
994
|
+
});
|
|
995
|
+
successResponse(
|
|
996
|
+
res,
|
|
997
|
+
{ deletedCount: result.deletedCount },
|
|
998
|
+
`${result.deletedCount} ${resourceName.toLowerCase()}(s) deleted successfully`
|
|
999
|
+
);
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
logger.error(`Error in bulkDelete ${resourceName}`, {
|
|
1002
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1003
|
+
});
|
|
1004
|
+
errorResponse(res, `Failed to delete ${resourceName.toLowerCase()}(s)`);
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
return {
|
|
1008
|
+
getAll,
|
|
1009
|
+
getById,
|
|
1010
|
+
create,
|
|
1011
|
+
update,
|
|
1012
|
+
deleteOne,
|
|
1013
|
+
bulkDelete
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
function createPaginationMiddleware(model, config = {}) {
|
|
1017
|
+
const {
|
|
1018
|
+
searchFields = [],
|
|
1019
|
+
regexFilterFields = [],
|
|
1020
|
+
withOrganization = true,
|
|
1021
|
+
orgField = "organizationId"
|
|
1022
|
+
} = config;
|
|
1023
|
+
return async (req, res, next) => {
|
|
1024
|
+
try {
|
|
1025
|
+
const page = parseInt(req.query.page) || 1;
|
|
1026
|
+
const limit = parseInt(req.query.limit) || 10;
|
|
1027
|
+
const sortField = req.query.sortBy || "createdAt";
|
|
1028
|
+
const sortOrder = req.query.sortOrder || "desc";
|
|
1029
|
+
const search = req.query.search;
|
|
1030
|
+
const query = {};
|
|
1031
|
+
if (withOrganization) {
|
|
1032
|
+
const orgId = getOrgId(req, orgField);
|
|
1033
|
+
if (orgId) {
|
|
1034
|
+
query[orgField] = orgId;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
if (search && searchFields.length > 0) {
|
|
1038
|
+
query.$or = searchFields.map((field) => ({
|
|
1039
|
+
[field]: { $regex: search, $options: "i" }
|
|
1040
|
+
}));
|
|
1041
|
+
}
|
|
1042
|
+
const filterableParams = Object.keys(req.query).filter(
|
|
1043
|
+
(key) => !["page", "limit", "sortBy", "sortOrder", "search"].includes(key)
|
|
1044
|
+
);
|
|
1045
|
+
filterableParams.forEach((key) => {
|
|
1046
|
+
const value = req.query[key];
|
|
1047
|
+
if (value !== void 0 && value !== "" && value !== "all") {
|
|
1048
|
+
if (regexFilterFields.includes(key)) {
|
|
1049
|
+
query[key] = { $regex: value, $options: "i" };
|
|
1050
|
+
} else {
|
|
1051
|
+
query[key] = value;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
});
|
|
1055
|
+
const sortQuery = { [sortField]: sortOrder };
|
|
1056
|
+
const skip = (page - 1) * limit;
|
|
1057
|
+
const [data, total] = await Promise.all([
|
|
1058
|
+
model.find(query).sort(sortQuery).skip(skip).limit(limit),
|
|
1059
|
+
model.countDocuments(query)
|
|
1060
|
+
]);
|
|
1061
|
+
const paginatedRes = res;
|
|
1062
|
+
paginatedRes.paginatedResult = {
|
|
1063
|
+
data,
|
|
1064
|
+
meta: {
|
|
1065
|
+
page,
|
|
1066
|
+
limit,
|
|
1067
|
+
total,
|
|
1068
|
+
totalPages: Math.ceil(total / limit)
|
|
1069
|
+
},
|
|
1070
|
+
columns: extractSchemaMeta(model, config.createSchema)
|
|
1071
|
+
};
|
|
1072
|
+
next();
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
next(error);
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
var parseBulkDelete = (req, res, next) => {
|
|
1079
|
+
try {
|
|
1080
|
+
const bulkReq = req;
|
|
1081
|
+
let ids = [];
|
|
1082
|
+
if (Array.isArray(req.body)) {
|
|
1083
|
+
ids = req.body;
|
|
1084
|
+
} else if (req.body && Array.isArray(req.body.ids)) {
|
|
1085
|
+
ids = req.body.ids;
|
|
1086
|
+
} else if (req.body && typeof req.body === "object") {
|
|
1087
|
+
if (Array.isArray(req.body.data)) {
|
|
1088
|
+
ids = req.body.data;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
if (ids.length === 0) {
|
|
1092
|
+
return badRequestResponse(
|
|
1093
|
+
res,
|
|
1094
|
+
'Request body must contain an array of IDs. Use ["*"] to delete all records or ["id1", "id2"] to delete specific records.'
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
if (ids.length === 1 && ids[0] === "*") {
|
|
1098
|
+
bulkReq.deleteAll = true;
|
|
1099
|
+
bulkReq.deleteIds = [];
|
|
1100
|
+
logger.info("Bulk delete: Deleting all records");
|
|
1101
|
+
return next();
|
|
1102
|
+
}
|
|
1103
|
+
const validIds = [];
|
|
1104
|
+
const invalidIds = [];
|
|
1105
|
+
for (const id of ids) {
|
|
1106
|
+
if (typeof id === "string" && mongoose.Types.ObjectId.isValid(id)) {
|
|
1107
|
+
validIds.push(id);
|
|
1108
|
+
} else {
|
|
1109
|
+
invalidIds.push(id);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
if (invalidIds.length > 0) {
|
|
1113
|
+
return badRequestResponse(
|
|
1114
|
+
res,
|
|
1115
|
+
`Invalid ID format(s): ${invalidIds.slice(0, 5).join(", ")}${invalidIds.length > 5 ? "..." : ""}. All IDs must be valid MongoDB ObjectIds.`
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
if (validIds.length === 0) {
|
|
1119
|
+
return badRequestResponse(res, "No valid IDs provided for deletion.");
|
|
1120
|
+
}
|
|
1121
|
+
bulkReq.deleteAll = false;
|
|
1122
|
+
bulkReq.deleteIds = validIds;
|
|
1123
|
+
logger.info(`Bulk delete: Deleting ${validIds.length} record(s)`);
|
|
1124
|
+
next();
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
logger.error("Error in parseBulkDelete middleware", error);
|
|
1127
|
+
return badRequestResponse(res, "Failed to parse delete request");
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1130
|
+
var buildDeleteFilter = (req, organizationId) => {
|
|
1131
|
+
const filter = {
|
|
1132
|
+
organizationId: new mongoose.Types.ObjectId(organizationId)
|
|
1133
|
+
};
|
|
1134
|
+
if (!req.deleteAll && req.deleteIds && req.deleteIds.length > 0) {
|
|
1135
|
+
filter._id = {
|
|
1136
|
+
$in: req.deleteIds.map((id) => new mongoose.Types.ObjectId(id))
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
return filter;
|
|
1140
|
+
};
|
|
1141
|
+
var createBulkDeleteHandler = (Model2, modelName) => {
|
|
1142
|
+
return async (req, res) => {
|
|
1143
|
+
const bulkReq = req;
|
|
1144
|
+
const organizationId = req.headers["x-organization-id"];
|
|
1145
|
+
if (!organizationId) {
|
|
1146
|
+
return badRequestResponse(res, "Organization ID is required");
|
|
1147
|
+
}
|
|
1148
|
+
try {
|
|
1149
|
+
const filter = buildDeleteFilter(bulkReq, organizationId);
|
|
1150
|
+
const result = await Model2.deleteMany(filter);
|
|
1151
|
+
const deletedCount = result.deletedCount || 0;
|
|
1152
|
+
logger.info(`Bulk delete completed: ${deletedCount} ${modelName}(s) deleted`, {
|
|
1153
|
+
organizationId,
|
|
1154
|
+
deleteAll: bulkReq.deleteAll,
|
|
1155
|
+
requestedIds: bulkReq.deleteIds?.length || "all",
|
|
1156
|
+
deletedCount
|
|
1157
|
+
});
|
|
1158
|
+
return res.status(200).json({
|
|
1159
|
+
message: `Successfully deleted ${deletedCount} ${modelName}(s)`,
|
|
1160
|
+
data: {
|
|
1161
|
+
deletedCount,
|
|
1162
|
+
deleteAll: bulkReq.deleteAll
|
|
1163
|
+
},
|
|
1164
|
+
status: "success",
|
|
1165
|
+
statusCode: 200
|
|
1166
|
+
});
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
logger.error(`Error in bulk delete ${modelName}`, error);
|
|
1169
|
+
return res.status(500).json({
|
|
1170
|
+
message: `Failed to delete ${modelName}(s)`,
|
|
1171
|
+
data: null,
|
|
1172
|
+
status: "error",
|
|
1173
|
+
statusCode: 500
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
};
|
|
1177
|
+
};
|
|
1178
|
+
|
|
548
1179
|
// src/server/utils/filter-builder.ts
|
|
549
1180
|
var buildFilter = (options) => {
|
|
550
1181
|
const {
|
|
@@ -1502,34 +2133,34 @@ var getDatabaseOptions = (config) => {
|
|
|
1502
2133
|
// src/client/index.ts
|
|
1503
2134
|
var client_exports = {};
|
|
1504
2135
|
__export(client_exports, {
|
|
1505
|
-
|
|
2136
|
+
API_BASE_URL: () => API_BASE_URL,
|
|
2137
|
+
API_PREFIX: () => API_PREFIX,
|
|
1506
2138
|
ClientLogger: () => ClientLogger,
|
|
1507
2139
|
ContactForm: () => ContactForm,
|
|
1508
|
-
|
|
2140
|
+
ERROR_CODES: () => ERROR_CODES,
|
|
1509
2141
|
LoginForm: () => LoginForm,
|
|
1510
2142
|
NewsletterForm: () => NewsletterForm,
|
|
1511
2143
|
RegisterForm: () => RegisterForm,
|
|
2144
|
+
STATUS_CODES: () => STATUS_CODES,
|
|
2145
|
+
STATUS_MESSAGES: () => STATUS_MESSAGES,
|
|
2146
|
+
SUCCESS_CODES: () => SUCCESS_CODES,
|
|
1512
2147
|
ThemeContext: () => ThemeContext,
|
|
1513
2148
|
ThemeProvider: () => ThemeProvider,
|
|
1514
2149
|
ThemeToggle: () => ThemeToggle,
|
|
1515
2150
|
VALIDATION_MESSAGES: () => VALIDATION_MESSAGES,
|
|
1516
|
-
addDays: () => addDays,
|
|
1517
2151
|
adjustColor: () => adjustColor,
|
|
1518
|
-
|
|
2152
|
+
axios: () => axiosInstance,
|
|
1519
2153
|
camelToKebab: () => camelToKebab,
|
|
1520
2154
|
capitalize: () => capitalize,
|
|
1521
2155
|
capitalizeWords: () => capitalizeWords,
|
|
1522
|
-
|
|
2156
|
+
clearCustomHeaders: () => clearCustomHeaders,
|
|
1523
2157
|
clientLogger: () => clientLogger,
|
|
2158
|
+
configureHttp: () => configureHttp,
|
|
1524
2159
|
contactFormSchema: () => contactFormSchema,
|
|
1525
2160
|
copyToClipboard: () => copyToClipboard,
|
|
1526
|
-
createApiEndpoints: () => createApiEndpoints,
|
|
1527
|
-
createApiUrlBuilder: () => createApiUrlBuilder,
|
|
1528
2161
|
createClientLogger: () => createClientLogger,
|
|
1529
2162
|
createEmptyPaginationMeta: () => createEmptyPaginationMeta,
|
|
1530
2163
|
createErrorResponse: () => createErrorResponse,
|
|
1531
|
-
createEventEmitter: () => createEventEmitter,
|
|
1532
|
-
createHttpClient: () => createHttpClient,
|
|
1533
2164
|
createRegisterFormSchema: () => createRegisterFormSchema,
|
|
1534
2165
|
createSuccessResponse: () => createSuccessResponse,
|
|
1535
2166
|
createTheme: () => createTheme,
|
|
@@ -1538,6 +2169,7 @@ __export(client_exports, {
|
|
|
1538
2169
|
deepMerge: () => deepMerge2,
|
|
1539
2170
|
defaultDarkTheme: () => defaultDarkTheme,
|
|
1540
2171
|
defaultLightTheme: () => defaultLightTheme,
|
|
2172
|
+
deleteRequest: () => deleteRequest,
|
|
1541
2173
|
dummyBannerData: () => dummyBannerData,
|
|
1542
2174
|
dummyFaqItems: () => dummyFaqItems,
|
|
1543
2175
|
dummyFeatures: () => dummyFeatures,
|
|
@@ -1546,59 +2178,76 @@ __export(client_exports, {
|
|
|
1546
2178
|
dummyImage: () => dummyImage,
|
|
1547
2179
|
dummyPricingPlans: () => dummyPricingPlans,
|
|
1548
2180
|
dummyTestimonials: () => dummyTestimonials,
|
|
1549
|
-
|
|
2181
|
+
extractData: () => extractData,
|
|
2182
|
+
extractMessage: () => extractMessage,
|
|
2183
|
+
extractNestedData: () => extractNestedData,
|
|
2184
|
+
extractPaginatedData: () => extractPaginatedData,
|
|
1550
2185
|
flattenToCssVars: () => flattenToCssVars,
|
|
1551
2186
|
formatDate: () => formatDate,
|
|
1552
|
-
formatDateForInput: () => formatDateForInput,
|
|
1553
2187
|
formatDateTime: () => formatDateTime,
|
|
1554
|
-
formatDateTimeForInput: () => formatDateTimeForInput,
|
|
1555
|
-
formatPackageCheckResult: () => formatPackageCheckResult2,
|
|
1556
2188
|
formatRelativeTime: () => formatRelativeTime,
|
|
1557
2189
|
generateCssVars: () => generateCssVars,
|
|
1558
|
-
|
|
2190
|
+
generateSlug: () => generateSlug,
|
|
2191
|
+
generateSnakeSlug: () => generateSnakeSlug,
|
|
2192
|
+
generateUrlSlug: () => generateUrlSlug,
|
|
2193
|
+
getApiBaseUrl: () => getApiBaseUrl,
|
|
2194
|
+
getApiPrefix: () => getApiPrefix,
|
|
1559
2195
|
getContrastColor: () => getContrastColor,
|
|
2196
|
+
getCustomHeaders: () => getCustomHeaders,
|
|
1560
2197
|
getErrorMessage: () => getErrorMessage,
|
|
2198
|
+
getHttpConfig: () => getHttpConfig,
|
|
1561
2199
|
getNextPage: () => getNextPage,
|
|
1562
2200
|
getPrevPage: () => getPrevPage,
|
|
2201
|
+
getRequest: () => getRequest,
|
|
1563
2202
|
getResponseData: () => getResponseData,
|
|
1564
2203
|
getSystemColorScheme: () => getSystemColorScheme,
|
|
1565
2204
|
hasData: () => hasData,
|
|
1566
2205
|
hasMorePages: () => hasMorePages,
|
|
1567
2206
|
hexToRgba: () => hexToRgba,
|
|
1568
2207
|
injectCssVars: () => injectCssVars,
|
|
1569
|
-
isClipboardAvailable: () => isClipboardAvailable,
|
|
1570
2208
|
isErrorResponse: () => isErrorResponse,
|
|
1571
|
-
isForbidden: () => isForbidden,
|
|
1572
|
-
isFuture: () => isFuture,
|
|
1573
|
-
isNotFound: () => isNotFound,
|
|
1574
|
-
isPast: () => isPast,
|
|
1575
|
-
isServerError: () => isServerError,
|
|
1576
|
-
isStatusError: () => isStatusError,
|
|
1577
2209
|
isSuccess: () => isSuccess,
|
|
1578
2210
|
isSuccessResponse: () => isSuccessResponse,
|
|
1579
|
-
|
|
1580
|
-
|
|
2211
|
+
isUtilErrorResponse: () => isErrorResponse2,
|
|
2212
|
+
isUtilSuccessResponse: () => isSuccessResponse2,
|
|
1581
2213
|
kebabToCamel: () => kebabToCamel,
|
|
1582
2214
|
loadThemeFromUrl: () => loadThemeFromUrl,
|
|
1583
2215
|
loadThemeMode: () => loadThemeMode,
|
|
2216
|
+
logger: () => logger2,
|
|
1584
2217
|
loginFormSchema: () => loginFormSchema,
|
|
1585
2218
|
loremIpsum: () => loremIpsum,
|
|
1586
2219
|
newsletterFormSchema: () => newsletterFormSchema,
|
|
1587
2220
|
packageCheck: () => packageCheck,
|
|
2221
|
+
parseAxiosErrorMessage: () => parseAxiosErrorMessage,
|
|
1588
2222
|
parseError: () => parseError,
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
2223
|
+
parsePaginatedResponse: () => parsePaginatedResponse,
|
|
2224
|
+
parseResponseData: () => parseResponseData,
|
|
2225
|
+
parseResponseMessage: () => parseResponseMessage,
|
|
2226
|
+
parseResponseStatus: () => parseResponseStatus,
|
|
2227
|
+
parseResponseStatusMessage: () => parseResponseStatusMessage,
|
|
2228
|
+
patchRequest: () => patchRequest,
|
|
2229
|
+
postRequest: () => postRequest,
|
|
2230
|
+
putRequest: () => putRequest,
|
|
1592
2231
|
registerFormSchema: () => registerFormSchema,
|
|
1593
2232
|
removeCssVars: () => removeCssVars,
|
|
2233
|
+
removeCustomHeader: () => removeCustomHeader,
|
|
2234
|
+
resetHttpConfig: () => resetHttpConfig,
|
|
1594
2235
|
resolveThemeMode: () => resolveThemeMode,
|
|
2236
|
+
safeJsonParse: () => safeJsonParse,
|
|
1595
2237
|
saveThemeMode: () => saveThemeMode,
|
|
2238
|
+
setApiBaseUrl: () => setApiBaseUrl,
|
|
2239
|
+
setApiPrefix: () => setApiPrefix,
|
|
2240
|
+
setCustomHeader: () => setCustomHeader,
|
|
2241
|
+
setCustomHeaders: () => setCustomHeaders,
|
|
2242
|
+
simpleMetaParseResponse: () => simpleMetaParseResponse,
|
|
2243
|
+
simpleParseDualDataResponse: () => simpleParseDualDataResponse,
|
|
2244
|
+
simpleParseResponse: () => simpleParseResponse,
|
|
1596
2245
|
slugify: () => slugify,
|
|
1597
2246
|
slugifyUnique: () => slugifyUnique,
|
|
1598
|
-
startOfDay: () => startOfDay,
|
|
1599
2247
|
truncate: () => truncate,
|
|
1600
2248
|
truncateWords: () => truncateWords,
|
|
1601
2249
|
unslugify: () => unslugify,
|
|
2250
|
+
uploadFile: () => uploadFile,
|
|
1602
2251
|
useBattery: () => useBattery_default,
|
|
1603
2252
|
useClickAway: () => useClickAway_default,
|
|
1604
2253
|
useContinuousRetry: () => useContinuousRetry_default,
|
|
@@ -1658,112 +2307,549 @@ __export(client_exports, {
|
|
|
1658
2307
|
useToggle: () => useToggle_default,
|
|
1659
2308
|
useVisibilityChange: () => useVisibilityChange_default,
|
|
1660
2309
|
useWindowScroll: () => useWindowScroll_default,
|
|
1661
|
-
useWindowSize: () => useWindowSize_default
|
|
1662
|
-
withAbortSignal: () => withAbortSignal,
|
|
1663
|
-
withFormData: () => withFormData,
|
|
1664
|
-
withTimeout: () => withTimeout
|
|
2310
|
+
useWindowSize: () => useWindowSize_default
|
|
1665
2311
|
});
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
headers: {
|
|
1680
|
-
"Content-Type": "application/json"
|
|
2312
|
+
|
|
2313
|
+
// src/client/http/logger.ts
|
|
2314
|
+
var Logger = class {
|
|
2315
|
+
constructor() {
|
|
2316
|
+
this.isDevelopment = typeof window !== "undefined" && window.location.hostname === "localhost";
|
|
2317
|
+
}
|
|
2318
|
+
/**
|
|
2319
|
+
* Log informational messages
|
|
2320
|
+
*/
|
|
2321
|
+
info(message, data, options) {
|
|
2322
|
+
if (this.isDevelopment) {
|
|
2323
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2324
|
+
console.log(`${prefix} ${message}`, data ?? "");
|
|
1681
2325
|
}
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
2326
|
+
}
|
|
2327
|
+
/**
|
|
2328
|
+
* Log warning messages
|
|
2329
|
+
*/
|
|
2330
|
+
warn(message, data, options) {
|
|
2331
|
+
if (this.isDevelopment) {
|
|
2332
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2333
|
+
console.warn(`${prefix} ${message}`, data ?? "");
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* Log error messages
|
|
2338
|
+
*/
|
|
2339
|
+
error(message, error, options) {
|
|
2340
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2341
|
+
if (this.isDevelopment) {
|
|
2342
|
+
console.error(`${prefix} ${message}`, error, options?.metadata || "");
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* Log debug messages (only in development)
|
|
2347
|
+
*/
|
|
2348
|
+
debug(message, data, options) {
|
|
2349
|
+
if (this.isDevelopment) {
|
|
2350
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2351
|
+
console.debug(`${prefix} ${message}`, data || "");
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Log API errors with structured information
|
|
2356
|
+
*/
|
|
2357
|
+
apiError(endpoint, error, metadata) {
|
|
2358
|
+
this.error(`API Error: ${endpoint}`, error, {
|
|
2359
|
+
context: "API",
|
|
2360
|
+
metadata: {
|
|
2361
|
+
endpoint,
|
|
2362
|
+
...metadata
|
|
1690
2363
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
};
|
|
2367
|
+
var logger2 = new Logger();
|
|
2368
|
+
|
|
2369
|
+
// src/client/http/response-parser.ts
|
|
2370
|
+
var STATUS_CODES = {
|
|
2371
|
+
SUCCESS: 200,
|
|
2372
|
+
CREATED: 201,
|
|
2373
|
+
NO_CONTENT: 204,
|
|
2374
|
+
BAD_REQUEST: 400,
|
|
2375
|
+
UNAUTHORIZED: 401,
|
|
2376
|
+
FORBIDDEN: 403,
|
|
2377
|
+
NOT_FOUND: 404,
|
|
2378
|
+
CONFLICT: 409,
|
|
2379
|
+
ERROR: 500
|
|
2380
|
+
};
|
|
2381
|
+
var STATUS_MESSAGES = {
|
|
2382
|
+
SUCCESS: "success",
|
|
2383
|
+
CREATED: "created",
|
|
2384
|
+
NO_CONTENT: "no_content",
|
|
2385
|
+
BAD_REQUEST: "bad_request",
|
|
2386
|
+
UNAUTHORIZED: "unauthorized",
|
|
2387
|
+
FORBIDDEN: "forbidden",
|
|
2388
|
+
NOT_FOUND: "not_found",
|
|
2389
|
+
CONFLICT: "conflict",
|
|
2390
|
+
ERROR: "error"
|
|
2391
|
+
};
|
|
2392
|
+
var SUCCESS_CODES = [200, 201, 204];
|
|
2393
|
+
var ERROR_CODES = [400, 401, 403, 404, 409, 500];
|
|
2394
|
+
var parseResponseData = (response, fallback = null) => {
|
|
2395
|
+
try {
|
|
2396
|
+
if (!response || typeof response !== "object") {
|
|
2397
|
+
return fallback;
|
|
2398
|
+
}
|
|
2399
|
+
const resp = response;
|
|
2400
|
+
if ("data" in resp) {
|
|
2401
|
+
return resp["data"] ?? fallback;
|
|
2402
|
+
}
|
|
2403
|
+
return response;
|
|
2404
|
+
} catch (error) {
|
|
2405
|
+
logger2.error("Error parsing response data", error);
|
|
2406
|
+
return fallback;
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
var parseResponseMessage = (response, fallback = "") => {
|
|
2410
|
+
try {
|
|
2411
|
+
if (!response || typeof response !== "object") {
|
|
2412
|
+
return fallback;
|
|
2413
|
+
}
|
|
2414
|
+
const resp = response;
|
|
2415
|
+
if ("message" in resp && typeof resp["message"] === "string") {
|
|
2416
|
+
return resp["message"];
|
|
2417
|
+
}
|
|
2418
|
+
return fallback;
|
|
2419
|
+
} catch (error) {
|
|
2420
|
+
logger2.error("Error parsing response message", error);
|
|
2421
|
+
return fallback;
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
var parseResponseStatus = (response) => {
|
|
2425
|
+
try {
|
|
2426
|
+
if (!response || typeof response !== "object") {
|
|
2427
|
+
return null;
|
|
2428
|
+
}
|
|
2429
|
+
const resp = response;
|
|
2430
|
+
if ("statusCode" in resp && typeof resp["statusCode"] === "number") {
|
|
2431
|
+
return resp["statusCode"];
|
|
2432
|
+
}
|
|
2433
|
+
if ("status" in resp && typeof resp["status"] === "number") {
|
|
2434
|
+
return resp["status"];
|
|
2435
|
+
}
|
|
2436
|
+
return null;
|
|
2437
|
+
} catch (error) {
|
|
2438
|
+
logger2.error("Error parsing response status", error);
|
|
2439
|
+
return null;
|
|
2440
|
+
}
|
|
2441
|
+
};
|
|
2442
|
+
var parseResponseStatusMessage = (response, fallback = "") => {
|
|
2443
|
+
try {
|
|
2444
|
+
if (!response || typeof response !== "object") {
|
|
2445
|
+
return fallback;
|
|
2446
|
+
}
|
|
2447
|
+
const resp = response;
|
|
2448
|
+
if ("status" in resp && typeof resp["status"] === "string") {
|
|
2449
|
+
return resp["status"];
|
|
2450
|
+
}
|
|
2451
|
+
return fallback;
|
|
2452
|
+
} catch (error) {
|
|
2453
|
+
logger2.error("Error parsing response status message", error);
|
|
2454
|
+
return fallback;
|
|
2455
|
+
}
|
|
2456
|
+
};
|
|
2457
|
+
var isSuccessResponse = (response) => {
|
|
2458
|
+
try {
|
|
2459
|
+
const statusCode2 = parseResponseStatus(response);
|
|
2460
|
+
if (statusCode2 !== null) {
|
|
2461
|
+
return SUCCESS_CODES.includes(statusCode2);
|
|
2462
|
+
}
|
|
2463
|
+
const status = parseResponseStatusMessage(response);
|
|
2464
|
+
return [STATUS_MESSAGES.SUCCESS, STATUS_MESSAGES.CREATED, STATUS_MESSAGES.NO_CONTENT].includes(
|
|
2465
|
+
status
|
|
2466
|
+
);
|
|
2467
|
+
} catch (error) {
|
|
2468
|
+
logger2.error("Error checking response success", error);
|
|
2469
|
+
return false;
|
|
2470
|
+
}
|
|
2471
|
+
};
|
|
2472
|
+
var isErrorResponse = (response) => {
|
|
2473
|
+
try {
|
|
2474
|
+
const statusCode2 = parseResponseStatus(response);
|
|
2475
|
+
if (statusCode2 !== null) {
|
|
2476
|
+
return ERROR_CODES.includes(statusCode2);
|
|
2477
|
+
}
|
|
2478
|
+
return false;
|
|
2479
|
+
} catch (error) {
|
|
2480
|
+
logger2.error("Error checking response error", error);
|
|
2481
|
+
return false;
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
var parsePaginatedResponse = (response) => {
|
|
2485
|
+
try {
|
|
2486
|
+
if (!response || typeof response !== "object") {
|
|
2487
|
+
return { items: [], total: 0, page: 1, limit: 10 };
|
|
2488
|
+
}
|
|
2489
|
+
const resp = response;
|
|
2490
|
+
let items = [];
|
|
2491
|
+
if ("data" in resp && Array.isArray(resp["data"])) {
|
|
2492
|
+
items = resp["data"];
|
|
2493
|
+
}
|
|
2494
|
+
let total = items.length;
|
|
2495
|
+
let page = 1;
|
|
2496
|
+
let limit = 10;
|
|
2497
|
+
let totalPages;
|
|
2498
|
+
if ("paginationData" in resp && resp["paginationData"] && typeof resp["paginationData"] === "object") {
|
|
2499
|
+
const paginationData = resp["paginationData"];
|
|
2500
|
+
if ("total" in paginationData && typeof paginationData["total"] === "number") {
|
|
2501
|
+
total = paginationData["total"];
|
|
2502
|
+
}
|
|
2503
|
+
if ("page" in paginationData && typeof paginationData["page"] === "number") {
|
|
2504
|
+
page = paginationData["page"];
|
|
2505
|
+
}
|
|
2506
|
+
if ("limit" in paginationData && typeof paginationData["limit"] === "number") {
|
|
2507
|
+
limit = paginationData["limit"];
|
|
2508
|
+
}
|
|
2509
|
+
if ("totalPages" in paginationData && typeof paginationData["totalPages"] === "number") {
|
|
2510
|
+
totalPages = paginationData["totalPages"];
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
let columns;
|
|
2514
|
+
if ("columns" in resp && Array.isArray(resp["columns"])) {
|
|
2515
|
+
columns = resp["columns"];
|
|
2516
|
+
}
|
|
2517
|
+
return {
|
|
2518
|
+
items,
|
|
2519
|
+
total,
|
|
2520
|
+
page,
|
|
2521
|
+
limit,
|
|
2522
|
+
...totalPages !== void 0 && { totalPages },
|
|
2523
|
+
...columns !== void 0 && { columns }
|
|
2524
|
+
};
|
|
2525
|
+
} catch (error) {
|
|
2526
|
+
logger2.error("Error parsing paginated response", error);
|
|
2527
|
+
return { items: [], total: 0, page: 1, limit: 10 };
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
var extractNestedData = (response, path2, fallback = null) => {
|
|
2531
|
+
try {
|
|
2532
|
+
const keys = path2.split(".");
|
|
2533
|
+
let current = response;
|
|
2534
|
+
for (const key of keys) {
|
|
2535
|
+
if (current && typeof current === "object" && key in current) {
|
|
2536
|
+
current = current[key];
|
|
2537
|
+
} else {
|
|
2538
|
+
return fallback;
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
return current;
|
|
2542
|
+
} catch (error) {
|
|
2543
|
+
logger2.error("Error extracting nested data", error);
|
|
2544
|
+
return fallback;
|
|
2545
|
+
}
|
|
2546
|
+
};
|
|
2547
|
+
var safeJsonParse = (json, fallback = null) => {
|
|
2548
|
+
try {
|
|
2549
|
+
return JSON.parse(json);
|
|
2550
|
+
} catch (error) {
|
|
2551
|
+
logger2.error("Error parsing JSON", error);
|
|
2552
|
+
return fallback;
|
|
2553
|
+
}
|
|
2554
|
+
};
|
|
2555
|
+
var parseAxiosErrorMessage = (error) => {
|
|
2556
|
+
try {
|
|
2557
|
+
if (!error || typeof error !== "object") {
|
|
2558
|
+
return "An unexpected error occurred";
|
|
2559
|
+
}
|
|
2560
|
+
const err = error;
|
|
2561
|
+
if ("response" in err && err["response"] && typeof err["response"] === "object") {
|
|
2562
|
+
const response = err["response"];
|
|
2563
|
+
if ("data" in response && response["data"] && typeof response["data"] === "object") {
|
|
2564
|
+
const data = response["data"];
|
|
2565
|
+
if ("data" in data && data["data"] && typeof data["data"] === "object") {
|
|
2566
|
+
const nestedData = data["data"];
|
|
2567
|
+
if ("message" in nestedData && typeof nestedData["message"] === "string") {
|
|
2568
|
+
return nestedData["message"];
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
if ("message" in data && typeof data["message"] === "string") {
|
|
2572
|
+
return data["message"];
|
|
1702
2573
|
}
|
|
1703
|
-
if (
|
|
1704
|
-
|
|
2574
|
+
if ("error" in data && typeof data["error"] === "string") {
|
|
2575
|
+
return data["error"];
|
|
1705
2576
|
}
|
|
1706
2577
|
}
|
|
1707
|
-
return Promise.reject(error);
|
|
1708
2578
|
}
|
|
1709
|
-
|
|
1710
|
-
|
|
2579
|
+
if ("message" in err && typeof err["message"] === "string") {
|
|
2580
|
+
return err["message"];
|
|
2581
|
+
}
|
|
2582
|
+
if (typeof error === "string") {
|
|
2583
|
+
return error;
|
|
2584
|
+
}
|
|
2585
|
+
return "An unexpected error occurred";
|
|
2586
|
+
} catch (parseError2) {
|
|
2587
|
+
logger2.error("Error parsing axios error message", parseError2);
|
|
2588
|
+
return "An unexpected error occurred";
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2591
|
+
var parseError = (error) => {
|
|
2592
|
+
try {
|
|
2593
|
+
if (!error || typeof error !== "object") {
|
|
2594
|
+
return {
|
|
2595
|
+
message: "An unexpected error occurred",
|
|
2596
|
+
statusCode: null,
|
|
2597
|
+
data: null
|
|
2598
|
+
};
|
|
2599
|
+
}
|
|
2600
|
+
const err = error;
|
|
2601
|
+
let statusCode2 = null;
|
|
2602
|
+
let data = null;
|
|
2603
|
+
let status;
|
|
2604
|
+
if ("response" in err && err["response"] && typeof err["response"] === "object") {
|
|
2605
|
+
const response = err["response"];
|
|
2606
|
+
if ("status" in response && typeof response["status"] === "number") {
|
|
2607
|
+
statusCode2 = response["status"];
|
|
2608
|
+
}
|
|
2609
|
+
if ("data" in response && response["data"] !== void 0) {
|
|
2610
|
+
data = response["data"];
|
|
2611
|
+
if (data && typeof data === "object" && "status" in data) {
|
|
2612
|
+
const dataObj = data;
|
|
2613
|
+
if (typeof dataObj["status"] === "string") {
|
|
2614
|
+
status = dataObj["status"];
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
if (statusCode2 === null && "statusCode" in err && typeof err["statusCode"] === "number") {
|
|
2620
|
+
statusCode2 = err["statusCode"];
|
|
2621
|
+
}
|
|
2622
|
+
if (data === null && "data" in err && err["data"] !== void 0) {
|
|
2623
|
+
data = err["data"];
|
|
2624
|
+
}
|
|
2625
|
+
if (!status && "status" in err && typeof err["status"] === "string") {
|
|
2626
|
+
status = err["status"];
|
|
2627
|
+
}
|
|
2628
|
+
return {
|
|
2629
|
+
message: parseAxiosErrorMessage(error),
|
|
2630
|
+
statusCode: statusCode2,
|
|
2631
|
+
data,
|
|
2632
|
+
...status !== void 0 && { status }
|
|
2633
|
+
};
|
|
2634
|
+
} catch (err) {
|
|
2635
|
+
logger2.error("Error parsing error object", err);
|
|
2636
|
+
return {
|
|
2637
|
+
message: "An unexpected error occurred",
|
|
2638
|
+
statusCode: null,
|
|
2639
|
+
data: null
|
|
2640
|
+
};
|
|
2641
|
+
}
|
|
2642
|
+
};
|
|
2643
|
+
var simpleParseResponse = (response) => {
|
|
2644
|
+
return response?.data?.data?.data;
|
|
2645
|
+
};
|
|
2646
|
+
var simpleMetaParseResponse = (response) => {
|
|
2647
|
+
return response?.data?.data?.meta;
|
|
1711
2648
|
};
|
|
1712
|
-
var
|
|
2649
|
+
var simpleParseDualDataResponse = (response) => {
|
|
2650
|
+
return response?.data?.data;
|
|
2651
|
+
};
|
|
2652
|
+
|
|
2653
|
+
// src/client/http/http.ts
|
|
2654
|
+
var defaultConfig2 = {
|
|
2655
|
+
baseUrl: typeof window !== "undefined" && window.location.hostname === "localhost" ? "http://localhost:4002" : "https://service-api.exyconn.com",
|
|
2656
|
+
apiPrefix: "/v1/api",
|
|
2657
|
+
timeout: 3e4,
|
|
2658
|
+
defaultHeaders: {}
|
|
2659
|
+
};
|
|
2660
|
+
var currentConfig = { ...defaultConfig2 };
|
|
2661
|
+
var axiosInstance = axios__default.default.create({
|
|
2662
|
+
baseURL: defaultConfig2.baseUrl,
|
|
2663
|
+
timeout: defaultConfig2.timeout,
|
|
1713
2664
|
headers: {
|
|
1714
|
-
"Content-Type": "
|
|
2665
|
+
"Content-Type": "application/json"
|
|
1715
2666
|
}
|
|
1716
2667
|
});
|
|
1717
|
-
var
|
|
1718
|
-
|
|
1719
|
-
}
|
|
1720
|
-
var
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
var
|
|
1726
|
-
|
|
1727
|
-
|
|
2668
|
+
var getApiBaseUrl = () => {
|
|
2669
|
+
return currentConfig.baseUrl || defaultConfig2.baseUrl;
|
|
2670
|
+
};
|
|
2671
|
+
var setApiBaseUrl = (baseUrl) => {
|
|
2672
|
+
currentConfig.baseUrl = baseUrl;
|
|
2673
|
+
axiosInstance.defaults.baseURL = baseUrl;
|
|
2674
|
+
logger2.info(`API Base URL updated to: ${baseUrl}`);
|
|
2675
|
+
};
|
|
2676
|
+
var getApiPrefix = () => {
|
|
2677
|
+
return currentConfig.apiPrefix || defaultConfig2.apiPrefix;
|
|
2678
|
+
};
|
|
2679
|
+
var setApiPrefix = (prefix) => {
|
|
2680
|
+
currentConfig.apiPrefix = prefix;
|
|
2681
|
+
logger2.info(`API Prefix updated to: ${prefix}`);
|
|
2682
|
+
};
|
|
2683
|
+
var getCustomHeaders = () => {
|
|
2684
|
+
return { ...currentConfig.defaultHeaders };
|
|
2685
|
+
};
|
|
2686
|
+
var setCustomHeader = (key, value) => {
|
|
2687
|
+
if (!currentConfig.defaultHeaders) {
|
|
2688
|
+
currentConfig.defaultHeaders = {};
|
|
1728
2689
|
}
|
|
1729
|
-
|
|
2690
|
+
currentConfig.defaultHeaders[key] = value;
|
|
2691
|
+
axiosInstance.defaults.headers.common[key] = value;
|
|
2692
|
+
logger2.info(`Custom header added: ${key}`);
|
|
1730
2693
|
};
|
|
1731
|
-
var
|
|
1732
|
-
|
|
2694
|
+
var removeCustomHeader = (key) => {
|
|
2695
|
+
if (currentConfig.defaultHeaders) {
|
|
2696
|
+
delete currentConfig.defaultHeaders[key];
|
|
2697
|
+
}
|
|
2698
|
+
delete axiosInstance.defaults.headers.common[key];
|
|
2699
|
+
logger2.info(`Custom header removed: ${key}`);
|
|
1733
2700
|
};
|
|
1734
|
-
var
|
|
1735
|
-
|
|
1736
|
-
|
|
2701
|
+
var setCustomHeaders = (headers) => {
|
|
2702
|
+
currentConfig.defaultHeaders = { ...currentConfig.defaultHeaders, ...headers };
|
|
2703
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
2704
|
+
axiosInstance.defaults.headers.common[key] = value;
|
|
2705
|
+
});
|
|
2706
|
+
logger2.info(`Multiple custom headers added: ${Object.keys(headers).join(", ")}`);
|
|
2707
|
+
};
|
|
2708
|
+
var clearCustomHeaders = () => {
|
|
2709
|
+
if (currentConfig.defaultHeaders) {
|
|
2710
|
+
Object.keys(currentConfig.defaultHeaders).forEach((key) => {
|
|
2711
|
+
delete axiosInstance.defaults.headers.common[key];
|
|
2712
|
+
});
|
|
1737
2713
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
2714
|
+
currentConfig.defaultHeaders = {};
|
|
2715
|
+
logger2.info("All custom headers cleared");
|
|
2716
|
+
};
|
|
2717
|
+
var configureHttp = (config) => {
|
|
2718
|
+
if (config.baseUrl) {
|
|
2719
|
+
setApiBaseUrl(config.baseUrl);
|
|
2720
|
+
}
|
|
2721
|
+
if (config.apiPrefix) {
|
|
2722
|
+
setApiPrefix(config.apiPrefix);
|
|
1740
2723
|
}
|
|
1741
|
-
if (
|
|
1742
|
-
|
|
2724
|
+
if (config.timeout !== void 0) {
|
|
2725
|
+
currentConfig.timeout = config.timeout;
|
|
2726
|
+
axiosInstance.defaults.timeout = config.timeout;
|
|
1743
2727
|
}
|
|
1744
|
-
if (
|
|
1745
|
-
|
|
2728
|
+
if (config.defaultHeaders) {
|
|
2729
|
+
setCustomHeaders(config.defaultHeaders);
|
|
1746
2730
|
}
|
|
1747
|
-
|
|
2731
|
+
logger2.info("HTTP client configured successfully");
|
|
1748
2732
|
};
|
|
1749
|
-
var
|
|
1750
|
-
return
|
|
2733
|
+
var getHttpConfig = () => {
|
|
2734
|
+
return { ...currentConfig };
|
|
2735
|
+
};
|
|
2736
|
+
var resetHttpConfig = () => {
|
|
2737
|
+
currentConfig = { ...defaultConfig2 };
|
|
2738
|
+
axiosInstance.defaults.baseURL = defaultConfig2.baseUrl;
|
|
2739
|
+
axiosInstance.defaults.timeout = defaultConfig2.timeout;
|
|
2740
|
+
clearCustomHeaders();
|
|
2741
|
+
logger2.info("HTTP configuration reset to defaults");
|
|
2742
|
+
};
|
|
2743
|
+
var API_BASE_URL = getApiBaseUrl();
|
|
2744
|
+
var API_PREFIX = getApiPrefix();
|
|
2745
|
+
axiosInstance.interceptors.request.use(
|
|
2746
|
+
(config) => {
|
|
2747
|
+
try {
|
|
2748
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
2749
|
+
const selectedOrg = localStorage.getItem("selectedOrganization");
|
|
2750
|
+
if (selectedOrg) {
|
|
2751
|
+
const org = JSON.parse(selectedOrg);
|
|
2752
|
+
if (org && org._id) {
|
|
2753
|
+
config.headers["x-organization-id"] = org._id;
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
} catch (error) {
|
|
2758
|
+
logger2.warn("Failed to read organization from localStorage", error);
|
|
2759
|
+
}
|
|
2760
|
+
return config;
|
|
2761
|
+
},
|
|
2762
|
+
(error) => {
|
|
2763
|
+
return Promise.reject(error);
|
|
2764
|
+
}
|
|
2765
|
+
);
|
|
2766
|
+
axiosInstance.interceptors.response.use(
|
|
2767
|
+
(response) => response,
|
|
2768
|
+
(error) => {
|
|
2769
|
+
const parsedError = parseError(error);
|
|
2770
|
+
logger2.error("API Error", parsedError);
|
|
2771
|
+
return Promise.reject(parsedError);
|
|
2772
|
+
}
|
|
2773
|
+
);
|
|
2774
|
+
var buildHeaders = (customHeaders) => {
|
|
2775
|
+
const headers = {
|
|
2776
|
+
"Content-Type": "application/json",
|
|
2777
|
+
...currentConfig.defaultHeaders,
|
|
2778
|
+
// Add global custom headers
|
|
2779
|
+
...customHeaders
|
|
2780
|
+
// Request-specific headers override global ones
|
|
2781
|
+
};
|
|
2782
|
+
return headers;
|
|
2783
|
+
};
|
|
2784
|
+
var buildConfig2 = (params, customHeaders) => {
|
|
2785
|
+
const config = {
|
|
2786
|
+
headers: buildHeaders(customHeaders)
|
|
2787
|
+
};
|
|
2788
|
+
if (params) {
|
|
2789
|
+
config.params = params;
|
|
2790
|
+
}
|
|
2791
|
+
return config;
|
|
2792
|
+
};
|
|
2793
|
+
var getRequest = async (url, params, customHeaders) => {
|
|
2794
|
+
const config = buildConfig2(params, customHeaders);
|
|
2795
|
+
return axiosInstance.get(url, config);
|
|
1751
2796
|
};
|
|
1752
|
-
var
|
|
1753
|
-
|
|
2797
|
+
var postRequest = async (url, data, customHeaders) => {
|
|
2798
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2799
|
+
return axiosInstance.post(url, data, config);
|
|
1754
2800
|
};
|
|
1755
|
-
var
|
|
1756
|
-
|
|
2801
|
+
var putRequest = async (url, data, customHeaders) => {
|
|
2802
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2803
|
+
return axiosInstance.put(url, data, config);
|
|
1757
2804
|
};
|
|
1758
|
-
var
|
|
1759
|
-
|
|
2805
|
+
var patchRequest = async (url, data, customHeaders) => {
|
|
2806
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2807
|
+
return axiosInstance.patch(url, data, config);
|
|
1760
2808
|
};
|
|
1761
|
-
var
|
|
1762
|
-
|
|
2809
|
+
var deleteRequest = async (url, params, customHeaders) => {
|
|
2810
|
+
const config = buildConfig2(params, customHeaders);
|
|
2811
|
+
return axiosInstance.delete(url, config);
|
|
1763
2812
|
};
|
|
1764
|
-
var
|
|
1765
|
-
const
|
|
1766
|
-
|
|
2813
|
+
var uploadFile = async (url, file, additionalData) => {
|
|
2814
|
+
const formData = new FormData();
|
|
2815
|
+
formData.append("file", file);
|
|
2816
|
+
if (additionalData) {
|
|
2817
|
+
Object.entries(additionalData).forEach(([key, value]) => {
|
|
2818
|
+
formData.append(key, String(value));
|
|
2819
|
+
});
|
|
2820
|
+
}
|
|
2821
|
+
const config = {
|
|
2822
|
+
headers: {
|
|
2823
|
+
"Content-Type": "multipart/form-data"
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
return axiosInstance.post(url, formData, config);
|
|
2827
|
+
};
|
|
2828
|
+
var extractData = (response) => {
|
|
2829
|
+
return parseResponseData(response.data);
|
|
2830
|
+
};
|
|
2831
|
+
var extractMessage = (response) => {
|
|
2832
|
+
return parseResponseMessage(response, "");
|
|
2833
|
+
};
|
|
2834
|
+
var isSuccess = (response) => {
|
|
2835
|
+
return response.status >= 200 && response.status < 300;
|
|
2836
|
+
};
|
|
2837
|
+
var extractPaginatedData = (response) => {
|
|
2838
|
+
return parsePaginatedResponse(response.data);
|
|
2839
|
+
};
|
|
2840
|
+
|
|
2841
|
+
// src/client/http/slug.ts
|
|
2842
|
+
var generateSlug = (text) => {
|
|
2843
|
+
if (!text) return "";
|
|
2844
|
+
return text.trim().replace(/[^\w\s]/g, "").replace(/\s+(.)/g, (_, char) => char.toUpperCase()).replace(/\s+/g, "").replace(/^(.)/, (_, char) => char.toLowerCase());
|
|
2845
|
+
};
|
|
2846
|
+
var generateUrlSlug = (text) => {
|
|
2847
|
+
if (!text) return "";
|
|
2848
|
+
return text.trim().toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
2849
|
+
};
|
|
2850
|
+
var generateSnakeSlug = (text) => {
|
|
2851
|
+
if (!text) return "";
|
|
2852
|
+
return text.trim().toLowerCase().replace(/[^\w\s]/g, "").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
1767
2853
|
};
|
|
1768
2854
|
|
|
1769
2855
|
// src/client/logger/client-logger.ts
|
|
@@ -1919,40 +3005,6 @@ var formatRelativeTime = (date) => {
|
|
|
1919
3005
|
}
|
|
1920
3006
|
return "just now";
|
|
1921
3007
|
};
|
|
1922
|
-
var formatDateForInput = (date) => {
|
|
1923
|
-
const dateObj = new Date(date);
|
|
1924
|
-
return dateObj.toISOString().split("T")[0];
|
|
1925
|
-
};
|
|
1926
|
-
var formatDateTimeForInput = (date) => {
|
|
1927
|
-
const dateObj = new Date(date);
|
|
1928
|
-
return dateObj.toISOString().slice(0, 16);
|
|
1929
|
-
};
|
|
1930
|
-
var isToday = (date) => {
|
|
1931
|
-
const dateObj = new Date(date);
|
|
1932
|
-
const today = /* @__PURE__ */ new Date();
|
|
1933
|
-
return dateObj.getDate() === today.getDate() && dateObj.getMonth() === today.getMonth() && dateObj.getFullYear() === today.getFullYear();
|
|
1934
|
-
};
|
|
1935
|
-
var isPast = (date) => {
|
|
1936
|
-
return new Date(date).getTime() < Date.now();
|
|
1937
|
-
};
|
|
1938
|
-
var isFuture = (date) => {
|
|
1939
|
-
return new Date(date).getTime() > Date.now();
|
|
1940
|
-
};
|
|
1941
|
-
var addDays = (date, days) => {
|
|
1942
|
-
const dateObj = new Date(date);
|
|
1943
|
-
dateObj.setDate(dateObj.getDate() + days);
|
|
1944
|
-
return dateObj;
|
|
1945
|
-
};
|
|
1946
|
-
var startOfDay = (date) => {
|
|
1947
|
-
const dateObj = new Date(date);
|
|
1948
|
-
dateObj.setHours(0, 0, 0, 0);
|
|
1949
|
-
return dateObj;
|
|
1950
|
-
};
|
|
1951
|
-
var endOfDay = (date) => {
|
|
1952
|
-
const dateObj = new Date(date);
|
|
1953
|
-
dateObj.setHours(23, 59, 59, 999);
|
|
1954
|
-
return dateObj;
|
|
1955
|
-
};
|
|
1956
3008
|
|
|
1957
3009
|
// src/client/utils/clipboard.ts
|
|
1958
3010
|
var copyToClipboard = async (text) => {
|
|
@@ -1977,20 +3029,6 @@ var copyToClipboard = async (text) => {
|
|
|
1977
3029
|
return false;
|
|
1978
3030
|
}
|
|
1979
3031
|
};
|
|
1980
|
-
var readFromClipboard = async () => {
|
|
1981
|
-
try {
|
|
1982
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
1983
|
-
return await navigator.clipboard.readText();
|
|
1984
|
-
}
|
|
1985
|
-
return null;
|
|
1986
|
-
} catch (error) {
|
|
1987
|
-
console.error("Failed to read from clipboard:", error);
|
|
1988
|
-
return null;
|
|
1989
|
-
}
|
|
1990
|
-
};
|
|
1991
|
-
var isClipboardAvailable = () => {
|
|
1992
|
-
return !!(navigator.clipboard && window.isSecureContext);
|
|
1993
|
-
};
|
|
1994
3032
|
|
|
1995
3033
|
// src/client/utils/slug.ts
|
|
1996
3034
|
var slugify = (text) => {
|
|
@@ -2027,165 +3065,15 @@ var kebabToCamel = (text) => {
|
|
|
2027
3065
|
return text.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
2028
3066
|
};
|
|
2029
3067
|
|
|
2030
|
-
// src/client/utils/events.ts
|
|
2031
|
-
var EventEmitter = class {
|
|
2032
|
-
constructor() {
|
|
2033
|
-
this.handlers = /* @__PURE__ */ new Map();
|
|
2034
|
-
}
|
|
2035
|
-
/**
|
|
2036
|
-
* Subscribe to an event
|
|
2037
|
-
* @returns Unsubscribe function
|
|
2038
|
-
*/
|
|
2039
|
-
on(event, handler) {
|
|
2040
|
-
if (!this.handlers.has(event)) {
|
|
2041
|
-
this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
2042
|
-
}
|
|
2043
|
-
this.handlers.get(event).add(handler);
|
|
2044
|
-
return () => this.off(event, handler);
|
|
2045
|
-
}
|
|
2046
|
-
/**
|
|
2047
|
-
* Subscribe to an event once
|
|
2048
|
-
*/
|
|
2049
|
-
once(event, handler) {
|
|
2050
|
-
const wrappedHandler = (data) => {
|
|
2051
|
-
this.off(event, wrappedHandler);
|
|
2052
|
-
handler(data);
|
|
2053
|
-
};
|
|
2054
|
-
return this.on(event, wrappedHandler);
|
|
2055
|
-
}
|
|
2056
|
-
/**
|
|
2057
|
-
* Unsubscribe from an event
|
|
2058
|
-
*/
|
|
2059
|
-
off(event, handler) {
|
|
2060
|
-
const eventHandlers = this.handlers.get(event);
|
|
2061
|
-
if (eventHandlers) {
|
|
2062
|
-
eventHandlers.delete(handler);
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
/**
|
|
2066
|
-
* Emit an event
|
|
2067
|
-
*/
|
|
2068
|
-
emit(event, data) {
|
|
2069
|
-
const eventHandlers = this.handlers.get(event);
|
|
2070
|
-
if (eventHandlers) {
|
|
2071
|
-
eventHandlers.forEach((handler) => {
|
|
2072
|
-
try {
|
|
2073
|
-
handler(data);
|
|
2074
|
-
} catch (error) {
|
|
2075
|
-
console.error(`Error in event handler for "${String(event)}":`, error);
|
|
2076
|
-
}
|
|
2077
|
-
});
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
/**
|
|
2081
|
-
* Remove all handlers for an event (or all events)
|
|
2082
|
-
*/
|
|
2083
|
-
removeAllListeners(event) {
|
|
2084
|
-
if (event) {
|
|
2085
|
-
this.handlers.delete(event);
|
|
2086
|
-
} else {
|
|
2087
|
-
this.handlers.clear();
|
|
2088
|
-
}
|
|
2089
|
-
}
|
|
2090
|
-
/**
|
|
2091
|
-
* Get count of listeners for an event
|
|
2092
|
-
*/
|
|
2093
|
-
listenerCount(event) {
|
|
2094
|
-
return this.handlers.get(event)?.size ?? 0;
|
|
2095
|
-
}
|
|
2096
|
-
};
|
|
2097
|
-
var createEventEmitter = () => {
|
|
2098
|
-
return new EventEmitter();
|
|
2099
|
-
};
|
|
2100
|
-
var appEvents = new EventEmitter();
|
|
2101
|
-
|
|
2102
|
-
// src/client/utils/api-urls.ts
|
|
2103
|
-
var ApiUrlBuilder = class {
|
|
2104
|
-
constructor(config) {
|
|
2105
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
2106
|
-
this.version = config.version || "";
|
|
2107
|
-
}
|
|
2108
|
-
/**
|
|
2109
|
-
* Build full URL from path
|
|
2110
|
-
*/
|
|
2111
|
-
build(path2) {
|
|
2112
|
-
const normalizedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
2113
|
-
const versionPath = this.version ? `/${this.version}` : "";
|
|
2114
|
-
return `${this.baseUrl}${versionPath}${normalizedPath}`;
|
|
2115
|
-
}
|
|
2116
|
-
/**
|
|
2117
|
-
* Build URL with query parameters
|
|
2118
|
-
*/
|
|
2119
|
-
buildWithParams(path2, params) {
|
|
2120
|
-
const url = this.build(path2);
|
|
2121
|
-
const filteredParams = Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join("&");
|
|
2122
|
-
return filteredParams ? `${url}?${filteredParams}` : url;
|
|
2123
|
-
}
|
|
2124
|
-
/**
|
|
2125
|
-
* Build URL with path parameters
|
|
2126
|
-
*/
|
|
2127
|
-
buildWithPathParams(template, params) {
|
|
2128
|
-
let path2 = template;
|
|
2129
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
2130
|
-
path2 = path2.replace(`:${key}`, String(value));
|
|
2131
|
-
path2 = path2.replace(`{${key}}`, String(value));
|
|
2132
|
-
});
|
|
2133
|
-
return this.build(path2);
|
|
2134
|
-
}
|
|
2135
|
-
/**
|
|
2136
|
-
* Get base URL
|
|
2137
|
-
*/
|
|
2138
|
-
getBaseUrl() {
|
|
2139
|
-
return this.baseUrl;
|
|
2140
|
-
}
|
|
2141
|
-
/**
|
|
2142
|
-
* Set new base URL
|
|
2143
|
-
*/
|
|
2144
|
-
setBaseUrl(baseUrl) {
|
|
2145
|
-
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
2146
|
-
}
|
|
2147
|
-
};
|
|
2148
|
-
var createApiUrlBuilder = (config) => {
|
|
2149
|
-
return new ApiUrlBuilder(config);
|
|
2150
|
-
};
|
|
2151
|
-
var createApiEndpoints = (builder) => ({
|
|
2152
|
-
// Auth endpoints
|
|
2153
|
-
auth: {
|
|
2154
|
-
login: () => builder.build("/auth/login"),
|
|
2155
|
-
register: () => builder.build("/auth/register"),
|
|
2156
|
-
logout: () => builder.build("/auth/logout"),
|
|
2157
|
-
refresh: () => builder.build("/auth/refresh"),
|
|
2158
|
-
me: () => builder.build("/auth/me"),
|
|
2159
|
-
forgotPassword: () => builder.build("/auth/forgot-password"),
|
|
2160
|
-
resetPassword: () => builder.build("/auth/reset-password")
|
|
2161
|
-
},
|
|
2162
|
-
// User endpoints
|
|
2163
|
-
users: {
|
|
2164
|
-
list: () => builder.build("/users"),
|
|
2165
|
-
get: (id) => builder.buildWithPathParams("/users/:id", { id }),
|
|
2166
|
-
create: () => builder.build("/users"),
|
|
2167
|
-
update: (id) => builder.buildWithPathParams("/users/:id", { id }),
|
|
2168
|
-
delete: (id) => builder.buildWithPathParams("/users/:id", { id })
|
|
2169
|
-
},
|
|
2170
|
-
// Generic CRUD factory
|
|
2171
|
-
crud: (resource) => ({
|
|
2172
|
-
list: () => builder.build(`/${resource}`),
|
|
2173
|
-
get: (id) => builder.buildWithPathParams(`/${resource}/:id`, { id }),
|
|
2174
|
-
create: () => builder.build(`/${resource}`),
|
|
2175
|
-
update: (id) => builder.buildWithPathParams(`/${resource}/:id`, { id }),
|
|
2176
|
-
delete: (id) => builder.buildWithPathParams(`/${resource}/:id`, { id })
|
|
2177
|
-
})
|
|
2178
|
-
});
|
|
2179
|
-
|
|
2180
3068
|
// src/client/utils/response-parser.ts
|
|
2181
|
-
var
|
|
3069
|
+
var isSuccessResponse2 = (response) => {
|
|
2182
3070
|
return response.success === true;
|
|
2183
3071
|
};
|
|
2184
|
-
var
|
|
3072
|
+
var isErrorResponse2 = (response) => {
|
|
2185
3073
|
return response.success === false;
|
|
2186
3074
|
};
|
|
2187
3075
|
var getResponseData = (response, defaultValue) => {
|
|
2188
|
-
if (
|
|
3076
|
+
if (isSuccessResponse2(response) && response.data !== void 0) {
|
|
2189
3077
|
return response.data;
|
|
2190
3078
|
}
|
|
2191
3079
|
return defaultValue;
|
|
@@ -4426,18 +5314,18 @@ function useLogger(componentName, props, options = {}) {
|
|
|
4426
5314
|
const {
|
|
4427
5315
|
logProps = true,
|
|
4428
5316
|
logLifecycle = true,
|
|
4429
|
-
logger:
|
|
5317
|
+
logger: logger3 = console.log
|
|
4430
5318
|
} = options;
|
|
4431
5319
|
const previousProps = react.useRef(props);
|
|
4432
5320
|
const renderCount = react.useRef(0);
|
|
4433
5321
|
renderCount.current++;
|
|
4434
5322
|
react.useEffect(() => {
|
|
4435
5323
|
if (logLifecycle) {
|
|
4436
|
-
|
|
5324
|
+
logger3(`[${componentName}] Mounted`);
|
|
4437
5325
|
}
|
|
4438
5326
|
return () => {
|
|
4439
5327
|
if (logLifecycle) {
|
|
4440
|
-
|
|
5328
|
+
logger3(`[${componentName}] Unmounted (rendered ${renderCount.current} times)`);
|
|
4441
5329
|
}
|
|
4442
5330
|
};
|
|
4443
5331
|
}, []);
|
|
@@ -4469,12 +5357,12 @@ function useLogger(componentName, props, options = {}) {
|
|
|
4469
5357
|
});
|
|
4470
5358
|
}
|
|
4471
5359
|
if (hasChanges) {
|
|
4472
|
-
|
|
5360
|
+
logger3(`[${componentName}] Props changed:`, changedProps);
|
|
4473
5361
|
}
|
|
4474
5362
|
previousProps.current = props;
|
|
4475
|
-
}, [componentName, props, logProps,
|
|
5363
|
+
}, [componentName, props, logProps, logger3]);
|
|
4476
5364
|
if (process.env.NODE_ENV === "development") {
|
|
4477
|
-
|
|
5365
|
+
logger3(`[${componentName}] Render #${renderCount.current}`);
|
|
4478
5366
|
}
|
|
4479
5367
|
}
|
|
4480
5368
|
var useLogger_default = useLogger;
|