@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.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,32 @@ 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
|
-
checkPackage: () => checkPackage,
|
|
1523
2156
|
clientLogger: () => clientLogger,
|
|
1524
2157
|
contactFormSchema: () => contactFormSchema,
|
|
1525
2158
|
copyToClipboard: () => copyToClipboard,
|
|
1526
|
-
createApiEndpoints: () => createApiEndpoints,
|
|
1527
|
-
createApiUrlBuilder: () => createApiUrlBuilder,
|
|
1528
2159
|
createClientLogger: () => createClientLogger,
|
|
1529
2160
|
createEmptyPaginationMeta: () => createEmptyPaginationMeta,
|
|
1530
2161
|
createErrorResponse: () => createErrorResponse,
|
|
1531
|
-
createEventEmitter: () => createEventEmitter,
|
|
1532
|
-
createHttpClient: () => createHttpClient,
|
|
1533
2162
|
createRegisterFormSchema: () => createRegisterFormSchema,
|
|
1534
2163
|
createSuccessResponse: () => createSuccessResponse,
|
|
1535
2164
|
createTheme: () => createTheme,
|
|
@@ -1538,6 +2167,7 @@ __export(client_exports, {
|
|
|
1538
2167
|
deepMerge: () => deepMerge2,
|
|
1539
2168
|
defaultDarkTheme: () => defaultDarkTheme,
|
|
1540
2169
|
defaultLightTheme: () => defaultLightTheme,
|
|
2170
|
+
deleteRequest: () => deleteRequest,
|
|
1541
2171
|
dummyBannerData: () => dummyBannerData,
|
|
1542
2172
|
dummyFaqItems: () => dummyFaqItems,
|
|
1543
2173
|
dummyFeatures: () => dummyFeatures,
|
|
@@ -1546,59 +2176,66 @@ __export(client_exports, {
|
|
|
1546
2176
|
dummyImage: () => dummyImage,
|
|
1547
2177
|
dummyPricingPlans: () => dummyPricingPlans,
|
|
1548
2178
|
dummyTestimonials: () => dummyTestimonials,
|
|
1549
|
-
|
|
2179
|
+
extractData: () => extractData,
|
|
2180
|
+
extractMessage: () => extractMessage,
|
|
2181
|
+
extractNestedData: () => extractNestedData,
|
|
2182
|
+
extractPaginatedData: () => extractPaginatedData,
|
|
1550
2183
|
flattenToCssVars: () => flattenToCssVars,
|
|
1551
2184
|
formatDate: () => formatDate,
|
|
1552
|
-
formatDateForInput: () => formatDateForInput,
|
|
1553
2185
|
formatDateTime: () => formatDateTime,
|
|
1554
|
-
formatDateTimeForInput: () => formatDateTimeForInput,
|
|
1555
|
-
formatPackageCheckResult: () => formatPackageCheckResult2,
|
|
1556
2186
|
formatRelativeTime: () => formatRelativeTime,
|
|
1557
2187
|
generateCssVars: () => generateCssVars,
|
|
1558
|
-
|
|
2188
|
+
generateSlug: () => generateSlug,
|
|
2189
|
+
generateSnakeSlug: () => generateSnakeSlug,
|
|
2190
|
+
generateUrlSlug: () => generateUrlSlug,
|
|
1559
2191
|
getContrastColor: () => getContrastColor,
|
|
1560
2192
|
getErrorMessage: () => getErrorMessage,
|
|
1561
2193
|
getNextPage: () => getNextPage,
|
|
1562
2194
|
getPrevPage: () => getPrevPage,
|
|
2195
|
+
getRequest: () => getRequest,
|
|
1563
2196
|
getResponseData: () => getResponseData,
|
|
1564
2197
|
getSystemColorScheme: () => getSystemColorScheme,
|
|
1565
2198
|
hasData: () => hasData,
|
|
1566
2199
|
hasMorePages: () => hasMorePages,
|
|
1567
2200
|
hexToRgba: () => hexToRgba,
|
|
1568
2201
|
injectCssVars: () => injectCssVars,
|
|
1569
|
-
isClipboardAvailable: () => isClipboardAvailable,
|
|
1570
2202
|
isErrorResponse: () => isErrorResponse,
|
|
1571
|
-
isForbidden: () => isForbidden,
|
|
1572
|
-
isFuture: () => isFuture,
|
|
1573
|
-
isNotFound: () => isNotFound,
|
|
1574
|
-
isPast: () => isPast,
|
|
1575
|
-
isServerError: () => isServerError,
|
|
1576
|
-
isStatusError: () => isStatusError,
|
|
1577
2203
|
isSuccess: () => isSuccess,
|
|
1578
2204
|
isSuccessResponse: () => isSuccessResponse,
|
|
1579
|
-
|
|
1580
|
-
|
|
2205
|
+
isUtilErrorResponse: () => isErrorResponse2,
|
|
2206
|
+
isUtilSuccessResponse: () => isSuccessResponse2,
|
|
1581
2207
|
kebabToCamel: () => kebabToCamel,
|
|
1582
2208
|
loadThemeFromUrl: () => loadThemeFromUrl,
|
|
1583
2209
|
loadThemeMode: () => loadThemeMode,
|
|
2210
|
+
logger: () => logger2,
|
|
1584
2211
|
loginFormSchema: () => loginFormSchema,
|
|
1585
2212
|
loremIpsum: () => loremIpsum,
|
|
1586
2213
|
newsletterFormSchema: () => newsletterFormSchema,
|
|
1587
2214
|
packageCheck: () => packageCheck,
|
|
2215
|
+
parseAxiosErrorMessage: () => parseAxiosErrorMessage,
|
|
1588
2216
|
parseError: () => parseError,
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
2217
|
+
parsePaginatedResponse: () => parsePaginatedResponse,
|
|
2218
|
+
parseResponseData: () => parseResponseData,
|
|
2219
|
+
parseResponseMessage: () => parseResponseMessage,
|
|
2220
|
+
parseResponseStatus: () => parseResponseStatus,
|
|
2221
|
+
parseResponseStatusMessage: () => parseResponseStatusMessage,
|
|
2222
|
+
patchRequest: () => patchRequest,
|
|
2223
|
+
postRequest: () => postRequest,
|
|
2224
|
+
putRequest: () => putRequest,
|
|
1592
2225
|
registerFormSchema: () => registerFormSchema,
|
|
1593
2226
|
removeCssVars: () => removeCssVars,
|
|
1594
2227
|
resolveThemeMode: () => resolveThemeMode,
|
|
2228
|
+
safeJsonParse: () => safeJsonParse,
|
|
1595
2229
|
saveThemeMode: () => saveThemeMode,
|
|
2230
|
+
simpleMetaParseResponse: () => simpleMetaParseResponse,
|
|
2231
|
+
simpleParseDualDataResponse: () => simpleParseDualDataResponse,
|
|
2232
|
+
simpleParseResponse: () => simpleParseResponse,
|
|
1596
2233
|
slugify: () => slugify,
|
|
1597
2234
|
slugifyUnique: () => slugifyUnique,
|
|
1598
|
-
startOfDay: () => startOfDay,
|
|
1599
2235
|
truncate: () => truncate,
|
|
1600
2236
|
truncateWords: () => truncateWords,
|
|
1601
2237
|
unslugify: () => unslugify,
|
|
2238
|
+
uploadFile: () => uploadFile,
|
|
1602
2239
|
useBattery: () => useBattery_default,
|
|
1603
2240
|
useClickAway: () => useClickAway_default,
|
|
1604
2241
|
useContinuousRetry: () => useContinuousRetry_default,
|
|
@@ -1658,112 +2295,466 @@ __export(client_exports, {
|
|
|
1658
2295
|
useToggle: () => useToggle_default,
|
|
1659
2296
|
useVisibilityChange: () => useVisibilityChange_default,
|
|
1660
2297
|
useWindowScroll: () => useWindowScroll_default,
|
|
1661
|
-
useWindowSize: () => useWindowSize_default
|
|
1662
|
-
withAbortSignal: () => withAbortSignal,
|
|
1663
|
-
withFormData: () => withFormData,
|
|
1664
|
-
withTimeout: () => withTimeout
|
|
2298
|
+
useWindowSize: () => useWindowSize_default
|
|
1665
2299
|
});
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
headers: {
|
|
1680
|
-
"Content-Type": "application/json"
|
|
2300
|
+
|
|
2301
|
+
// src/client/http/logger.ts
|
|
2302
|
+
var Logger = class {
|
|
2303
|
+
constructor() {
|
|
2304
|
+
this.isDevelopment = typeof window !== "undefined" && window.location.hostname === "localhost";
|
|
2305
|
+
}
|
|
2306
|
+
/**
|
|
2307
|
+
* Log informational messages
|
|
2308
|
+
*/
|
|
2309
|
+
info(message, data, options) {
|
|
2310
|
+
if (this.isDevelopment) {
|
|
2311
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2312
|
+
console.log(`${prefix} ${message}`, data ?? "");
|
|
1681
2313
|
}
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
2314
|
+
}
|
|
2315
|
+
/**
|
|
2316
|
+
* Log warning messages
|
|
2317
|
+
*/
|
|
2318
|
+
warn(message, data, options) {
|
|
2319
|
+
if (this.isDevelopment) {
|
|
2320
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2321
|
+
console.warn(`${prefix} ${message}`, data ?? "");
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Log error messages
|
|
2326
|
+
*/
|
|
2327
|
+
error(message, error, options) {
|
|
2328
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2329
|
+
if (this.isDevelopment) {
|
|
2330
|
+
console.error(`${prefix} ${message}`, error, options?.metadata || "");
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* Log debug messages (only in development)
|
|
2335
|
+
*/
|
|
2336
|
+
debug(message, data, options) {
|
|
2337
|
+
if (this.isDevelopment) {
|
|
2338
|
+
const prefix = options?.context ? `[${options.context}]` : "";
|
|
2339
|
+
console.debug(`${prefix} ${message}`, data || "");
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Log API errors with structured information
|
|
2344
|
+
*/
|
|
2345
|
+
apiError(endpoint, error, metadata) {
|
|
2346
|
+
this.error(`API Error: ${endpoint}`, error, {
|
|
2347
|
+
context: "API",
|
|
2348
|
+
metadata: {
|
|
2349
|
+
endpoint,
|
|
2350
|
+
...metadata
|
|
1690
2351
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
var logger2 = new Logger();
|
|
2356
|
+
|
|
2357
|
+
// src/client/http/response-parser.ts
|
|
2358
|
+
var STATUS_CODES = {
|
|
2359
|
+
SUCCESS: 200,
|
|
2360
|
+
CREATED: 201,
|
|
2361
|
+
NO_CONTENT: 204,
|
|
2362
|
+
BAD_REQUEST: 400,
|
|
2363
|
+
UNAUTHORIZED: 401,
|
|
2364
|
+
FORBIDDEN: 403,
|
|
2365
|
+
NOT_FOUND: 404,
|
|
2366
|
+
CONFLICT: 409,
|
|
2367
|
+
ERROR: 500
|
|
2368
|
+
};
|
|
2369
|
+
var STATUS_MESSAGES = {
|
|
2370
|
+
SUCCESS: "success",
|
|
2371
|
+
CREATED: "created",
|
|
2372
|
+
NO_CONTENT: "no_content",
|
|
2373
|
+
BAD_REQUEST: "bad_request",
|
|
2374
|
+
UNAUTHORIZED: "unauthorized",
|
|
2375
|
+
FORBIDDEN: "forbidden",
|
|
2376
|
+
NOT_FOUND: "not_found",
|
|
2377
|
+
CONFLICT: "conflict",
|
|
2378
|
+
ERROR: "error"
|
|
2379
|
+
};
|
|
2380
|
+
var SUCCESS_CODES = [200, 201, 204];
|
|
2381
|
+
var ERROR_CODES = [400, 401, 403, 404, 409, 500];
|
|
2382
|
+
var parseResponseData = (response, fallback = null) => {
|
|
2383
|
+
try {
|
|
2384
|
+
if (!response || typeof response !== "object") {
|
|
2385
|
+
return fallback;
|
|
2386
|
+
}
|
|
2387
|
+
const resp = response;
|
|
2388
|
+
if ("data" in resp) {
|
|
2389
|
+
return resp["data"] ?? fallback;
|
|
2390
|
+
}
|
|
2391
|
+
return response;
|
|
2392
|
+
} catch (error) {
|
|
2393
|
+
logger2.error("Error parsing response data", error);
|
|
2394
|
+
return fallback;
|
|
2395
|
+
}
|
|
2396
|
+
};
|
|
2397
|
+
var parseResponseMessage = (response, fallback = "") => {
|
|
2398
|
+
try {
|
|
2399
|
+
if (!response || typeof response !== "object") {
|
|
2400
|
+
return fallback;
|
|
2401
|
+
}
|
|
2402
|
+
const resp = response;
|
|
2403
|
+
if ("message" in resp && typeof resp["message"] === "string") {
|
|
2404
|
+
return resp["message"];
|
|
2405
|
+
}
|
|
2406
|
+
return fallback;
|
|
2407
|
+
} catch (error) {
|
|
2408
|
+
logger2.error("Error parsing response message", error);
|
|
2409
|
+
return fallback;
|
|
2410
|
+
}
|
|
2411
|
+
};
|
|
2412
|
+
var parseResponseStatus = (response) => {
|
|
2413
|
+
try {
|
|
2414
|
+
if (!response || typeof response !== "object") {
|
|
2415
|
+
return null;
|
|
2416
|
+
}
|
|
2417
|
+
const resp = response;
|
|
2418
|
+
if ("statusCode" in resp && typeof resp["statusCode"] === "number") {
|
|
2419
|
+
return resp["statusCode"];
|
|
2420
|
+
}
|
|
2421
|
+
if ("status" in resp && typeof resp["status"] === "number") {
|
|
2422
|
+
return resp["status"];
|
|
2423
|
+
}
|
|
2424
|
+
return null;
|
|
2425
|
+
} catch (error) {
|
|
2426
|
+
logger2.error("Error parsing response status", error);
|
|
2427
|
+
return null;
|
|
2428
|
+
}
|
|
2429
|
+
};
|
|
2430
|
+
var parseResponseStatusMessage = (response, fallback = "") => {
|
|
2431
|
+
try {
|
|
2432
|
+
if (!response || typeof response !== "object") {
|
|
2433
|
+
return fallback;
|
|
2434
|
+
}
|
|
2435
|
+
const resp = response;
|
|
2436
|
+
if ("status" in resp && typeof resp["status"] === "string") {
|
|
2437
|
+
return resp["status"];
|
|
2438
|
+
}
|
|
2439
|
+
return fallback;
|
|
2440
|
+
} catch (error) {
|
|
2441
|
+
logger2.error("Error parsing response status message", error);
|
|
2442
|
+
return fallback;
|
|
2443
|
+
}
|
|
2444
|
+
};
|
|
2445
|
+
var isSuccessResponse = (response) => {
|
|
2446
|
+
try {
|
|
2447
|
+
const statusCode2 = parseResponseStatus(response);
|
|
2448
|
+
if (statusCode2 !== null) {
|
|
2449
|
+
return SUCCESS_CODES.includes(statusCode2);
|
|
2450
|
+
}
|
|
2451
|
+
const status = parseResponseStatusMessage(response);
|
|
2452
|
+
return [STATUS_MESSAGES.SUCCESS, STATUS_MESSAGES.CREATED, STATUS_MESSAGES.NO_CONTENT].includes(
|
|
2453
|
+
status
|
|
2454
|
+
);
|
|
2455
|
+
} catch (error) {
|
|
2456
|
+
logger2.error("Error checking response success", error);
|
|
2457
|
+
return false;
|
|
2458
|
+
}
|
|
2459
|
+
};
|
|
2460
|
+
var isErrorResponse = (response) => {
|
|
2461
|
+
try {
|
|
2462
|
+
const statusCode2 = parseResponseStatus(response);
|
|
2463
|
+
if (statusCode2 !== null) {
|
|
2464
|
+
return ERROR_CODES.includes(statusCode2);
|
|
2465
|
+
}
|
|
2466
|
+
return false;
|
|
2467
|
+
} catch (error) {
|
|
2468
|
+
logger2.error("Error checking response error", error);
|
|
2469
|
+
return false;
|
|
2470
|
+
}
|
|
2471
|
+
};
|
|
2472
|
+
var parsePaginatedResponse = (response) => {
|
|
2473
|
+
try {
|
|
2474
|
+
if (!response || typeof response !== "object") {
|
|
2475
|
+
return { items: [], total: 0, page: 1, limit: 10 };
|
|
2476
|
+
}
|
|
2477
|
+
const resp = response;
|
|
2478
|
+
let items = [];
|
|
2479
|
+
if ("data" in resp && Array.isArray(resp["data"])) {
|
|
2480
|
+
items = resp["data"];
|
|
2481
|
+
}
|
|
2482
|
+
let total = items.length;
|
|
2483
|
+
let page = 1;
|
|
2484
|
+
let limit = 10;
|
|
2485
|
+
let totalPages;
|
|
2486
|
+
if ("paginationData" in resp && resp["paginationData"] && typeof resp["paginationData"] === "object") {
|
|
2487
|
+
const paginationData = resp["paginationData"];
|
|
2488
|
+
if ("total" in paginationData && typeof paginationData["total"] === "number") {
|
|
2489
|
+
total = paginationData["total"];
|
|
2490
|
+
}
|
|
2491
|
+
if ("page" in paginationData && typeof paginationData["page"] === "number") {
|
|
2492
|
+
page = paginationData["page"];
|
|
2493
|
+
}
|
|
2494
|
+
if ("limit" in paginationData && typeof paginationData["limit"] === "number") {
|
|
2495
|
+
limit = paginationData["limit"];
|
|
2496
|
+
}
|
|
2497
|
+
if ("totalPages" in paginationData && typeof paginationData["totalPages"] === "number") {
|
|
2498
|
+
totalPages = paginationData["totalPages"];
|
|
1706
2499
|
}
|
|
1707
|
-
return Promise.reject(error);
|
|
1708
2500
|
}
|
|
1709
|
-
|
|
1710
|
-
|
|
2501
|
+
let columns;
|
|
2502
|
+
if ("columns" in resp && Array.isArray(resp["columns"])) {
|
|
2503
|
+
columns = resp["columns"];
|
|
2504
|
+
}
|
|
2505
|
+
return {
|
|
2506
|
+
items,
|
|
2507
|
+
total,
|
|
2508
|
+
page,
|
|
2509
|
+
limit,
|
|
2510
|
+
...totalPages !== void 0 && { totalPages },
|
|
2511
|
+
...columns !== void 0 && { columns }
|
|
2512
|
+
};
|
|
2513
|
+
} catch (error) {
|
|
2514
|
+
logger2.error("Error parsing paginated response", error);
|
|
2515
|
+
return { items: [], total: 0, page: 1, limit: 10 };
|
|
2516
|
+
}
|
|
1711
2517
|
};
|
|
1712
|
-
var
|
|
1713
|
-
|
|
1714
|
-
|
|
2518
|
+
var extractNestedData = (response, path2, fallback = null) => {
|
|
2519
|
+
try {
|
|
2520
|
+
const keys = path2.split(".");
|
|
2521
|
+
let current = response;
|
|
2522
|
+
for (const key of keys) {
|
|
2523
|
+
if (current && typeof current === "object" && key in current) {
|
|
2524
|
+
current = current[key];
|
|
2525
|
+
} else {
|
|
2526
|
+
return fallback;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
return current;
|
|
2530
|
+
} catch (error) {
|
|
2531
|
+
logger2.error("Error extracting nested data", error);
|
|
2532
|
+
return fallback;
|
|
1715
2533
|
}
|
|
1716
|
-
}
|
|
1717
|
-
var
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
// src/client/http/response-parser.ts
|
|
1725
|
-
var parseResponse = (response) => {
|
|
1726
|
-
if (response.data?.success && response.data?.data !== void 0) {
|
|
1727
|
-
return response.data.data;
|
|
2534
|
+
};
|
|
2535
|
+
var safeJsonParse = (json, fallback = null) => {
|
|
2536
|
+
try {
|
|
2537
|
+
return JSON.parse(json);
|
|
2538
|
+
} catch (error) {
|
|
2539
|
+
logger2.error("Error parsing JSON", error);
|
|
2540
|
+
return fallback;
|
|
1728
2541
|
}
|
|
1729
|
-
return null;
|
|
1730
2542
|
};
|
|
1731
|
-
var
|
|
1732
|
-
|
|
2543
|
+
var parseAxiosErrorMessage = (error) => {
|
|
2544
|
+
try {
|
|
2545
|
+
if (!error || typeof error !== "object") {
|
|
2546
|
+
return "An unexpected error occurred";
|
|
2547
|
+
}
|
|
2548
|
+
const err = error;
|
|
2549
|
+
if ("response" in err && err["response"] && typeof err["response"] === "object") {
|
|
2550
|
+
const response = err["response"];
|
|
2551
|
+
if ("data" in response && response["data"] && typeof response["data"] === "object") {
|
|
2552
|
+
const data = response["data"];
|
|
2553
|
+
if ("data" in data && data["data"] && typeof data["data"] === "object") {
|
|
2554
|
+
const nestedData = data["data"];
|
|
2555
|
+
if ("message" in nestedData && typeof nestedData["message"] === "string") {
|
|
2556
|
+
return nestedData["message"];
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
if ("message" in data && typeof data["message"] === "string") {
|
|
2560
|
+
return data["message"];
|
|
2561
|
+
}
|
|
2562
|
+
if ("error" in data && typeof data["error"] === "string") {
|
|
2563
|
+
return data["error"];
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
if ("message" in err && typeof err["message"] === "string") {
|
|
2568
|
+
return err["message"];
|
|
2569
|
+
}
|
|
2570
|
+
if (typeof error === "string") {
|
|
2571
|
+
return error;
|
|
2572
|
+
}
|
|
2573
|
+
return "An unexpected error occurred";
|
|
2574
|
+
} catch (parseError2) {
|
|
2575
|
+
logger2.error("Error parsing axios error message", parseError2);
|
|
2576
|
+
return "An unexpected error occurred";
|
|
2577
|
+
}
|
|
1733
2578
|
};
|
|
1734
2579
|
var parseError = (error) => {
|
|
1735
|
-
|
|
1736
|
-
|
|
2580
|
+
try {
|
|
2581
|
+
if (!error || typeof error !== "object") {
|
|
2582
|
+
return {
|
|
2583
|
+
message: "An unexpected error occurred",
|
|
2584
|
+
statusCode: null,
|
|
2585
|
+
data: null
|
|
2586
|
+
};
|
|
2587
|
+
}
|
|
2588
|
+
const err = error;
|
|
2589
|
+
let statusCode2 = null;
|
|
2590
|
+
let data = null;
|
|
2591
|
+
let status;
|
|
2592
|
+
if ("response" in err && err["response"] && typeof err["response"] === "object") {
|
|
2593
|
+
const response = err["response"];
|
|
2594
|
+
if ("status" in response && typeof response["status"] === "number") {
|
|
2595
|
+
statusCode2 = response["status"];
|
|
2596
|
+
}
|
|
2597
|
+
if ("data" in response && response["data"] !== void 0) {
|
|
2598
|
+
data = response["data"];
|
|
2599
|
+
if (data && typeof data === "object" && "status" in data) {
|
|
2600
|
+
const dataObj = data;
|
|
2601
|
+
if (typeof dataObj["status"] === "string") {
|
|
2602
|
+
status = dataObj["status"];
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
if (statusCode2 === null && "statusCode" in err && typeof err["statusCode"] === "number") {
|
|
2608
|
+
statusCode2 = err["statusCode"];
|
|
2609
|
+
}
|
|
2610
|
+
if (data === null && "data" in err && err["data"] !== void 0) {
|
|
2611
|
+
data = err["data"];
|
|
2612
|
+
}
|
|
2613
|
+
if (!status && "status" in err && typeof err["status"] === "string") {
|
|
2614
|
+
status = err["status"];
|
|
2615
|
+
}
|
|
2616
|
+
return {
|
|
2617
|
+
message: parseAxiosErrorMessage(error),
|
|
2618
|
+
statusCode: statusCode2,
|
|
2619
|
+
data,
|
|
2620
|
+
...status !== void 0 && { status }
|
|
2621
|
+
};
|
|
2622
|
+
} catch (err) {
|
|
2623
|
+
logger2.error("Error parsing error object", err);
|
|
2624
|
+
return {
|
|
2625
|
+
message: "An unexpected error occurred",
|
|
2626
|
+
statusCode: null,
|
|
2627
|
+
data: null
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
};
|
|
2631
|
+
var simpleParseResponse = (response) => {
|
|
2632
|
+
return response?.data?.data?.data;
|
|
2633
|
+
};
|
|
2634
|
+
var simpleMetaParseResponse = (response) => {
|
|
2635
|
+
return response?.data?.data?.meta;
|
|
2636
|
+
};
|
|
2637
|
+
var simpleParseDualDataResponse = (response) => {
|
|
2638
|
+
return response?.data?.data;
|
|
2639
|
+
};
|
|
2640
|
+
|
|
2641
|
+
// src/client/http/http.ts
|
|
2642
|
+
var isDevelopment2 = typeof window !== "undefined" && window.location.hostname === "localhost";
|
|
2643
|
+
var API_BASE_URL = isDevelopment2 ? "http://localhost:4002" : "https://service-api.exyconn.com";
|
|
2644
|
+
var API_PREFIX = "/v1/api";
|
|
2645
|
+
var axiosInstance = axios__default.default.create({
|
|
2646
|
+
baseURL: API_BASE_URL,
|
|
2647
|
+
timeout: 3e4,
|
|
2648
|
+
// 30 seconds
|
|
2649
|
+
headers: {
|
|
2650
|
+
"Content-Type": "application/json"
|
|
1737
2651
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
2652
|
+
});
|
|
2653
|
+
axiosInstance.interceptors.request.use(
|
|
2654
|
+
(config) => {
|
|
2655
|
+
try {
|
|
2656
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
2657
|
+
const selectedOrg = localStorage.getItem("selectedOrganization");
|
|
2658
|
+
if (selectedOrg) {
|
|
2659
|
+
const org = JSON.parse(selectedOrg);
|
|
2660
|
+
if (org && org._id) {
|
|
2661
|
+
config.headers["x-organization-id"] = org._id;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
} catch (error) {
|
|
2666
|
+
logger2.warn("Failed to read organization from localStorage", error);
|
|
2667
|
+
}
|
|
2668
|
+
return config;
|
|
2669
|
+
},
|
|
2670
|
+
(error) => {
|
|
2671
|
+
return Promise.reject(error);
|
|
1740
2672
|
}
|
|
1741
|
-
|
|
1742
|
-
|
|
2673
|
+
);
|
|
2674
|
+
axiosInstance.interceptors.response.use(
|
|
2675
|
+
(response) => response,
|
|
2676
|
+
(error) => {
|
|
2677
|
+
const parsedError = parseError(error);
|
|
2678
|
+
logger2.error("API Error", parsedError);
|
|
2679
|
+
return Promise.reject(parsedError);
|
|
1743
2680
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
2681
|
+
);
|
|
2682
|
+
var buildHeaders = (customHeaders) => {
|
|
2683
|
+
const headers = {
|
|
2684
|
+
"Content-Type": "application/json",
|
|
2685
|
+
...customHeaders
|
|
2686
|
+
};
|
|
2687
|
+
return headers;
|
|
2688
|
+
};
|
|
2689
|
+
var buildConfig2 = (params, customHeaders) => {
|
|
2690
|
+
const config = {
|
|
2691
|
+
headers: buildHeaders(customHeaders)
|
|
2692
|
+
};
|
|
2693
|
+
if (params) {
|
|
2694
|
+
config.params = params;
|
|
1746
2695
|
}
|
|
1747
|
-
return
|
|
2696
|
+
return config;
|
|
1748
2697
|
};
|
|
1749
|
-
var
|
|
1750
|
-
|
|
2698
|
+
var getRequest = async (url, params, customHeaders) => {
|
|
2699
|
+
const config = buildConfig2(params, customHeaders);
|
|
2700
|
+
return axiosInstance.get(url, config);
|
|
2701
|
+
};
|
|
2702
|
+
var postRequest = async (url, data, customHeaders) => {
|
|
2703
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2704
|
+
return axiosInstance.post(url, data, config);
|
|
2705
|
+
};
|
|
2706
|
+
var putRequest = async (url, data, customHeaders) => {
|
|
2707
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2708
|
+
return axiosInstance.put(url, data, config);
|
|
1751
2709
|
};
|
|
1752
|
-
var
|
|
1753
|
-
|
|
2710
|
+
var patchRequest = async (url, data, customHeaders) => {
|
|
2711
|
+
const config = buildConfig2(void 0, customHeaders);
|
|
2712
|
+
return axiosInstance.patch(url, data, config);
|
|
2713
|
+
};
|
|
2714
|
+
var deleteRequest = async (url, params, customHeaders) => {
|
|
2715
|
+
const config = buildConfig2(params, customHeaders);
|
|
2716
|
+
return axiosInstance.delete(url, config);
|
|
2717
|
+
};
|
|
2718
|
+
var uploadFile = async (url, file, additionalData) => {
|
|
2719
|
+
const formData = new FormData();
|
|
2720
|
+
formData.append("file", file);
|
|
2721
|
+
if (additionalData) {
|
|
2722
|
+
Object.entries(additionalData).forEach(([key, value]) => {
|
|
2723
|
+
formData.append(key, String(value));
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
const config = {
|
|
2727
|
+
headers: {
|
|
2728
|
+
"Content-Type": "multipart/form-data"
|
|
2729
|
+
}
|
|
2730
|
+
};
|
|
2731
|
+
return axiosInstance.post(url, formData, config);
|
|
1754
2732
|
};
|
|
1755
|
-
var
|
|
1756
|
-
return
|
|
2733
|
+
var extractData = (response) => {
|
|
2734
|
+
return parseResponseData(response.data);
|
|
1757
2735
|
};
|
|
1758
|
-
var
|
|
1759
|
-
return
|
|
2736
|
+
var extractMessage = (response) => {
|
|
2737
|
+
return parseResponseMessage(response, "");
|
|
1760
2738
|
};
|
|
1761
|
-
var
|
|
1762
|
-
return
|
|
2739
|
+
var isSuccess = (response) => {
|
|
2740
|
+
return response.status >= 200 && response.status < 300;
|
|
1763
2741
|
};
|
|
1764
|
-
var
|
|
1765
|
-
|
|
1766
|
-
|
|
2742
|
+
var extractPaginatedData = (response) => {
|
|
2743
|
+
return parsePaginatedResponse(response.data);
|
|
2744
|
+
};
|
|
2745
|
+
|
|
2746
|
+
// src/client/http/slug.ts
|
|
2747
|
+
var generateSlug = (text) => {
|
|
2748
|
+
if (!text) return "";
|
|
2749
|
+
return text.trim().replace(/[^\w\s]/g, "").replace(/\s+(.)/g, (_, char) => char.toUpperCase()).replace(/\s+/g, "").replace(/^(.)/, (_, char) => char.toLowerCase());
|
|
2750
|
+
};
|
|
2751
|
+
var generateUrlSlug = (text) => {
|
|
2752
|
+
if (!text) return "";
|
|
2753
|
+
return text.trim().toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
2754
|
+
};
|
|
2755
|
+
var generateSnakeSlug = (text) => {
|
|
2756
|
+
if (!text) return "";
|
|
2757
|
+
return text.trim().toLowerCase().replace(/[^\w\s]/g, "").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
1767
2758
|
};
|
|
1768
2759
|
|
|
1769
2760
|
// src/client/logger/client-logger.ts
|
|
@@ -1919,40 +2910,6 @@ var formatRelativeTime = (date) => {
|
|
|
1919
2910
|
}
|
|
1920
2911
|
return "just now";
|
|
1921
2912
|
};
|
|
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
2913
|
|
|
1957
2914
|
// src/client/utils/clipboard.ts
|
|
1958
2915
|
var copyToClipboard = async (text) => {
|
|
@@ -1977,20 +2934,6 @@ var copyToClipboard = async (text) => {
|
|
|
1977
2934
|
return false;
|
|
1978
2935
|
}
|
|
1979
2936
|
};
|
|
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
2937
|
|
|
1995
2938
|
// src/client/utils/slug.ts
|
|
1996
2939
|
var slugify = (text) => {
|
|
@@ -2027,165 +2970,15 @@ var kebabToCamel = (text) => {
|
|
|
2027
2970
|
return text.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
2028
2971
|
};
|
|
2029
2972
|
|
|
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
2973
|
// src/client/utils/response-parser.ts
|
|
2181
|
-
var
|
|
2974
|
+
var isSuccessResponse2 = (response) => {
|
|
2182
2975
|
return response.success === true;
|
|
2183
2976
|
};
|
|
2184
|
-
var
|
|
2977
|
+
var isErrorResponse2 = (response) => {
|
|
2185
2978
|
return response.success === false;
|
|
2186
2979
|
};
|
|
2187
2980
|
var getResponseData = (response, defaultValue) => {
|
|
2188
|
-
if (
|
|
2981
|
+
if (isSuccessResponse2(response) && response.data !== void 0) {
|
|
2189
2982
|
return response.data;
|
|
2190
2983
|
}
|
|
2191
2984
|
return defaultValue;
|
|
@@ -4426,18 +5219,18 @@ function useLogger(componentName, props, options = {}) {
|
|
|
4426
5219
|
const {
|
|
4427
5220
|
logProps = true,
|
|
4428
5221
|
logLifecycle = true,
|
|
4429
|
-
logger:
|
|
5222
|
+
logger: logger3 = console.log
|
|
4430
5223
|
} = options;
|
|
4431
5224
|
const previousProps = react.useRef(props);
|
|
4432
5225
|
const renderCount = react.useRef(0);
|
|
4433
5226
|
renderCount.current++;
|
|
4434
5227
|
react.useEffect(() => {
|
|
4435
5228
|
if (logLifecycle) {
|
|
4436
|
-
|
|
5229
|
+
logger3(`[${componentName}] Mounted`);
|
|
4437
5230
|
}
|
|
4438
5231
|
return () => {
|
|
4439
5232
|
if (logLifecycle) {
|
|
4440
|
-
|
|
5233
|
+
logger3(`[${componentName}] Unmounted (rendered ${renderCount.current} times)`);
|
|
4441
5234
|
}
|
|
4442
5235
|
};
|
|
4443
5236
|
}, []);
|
|
@@ -4469,12 +5262,12 @@ function useLogger(componentName, props, options = {}) {
|
|
|
4469
5262
|
});
|
|
4470
5263
|
}
|
|
4471
5264
|
if (hasChanges) {
|
|
4472
|
-
|
|
5265
|
+
logger3(`[${componentName}] Props changed:`, changedProps);
|
|
4473
5266
|
}
|
|
4474
5267
|
previousProps.current = props;
|
|
4475
|
-
}, [componentName, props, logProps,
|
|
5268
|
+
}, [componentName, props, logProps, logger3]);
|
|
4476
5269
|
if (process.env.NODE_ENV === "development") {
|
|
4477
|
-
|
|
5270
|
+
logger3(`[${componentName}] Render #${renderCount.current}`);
|
|
4478
5271
|
}
|
|
4479
5272
|
}
|
|
4480
5273
|
var useLogger_default = useLogger;
|