@eeplatform/core 1.4.2 → 1.4.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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +62 -10
- package/dist/index.js +714 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +722 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/dist/index.mjs
CHANGED
|
@@ -11382,6 +11382,24 @@ function useVerificationRepo() {
|
|
|
11382
11382
|
});
|
|
11383
11383
|
});
|
|
11384
11384
|
}
|
|
11385
|
+
async function createIndexes() {
|
|
11386
|
+
try {
|
|
11387
|
+
await collection.createIndexes([
|
|
11388
|
+
{ key: { email: 1 } },
|
|
11389
|
+
{ key: { type: 1 } },
|
|
11390
|
+
{ key: { status: 1 } },
|
|
11391
|
+
{ key: { "metadata.org": 1 } },
|
|
11392
|
+
{ key: { email: "text" } },
|
|
11393
|
+
{
|
|
11394
|
+
key: { expiredAt: 1 },
|
|
11395
|
+
expireAfterSeconds: 0,
|
|
11396
|
+
name: "ttl_expiredAt_index"
|
|
11397
|
+
}
|
|
11398
|
+
]);
|
|
11399
|
+
} catch (error) {
|
|
11400
|
+
throw new InternalServerError("Failed to create indexes.");
|
|
11401
|
+
}
|
|
11402
|
+
}
|
|
11385
11403
|
async function createIndex() {
|
|
11386
11404
|
try {
|
|
11387
11405
|
await collection.createIndex([
|
|
@@ -11604,9 +11622,7 @@ function useVerificationRepo() {
|
|
|
11604
11622
|
}
|
|
11605
11623
|
}
|
|
11606
11624
|
return {
|
|
11607
|
-
|
|
11608
|
-
createTextIndex,
|
|
11609
|
-
createUniqueIndex,
|
|
11625
|
+
createIndexes,
|
|
11610
11626
|
add,
|
|
11611
11627
|
getVerifications,
|
|
11612
11628
|
getById,
|
|
@@ -13017,7 +13033,7 @@ function useVerificationService() {
|
|
|
13017
13033
|
type: "user-sign-up",
|
|
13018
13034
|
email,
|
|
13019
13035
|
metadata,
|
|
13020
|
-
expireAt: new Date((/* @__PURE__ */ new Date()).getTime() + 5 * 60 * 1e3)
|
|
13036
|
+
expireAt: new Date((/* @__PURE__ */ new Date()).getTime() + 5 * 60 * 1e3),
|
|
13021
13037
|
// 5mins from now
|
|
13022
13038
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13023
13039
|
};
|
|
@@ -25684,7 +25700,7 @@ function useRegionService() {
|
|
|
25684
25700
|
{
|
|
25685
25701
|
id: region.toString(),
|
|
25686
25702
|
name: "Admin",
|
|
25687
|
-
type: "
|
|
25703
|
+
type: "basic-edu-ro",
|
|
25688
25704
|
permissions: ["*"],
|
|
25689
25705
|
status: "active",
|
|
25690
25706
|
default: true
|
|
@@ -26245,7 +26261,7 @@ function useDivisionService() {
|
|
|
26245
26261
|
{
|
|
26246
26262
|
id: division.toString(),
|
|
26247
26263
|
name: "Admin",
|
|
26248
|
-
type: "
|
|
26264
|
+
type: "basic-edu-sdo",
|
|
26249
26265
|
permissions: ["*"],
|
|
26250
26266
|
status: "active",
|
|
26251
26267
|
default: true
|
|
@@ -29256,6 +29272,700 @@ function useStockCardController() {
|
|
|
29256
29272
|
getSuppliers
|
|
29257
29273
|
};
|
|
29258
29274
|
}
|
|
29275
|
+
|
|
29276
|
+
// src/services/github.service.ts
|
|
29277
|
+
import { AppError as AppError16, BadRequestError as BadRequestError72 } from "@eeplatform/nodejs-utils";
|
|
29278
|
+
import { Octokit } from "@octokit/rest";
|
|
29279
|
+
import _sodium from "libsodium-wrappers";
|
|
29280
|
+
function useGitHubService() {
|
|
29281
|
+
function parseRepoUrl(url2) {
|
|
29282
|
+
const match = url2.match(/github\.com[:\/]([^\/]+)\/(.+)\.git$/);
|
|
29283
|
+
if (!match)
|
|
29284
|
+
throw new Error("Invalid GitHub repo URL");
|
|
29285
|
+
return { owner: match[1], repo: match[2] };
|
|
29286
|
+
}
|
|
29287
|
+
async function checkAdminPermission(owner, repo, octokit) {
|
|
29288
|
+
try {
|
|
29289
|
+
const { data: repoData } = await octokit.repos.get({ owner, repo });
|
|
29290
|
+
if (!repoData.permissions?.admin) {
|
|
29291
|
+
throw new BadRequestError72(
|
|
29292
|
+
"You do not have admin access to this repository."
|
|
29293
|
+
);
|
|
29294
|
+
}
|
|
29295
|
+
} catch (error) {
|
|
29296
|
+
if (error.status === 404) {
|
|
29297
|
+
throw new BadRequestError72(
|
|
29298
|
+
"Repository not found or you don't have access to it."
|
|
29299
|
+
);
|
|
29300
|
+
} else if (error.status === 401) {
|
|
29301
|
+
throw new BadRequestError72(
|
|
29302
|
+
"Invalid GitHub token or insufficient permissions."
|
|
29303
|
+
);
|
|
29304
|
+
} else if (error.message.includes("admin access")) {
|
|
29305
|
+
throw error;
|
|
29306
|
+
} else {
|
|
29307
|
+
throw new BadRequestError72(
|
|
29308
|
+
`Failed to check repository permissions: ${error.message}`
|
|
29309
|
+
);
|
|
29310
|
+
}
|
|
29311
|
+
}
|
|
29312
|
+
}
|
|
29313
|
+
async function setVariables(params) {
|
|
29314
|
+
try {
|
|
29315
|
+
const { githubToken, repoUrl, environment, type, keyValues } = params;
|
|
29316
|
+
const octokit = new Octokit({ auth: githubToken });
|
|
29317
|
+
const { owner, repo } = parseRepoUrl(repoUrl);
|
|
29318
|
+
await checkAdminPermission(owner, repo, octokit);
|
|
29319
|
+
const lines = keyValues.split(/[\n\r\s\t]+/).map((l) => l.trim()).filter(Boolean);
|
|
29320
|
+
for (const line of lines) {
|
|
29321
|
+
const equalIndex = line.indexOf("=");
|
|
29322
|
+
if (equalIndex === -1)
|
|
29323
|
+
continue;
|
|
29324
|
+
const key = line.substring(0, equalIndex).trim();
|
|
29325
|
+
const value = line.substring(equalIndex + 1).trim();
|
|
29326
|
+
if (!key || !value)
|
|
29327
|
+
continue;
|
|
29328
|
+
if (type === "secret") {
|
|
29329
|
+
const { data: publicKeyRes } = await octokit.actions.getEnvironmentPublicKey({
|
|
29330
|
+
owner,
|
|
29331
|
+
repo,
|
|
29332
|
+
environment_name: environment
|
|
29333
|
+
});
|
|
29334
|
+
try {
|
|
29335
|
+
await _sodium.ready;
|
|
29336
|
+
const sodium = _sodium;
|
|
29337
|
+
const publicKeyBase64 = publicKeyRes.key;
|
|
29338
|
+
if (!publicKeyBase64) {
|
|
29339
|
+
throw new Error("No public key received from GitHub");
|
|
29340
|
+
}
|
|
29341
|
+
const keyBytes = new Uint8Array(
|
|
29342
|
+
Buffer.from(publicKeyBase64, "base64")
|
|
29343
|
+
);
|
|
29344
|
+
const valueBytes = new Uint8Array(Buffer.from(value, "utf8"));
|
|
29345
|
+
const encryptedBytes = sodium.crypto_box_seal(valueBytes, keyBytes);
|
|
29346
|
+
const encryptedValue = Buffer.from(encryptedBytes).toString("base64");
|
|
29347
|
+
await octokit.actions.createOrUpdateEnvironmentSecret({
|
|
29348
|
+
owner,
|
|
29349
|
+
repo,
|
|
29350
|
+
environment_name: environment,
|
|
29351
|
+
secret_name: key,
|
|
29352
|
+
encrypted_value: encryptedValue,
|
|
29353
|
+
key_id: publicKeyRes.key_id
|
|
29354
|
+
});
|
|
29355
|
+
} catch (encryptionError) {
|
|
29356
|
+
throw new BadRequestError72(
|
|
29357
|
+
`Failed to encrypt secret '${key}': ${encryptionError.message}`
|
|
29358
|
+
);
|
|
29359
|
+
}
|
|
29360
|
+
} else if (type === "env") {
|
|
29361
|
+
await octokit.actions.createEnvironmentVariable({
|
|
29362
|
+
owner,
|
|
29363
|
+
repo,
|
|
29364
|
+
environment_name: environment,
|
|
29365
|
+
name: key,
|
|
29366
|
+
value
|
|
29367
|
+
});
|
|
29368
|
+
}
|
|
29369
|
+
}
|
|
29370
|
+
return `Successfully set ${lines.length} ${type} variables/secrets in environment '${environment}'`;
|
|
29371
|
+
} catch (error) {
|
|
29372
|
+
if (error instanceof AppError16)
|
|
29373
|
+
throw error;
|
|
29374
|
+
if (error.status === 422) {
|
|
29375
|
+
throw new BadRequestError72(
|
|
29376
|
+
`GitHub API validation error: ${error.message}`
|
|
29377
|
+
);
|
|
29378
|
+
} else if (error.status === 404) {
|
|
29379
|
+
throw new BadRequestError72("Environment or repository not found.");
|
|
29380
|
+
} else if (error.status === 403) {
|
|
29381
|
+
throw new BadRequestError72(
|
|
29382
|
+
"Forbidden: Insufficient permissions or rate limit exceeded."
|
|
29383
|
+
);
|
|
29384
|
+
} else if (error.message.includes("admin access") || error.message.includes("permissions")) {
|
|
29385
|
+
throw error;
|
|
29386
|
+
} else {
|
|
29387
|
+
throw new BadRequestError72(
|
|
29388
|
+
`Failed to set GitHub variables: ${error.message}`
|
|
29389
|
+
);
|
|
29390
|
+
}
|
|
29391
|
+
}
|
|
29392
|
+
}
|
|
29393
|
+
return {
|
|
29394
|
+
setVariables
|
|
29395
|
+
};
|
|
29396
|
+
}
|
|
29397
|
+
|
|
29398
|
+
// src/controllers/util.controller.ts
|
|
29399
|
+
import Joi40 from "joi";
|
|
29400
|
+
import {
|
|
29401
|
+
AppError as AppError17,
|
|
29402
|
+
BadRequestError as BadRequestError73,
|
|
29403
|
+
InternalServerError as InternalServerError27,
|
|
29404
|
+
logger as logger35
|
|
29405
|
+
} from "@eeplatform/nodejs-utils";
|
|
29406
|
+
function useUtilController() {
|
|
29407
|
+
async function healthCheck(req, res, next) {
|
|
29408
|
+
try {
|
|
29409
|
+
res.status(200).json({
|
|
29410
|
+
success: true,
|
|
29411
|
+
message: "Util service is healthy",
|
|
29412
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29413
|
+
data: {
|
|
29414
|
+
availableEndpoints: [
|
|
29415
|
+
"POST /github/variables - Set GitHub environment variables or secrets"
|
|
29416
|
+
],
|
|
29417
|
+
keyValueFormat: "KEY=value pairs separated by newlines, spaces, or tabs"
|
|
29418
|
+
}
|
|
29419
|
+
});
|
|
29420
|
+
} catch (error) {
|
|
29421
|
+
logger35.error("Health check failed", { error: error.message });
|
|
29422
|
+
next(new InternalServerError27("Health check failed"));
|
|
29423
|
+
}
|
|
29424
|
+
}
|
|
29425
|
+
async function setGitHubVariables(req, res, next) {
|
|
29426
|
+
try {
|
|
29427
|
+
const { githubToken, repoUrl, environment, type, keyValues } = req.body;
|
|
29428
|
+
const validation = Joi40.object({
|
|
29429
|
+
githubToken: Joi40.string().required().messages({
|
|
29430
|
+
"string.empty": "GitHub token is required",
|
|
29431
|
+
"any.required": "GitHub token is required"
|
|
29432
|
+
}),
|
|
29433
|
+
repoUrl: Joi40.string().uri().required().messages({
|
|
29434
|
+
"string.empty": "Repository URL is required",
|
|
29435
|
+
"string.uri": "Repository URL must be a valid URL",
|
|
29436
|
+
"any.required": "Repository URL is required"
|
|
29437
|
+
}),
|
|
29438
|
+
environment: Joi40.string().required().messages({
|
|
29439
|
+
"string.empty": "Environment name is required",
|
|
29440
|
+
"any.required": "Environment name is required"
|
|
29441
|
+
}),
|
|
29442
|
+
type: Joi40.string().valid("env", "secret").required().messages({
|
|
29443
|
+
"any.only": 'Type must be either "env" or "secret"',
|
|
29444
|
+
"any.required": "Type is required"
|
|
29445
|
+
}),
|
|
29446
|
+
keyValues: Joi40.string().required().messages({
|
|
29447
|
+
"string.empty": "Key-value pairs are required",
|
|
29448
|
+
"any.required": "Key-value pairs are required"
|
|
29449
|
+
})
|
|
29450
|
+
});
|
|
29451
|
+
const { error } = validation.validate({
|
|
29452
|
+
githubToken,
|
|
29453
|
+
repoUrl,
|
|
29454
|
+
environment,
|
|
29455
|
+
type,
|
|
29456
|
+
keyValues
|
|
29457
|
+
});
|
|
29458
|
+
if (error) {
|
|
29459
|
+
next(new BadRequestError73(error.message));
|
|
29460
|
+
return;
|
|
29461
|
+
}
|
|
29462
|
+
const repoUrlPattern = /github\.com[:\/]([^\/]+)\/(.+)\.git$/;
|
|
29463
|
+
if (!repoUrlPattern.test(repoUrl)) {
|
|
29464
|
+
next(
|
|
29465
|
+
new BadRequestError73(
|
|
29466
|
+
"Invalid GitHub repository URL format. Expected format: https://github.com/owner/repo.git"
|
|
29467
|
+
)
|
|
29468
|
+
);
|
|
29469
|
+
return;
|
|
29470
|
+
}
|
|
29471
|
+
const lines = keyValues.split(/[\n\r\s\t]+/).map((l) => l.trim()).filter(Boolean);
|
|
29472
|
+
const invalidLines = lines.filter(
|
|
29473
|
+
(line) => !line.includes("=") || line.indexOf("=") === -1
|
|
29474
|
+
);
|
|
29475
|
+
if (invalidLines.length > 0) {
|
|
29476
|
+
next(
|
|
29477
|
+
new BadRequestError73(
|
|
29478
|
+
"Invalid key-value format. Each pair should be in format: KEY=value. Pairs can be separated by newlines, spaces, or tabs."
|
|
29479
|
+
)
|
|
29480
|
+
);
|
|
29481
|
+
return;
|
|
29482
|
+
}
|
|
29483
|
+
const githubService = useGitHubService();
|
|
29484
|
+
const result = await githubService.setVariables({
|
|
29485
|
+
githubToken,
|
|
29486
|
+
repoUrl,
|
|
29487
|
+
environment,
|
|
29488
|
+
type,
|
|
29489
|
+
keyValues
|
|
29490
|
+
});
|
|
29491
|
+
logger35.info(`GitHub variables set successfully`, {
|
|
29492
|
+
repoUrl,
|
|
29493
|
+
environment,
|
|
29494
|
+
type,
|
|
29495
|
+
count: lines.length
|
|
29496
|
+
});
|
|
29497
|
+
res.status(200).json({
|
|
29498
|
+
success: true,
|
|
29499
|
+
message: result,
|
|
29500
|
+
data: {
|
|
29501
|
+
repoUrl,
|
|
29502
|
+
environment,
|
|
29503
|
+
type,
|
|
29504
|
+
variablesSet: lines.length
|
|
29505
|
+
}
|
|
29506
|
+
});
|
|
29507
|
+
} catch (error) {
|
|
29508
|
+
logger35.error("Failed to set GitHub variables", {
|
|
29509
|
+
error: error.message,
|
|
29510
|
+
stack: error.stack
|
|
29511
|
+
});
|
|
29512
|
+
if (error instanceof AppError17) {
|
|
29513
|
+
next(error);
|
|
29514
|
+
} else {
|
|
29515
|
+
next(
|
|
29516
|
+
new InternalServerError27(
|
|
29517
|
+
`Failed to set GitHub variables: ${error.message}`
|
|
29518
|
+
)
|
|
29519
|
+
);
|
|
29520
|
+
}
|
|
29521
|
+
}
|
|
29522
|
+
}
|
|
29523
|
+
return {
|
|
29524
|
+
healthCheck,
|
|
29525
|
+
setGitHubVariables
|
|
29526
|
+
};
|
|
29527
|
+
}
|
|
29528
|
+
|
|
29529
|
+
// src/models/plantilla.model.ts
|
|
29530
|
+
import { BadRequestError as BadRequestError74 } from "@eeplatform/nodejs-utils";
|
|
29531
|
+
import Joi41 from "joi";
|
|
29532
|
+
import { ObjectId as ObjectId46 } from "mongodb";
|
|
29533
|
+
var schemaPlantilla = Joi41.object({
|
|
29534
|
+
_id: Joi41.string().hex().optional().allow(null, ""),
|
|
29535
|
+
itemNumber: Joi41.string().required(),
|
|
29536
|
+
positionTitle: Joi41.string().required(),
|
|
29537
|
+
officeAssignmentType: Joi41.string().required(),
|
|
29538
|
+
officeAssignment: Joi41.string().required(),
|
|
29539
|
+
status: Joi41.string().required(),
|
|
29540
|
+
employeeId: Joi41.string().hex().optional().allow(null, ""),
|
|
29541
|
+
createdAt: Joi41.date().iso().optional().allow(null, ""),
|
|
29542
|
+
updatedAt: Joi41.date().iso().optional().allow(null, ""),
|
|
29543
|
+
deletedAt: Joi41.date().iso().optional().allow(null, "")
|
|
29544
|
+
});
|
|
29545
|
+
function MPlantilla(data) {
|
|
29546
|
+
const { error } = schemaPlantilla.validate(data);
|
|
29547
|
+
if (error) {
|
|
29548
|
+
throw new BadRequestError74(error.message);
|
|
29549
|
+
}
|
|
29550
|
+
if (data._id && typeof data._id === "string") {
|
|
29551
|
+
try {
|
|
29552
|
+
data._id = new ObjectId46(data._id);
|
|
29553
|
+
} catch (error2) {
|
|
29554
|
+
throw new BadRequestError74("Invalid _id.");
|
|
29555
|
+
}
|
|
29556
|
+
}
|
|
29557
|
+
if (data.employeeId && typeof data.employeeId === "string") {
|
|
29558
|
+
try {
|
|
29559
|
+
data.employeeId = new ObjectId46(data.employeeId);
|
|
29560
|
+
} catch (error2) {
|
|
29561
|
+
throw new BadRequestError74("Invalid employeeId.");
|
|
29562
|
+
}
|
|
29563
|
+
}
|
|
29564
|
+
return {
|
|
29565
|
+
_id: data._id,
|
|
29566
|
+
itemNumber: data.itemNumber ?? "",
|
|
29567
|
+
positionTitle: data.positionTitle ?? "",
|
|
29568
|
+
officeAssignmentType: data.officeAssignmentType ?? "",
|
|
29569
|
+
officeAssignment: data.officeAssignment ?? "",
|
|
29570
|
+
status: data.status ?? "active",
|
|
29571
|
+
employeeId: data.employeeId,
|
|
29572
|
+
createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
|
|
29573
|
+
updatedAt: data.updatedAt ? new Date(data.updatedAt) : "",
|
|
29574
|
+
deletedAt: data.deletedAt ? new Date(data.deletedAt) : ""
|
|
29575
|
+
};
|
|
29576
|
+
}
|
|
29577
|
+
|
|
29578
|
+
// src/repositories/plantilla.repository.ts
|
|
29579
|
+
import {
|
|
29580
|
+
AppError as AppError18,
|
|
29581
|
+
BadRequestError as BadRequestError75,
|
|
29582
|
+
InternalServerError as InternalServerError28,
|
|
29583
|
+
logger as logger36,
|
|
29584
|
+
makeCacheKey as makeCacheKey23,
|
|
29585
|
+
paginate as paginate19,
|
|
29586
|
+
useAtlas as useAtlas38,
|
|
29587
|
+
useCache as useCache24
|
|
29588
|
+
} from "@eeplatform/nodejs-utils";
|
|
29589
|
+
import { ObjectId as ObjectId47 } from "mongodb";
|
|
29590
|
+
function usePlantillaRepo() {
|
|
29591
|
+
const db = useAtlas38.getDb();
|
|
29592
|
+
if (!db) {
|
|
29593
|
+
throw new Error("Unable to connect to server.");
|
|
29594
|
+
}
|
|
29595
|
+
const namespace_collection = "plantillas";
|
|
29596
|
+
const collection = db.collection(namespace_collection);
|
|
29597
|
+
const { getCache, setCache, delNamespace } = useCache24(namespace_collection);
|
|
29598
|
+
async function createIndexes() {
|
|
29599
|
+
try {
|
|
29600
|
+
await collection.createIndexes([
|
|
29601
|
+
{ key: { name: 1 }, unique: true, name: "unique_name_index" },
|
|
29602
|
+
{ key: { school: 1 } },
|
|
29603
|
+
{ key: { status: 1 } }
|
|
29604
|
+
]);
|
|
29605
|
+
} catch (error) {
|
|
29606
|
+
throw new Error("Failed to create index on plantillas.");
|
|
29607
|
+
}
|
|
29608
|
+
}
|
|
29609
|
+
async function add(value, session) {
|
|
29610
|
+
try {
|
|
29611
|
+
value = MPlantilla(value);
|
|
29612
|
+
const res = await collection.insertOne(value, { session });
|
|
29613
|
+
delCachedData();
|
|
29614
|
+
return res.insertedId;
|
|
29615
|
+
} catch (error) {
|
|
29616
|
+
logger36.log({
|
|
29617
|
+
level: "error",
|
|
29618
|
+
message: error.message
|
|
29619
|
+
});
|
|
29620
|
+
if (error instanceof AppError18) {
|
|
29621
|
+
throw error;
|
|
29622
|
+
} else {
|
|
29623
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
29624
|
+
if (isDuplicated) {
|
|
29625
|
+
throw new BadRequestError75("Plantilla already exists.");
|
|
29626
|
+
}
|
|
29627
|
+
throw new Error("Failed to create plantilla.");
|
|
29628
|
+
}
|
|
29629
|
+
}
|
|
29630
|
+
}
|
|
29631
|
+
async function updateById(_id, value, session) {
|
|
29632
|
+
try {
|
|
29633
|
+
_id = new ObjectId47(_id);
|
|
29634
|
+
} catch (error) {
|
|
29635
|
+
throw new BadRequestError75("Invalid ID.");
|
|
29636
|
+
}
|
|
29637
|
+
value.updatedAt = /* @__PURE__ */ new Date();
|
|
29638
|
+
try {
|
|
29639
|
+
const res = await collection.updateOne(
|
|
29640
|
+
{ _id },
|
|
29641
|
+
{ $set: value },
|
|
29642
|
+
{ session }
|
|
29643
|
+
);
|
|
29644
|
+
delCachedData();
|
|
29645
|
+
return res;
|
|
29646
|
+
} catch (error) {
|
|
29647
|
+
logger36.log({
|
|
29648
|
+
level: "error",
|
|
29649
|
+
message: error.message
|
|
29650
|
+
});
|
|
29651
|
+
if (error instanceof AppError18) {
|
|
29652
|
+
throw error;
|
|
29653
|
+
} else {
|
|
29654
|
+
throw new Error("Failed to update plantilla.");
|
|
29655
|
+
}
|
|
29656
|
+
}
|
|
29657
|
+
}
|
|
29658
|
+
async function getAll({
|
|
29659
|
+
search = "",
|
|
29660
|
+
page = 1,
|
|
29661
|
+
limit = 10,
|
|
29662
|
+
sort = {},
|
|
29663
|
+
org = "",
|
|
29664
|
+
status = "active"
|
|
29665
|
+
} = {}) {
|
|
29666
|
+
page = page > 0 ? page - 1 : 0;
|
|
29667
|
+
const query = {
|
|
29668
|
+
status
|
|
29669
|
+
};
|
|
29670
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
29671
|
+
if (search) {
|
|
29672
|
+
query.$text = { $search: search };
|
|
29673
|
+
}
|
|
29674
|
+
if (org) {
|
|
29675
|
+
try {
|
|
29676
|
+
query.org = new ObjectId47(org);
|
|
29677
|
+
} catch (error) {
|
|
29678
|
+
throw new BadRequestError75("Invalid org ID.");
|
|
29679
|
+
}
|
|
29680
|
+
}
|
|
29681
|
+
const cacheParams = {
|
|
29682
|
+
page,
|
|
29683
|
+
limit,
|
|
29684
|
+
sort: JSON.stringify(sort)
|
|
29685
|
+
};
|
|
29686
|
+
if (search)
|
|
29687
|
+
cacheParams.search = search;
|
|
29688
|
+
if (org)
|
|
29689
|
+
cacheParams.org = org;
|
|
29690
|
+
if (status !== "active")
|
|
29691
|
+
cacheParams.status = status;
|
|
29692
|
+
const cacheKey = makeCacheKey23(namespace_collection, cacheParams);
|
|
29693
|
+
logger36.log({
|
|
29694
|
+
level: "info",
|
|
29695
|
+
message: `Cache key for getAll plantillas: ${cacheKey}`
|
|
29696
|
+
});
|
|
29697
|
+
try {
|
|
29698
|
+
const cached = await getCache(cacheKey);
|
|
29699
|
+
if (cached) {
|
|
29700
|
+
logger36.log({
|
|
29701
|
+
level: "info",
|
|
29702
|
+
message: `Cache hit for getAll plantillas: ${cacheKey}`
|
|
29703
|
+
});
|
|
29704
|
+
return cached;
|
|
29705
|
+
}
|
|
29706
|
+
const items = await collection.aggregate([
|
|
29707
|
+
{ $match: query },
|
|
29708
|
+
{ $sort: sort },
|
|
29709
|
+
{ $skip: page * limit },
|
|
29710
|
+
{ $limit: limit }
|
|
29711
|
+
]).toArray();
|
|
29712
|
+
const length = await collection.countDocuments(query);
|
|
29713
|
+
const data = paginate19(items, page, limit, length);
|
|
29714
|
+
setCache(cacheKey, data, 600).then(() => {
|
|
29715
|
+
logger36.log({
|
|
29716
|
+
level: "info",
|
|
29717
|
+
message: `Cache set for getAll plantillas: ${cacheKey}`
|
|
29718
|
+
});
|
|
29719
|
+
}).catch((err) => {
|
|
29720
|
+
logger36.log({
|
|
29721
|
+
level: "error",
|
|
29722
|
+
message: `Failed to set cache for getAll plantillas: ${err.message}`
|
|
29723
|
+
});
|
|
29724
|
+
});
|
|
29725
|
+
return data;
|
|
29726
|
+
} catch (error) {
|
|
29727
|
+
logger36.log({ level: "error", message: `${error}` });
|
|
29728
|
+
throw error;
|
|
29729
|
+
}
|
|
29730
|
+
}
|
|
29731
|
+
async function getById(_id) {
|
|
29732
|
+
try {
|
|
29733
|
+
_id = new ObjectId47(_id);
|
|
29734
|
+
} catch (error) {
|
|
29735
|
+
throw new BadRequestError75("Invalid ID.");
|
|
29736
|
+
}
|
|
29737
|
+
const cacheKey = makeCacheKey23(namespace_collection, { _id: String(_id) });
|
|
29738
|
+
try {
|
|
29739
|
+
const cached = await getCache(cacheKey);
|
|
29740
|
+
if (cached) {
|
|
29741
|
+
logger36.log({
|
|
29742
|
+
level: "info",
|
|
29743
|
+
message: `Cache hit for getById plantilla: ${cacheKey}`
|
|
29744
|
+
});
|
|
29745
|
+
return cached;
|
|
29746
|
+
}
|
|
29747
|
+
const result = await collection.findOne({
|
|
29748
|
+
_id
|
|
29749
|
+
});
|
|
29750
|
+
setCache(cacheKey, result, 300).then(() => {
|
|
29751
|
+
logger36.log({
|
|
29752
|
+
level: "info",
|
|
29753
|
+
message: `Cache set for plantilla by id: ${cacheKey}`
|
|
29754
|
+
});
|
|
29755
|
+
}).catch((err) => {
|
|
29756
|
+
logger36.log({
|
|
29757
|
+
level: "error",
|
|
29758
|
+
message: `Failed to set cache for plantilla by id: ${err.message}`
|
|
29759
|
+
});
|
|
29760
|
+
});
|
|
29761
|
+
return result;
|
|
29762
|
+
} catch (error) {
|
|
29763
|
+
if (error instanceof AppError18) {
|
|
29764
|
+
throw error;
|
|
29765
|
+
} else {
|
|
29766
|
+
throw new InternalServerError28("Failed to get plantilla.");
|
|
29767
|
+
}
|
|
29768
|
+
}
|
|
29769
|
+
}
|
|
29770
|
+
async function deleteById(_id, session) {
|
|
29771
|
+
try {
|
|
29772
|
+
_id = new ObjectId47(_id);
|
|
29773
|
+
} catch (error) {
|
|
29774
|
+
throw new BadRequestError75("Invalid ID.");
|
|
29775
|
+
}
|
|
29776
|
+
try {
|
|
29777
|
+
const res = await collection.updateOne(
|
|
29778
|
+
{ _id },
|
|
29779
|
+
{ $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } }
|
|
29780
|
+
);
|
|
29781
|
+
delCachedData();
|
|
29782
|
+
return res;
|
|
29783
|
+
} catch (error) {
|
|
29784
|
+
logger36.log({
|
|
29785
|
+
level: "error",
|
|
29786
|
+
message: error.message
|
|
29787
|
+
});
|
|
29788
|
+
if (error instanceof AppError18) {
|
|
29789
|
+
throw error;
|
|
29790
|
+
} else {
|
|
29791
|
+
throw new InternalServerError28("Failed to delete plantilla.");
|
|
29792
|
+
}
|
|
29793
|
+
}
|
|
29794
|
+
}
|
|
29795
|
+
function delCachedData() {
|
|
29796
|
+
delNamespace().then(() => {
|
|
29797
|
+
logger36.log({
|
|
29798
|
+
level: "info",
|
|
29799
|
+
message: `Cache namespace cleared for ${namespace_collection}`
|
|
29800
|
+
});
|
|
29801
|
+
}).catch((err) => {
|
|
29802
|
+
logger36.log({
|
|
29803
|
+
level: "error",
|
|
29804
|
+
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
29805
|
+
});
|
|
29806
|
+
});
|
|
29807
|
+
}
|
|
29808
|
+
return {
|
|
29809
|
+
createIndexes,
|
|
29810
|
+
add,
|
|
29811
|
+
getAll,
|
|
29812
|
+
getById,
|
|
29813
|
+
updateById,
|
|
29814
|
+
deleteById
|
|
29815
|
+
};
|
|
29816
|
+
}
|
|
29817
|
+
|
|
29818
|
+
// src/controllers/plantilla.controller.ts
|
|
29819
|
+
import { BadRequestError as BadRequestError76 } from "@eeplatform/nodejs-utils";
|
|
29820
|
+
import Joi42 from "joi";
|
|
29821
|
+
function usePlantillaController() {
|
|
29822
|
+
const {
|
|
29823
|
+
add: _addPlantilla,
|
|
29824
|
+
getAll: _getAllPlantillas,
|
|
29825
|
+
getById: _getPlantillaById,
|
|
29826
|
+
updateById: _updatePlantillaById,
|
|
29827
|
+
deleteById: _deletePlantillaById
|
|
29828
|
+
} = usePlantillaRepo();
|
|
29829
|
+
async function createPlantilla(req, res, next) {
|
|
29830
|
+
const value = req.body;
|
|
29831
|
+
const validation = Joi42.object({
|
|
29832
|
+
itemNumber: Joi42.string().required(),
|
|
29833
|
+
positionTitle: Joi42.string().required(),
|
|
29834
|
+
officeAssignmentType: Joi42.string().required(),
|
|
29835
|
+
officeAssignment: Joi42.string().required(),
|
|
29836
|
+
status: Joi42.string().required(),
|
|
29837
|
+
employeeId: Joi42.string().hex().optional().allow(null, "")
|
|
29838
|
+
});
|
|
29839
|
+
const { error } = validation.validate(value);
|
|
29840
|
+
if (error) {
|
|
29841
|
+
next(new BadRequestError76(error.message));
|
|
29842
|
+
return;
|
|
29843
|
+
}
|
|
29844
|
+
try {
|
|
29845
|
+
const id = await _addPlantilla(value);
|
|
29846
|
+
res.json({ message: "Plantilla created successfully", id });
|
|
29847
|
+
return;
|
|
29848
|
+
} catch (error2) {
|
|
29849
|
+
next(error2);
|
|
29850
|
+
}
|
|
29851
|
+
}
|
|
29852
|
+
async function getAllPlantillas(req, res, next) {
|
|
29853
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
29854
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
29855
|
+
const search = req.query.search ?? "";
|
|
29856
|
+
const org = req.query.org ?? "";
|
|
29857
|
+
const isPageNumber = isFinite(page);
|
|
29858
|
+
if (!isPageNumber) {
|
|
29859
|
+
next(new BadRequestError76("Invalid page number."));
|
|
29860
|
+
return;
|
|
29861
|
+
}
|
|
29862
|
+
const isLimitNumber = isFinite(limit);
|
|
29863
|
+
if (!isLimitNumber) {
|
|
29864
|
+
next(new BadRequestError76("Invalid limit number."));
|
|
29865
|
+
return;
|
|
29866
|
+
}
|
|
29867
|
+
const validation = Joi42.object({
|
|
29868
|
+
page: Joi42.number().min(1).optional().allow("", null),
|
|
29869
|
+
limit: Joi42.number().min(1).optional().allow("", null),
|
|
29870
|
+
search: Joi42.string().optional().allow("", null),
|
|
29871
|
+
org: Joi42.string().optional().allow("", null)
|
|
29872
|
+
});
|
|
29873
|
+
const { error } = validation.validate({ page, limit, search, org });
|
|
29874
|
+
if (error) {
|
|
29875
|
+
next(new BadRequestError76(error.message));
|
|
29876
|
+
return;
|
|
29877
|
+
}
|
|
29878
|
+
try {
|
|
29879
|
+
const plantillas = await _getAllPlantillas({
|
|
29880
|
+
search,
|
|
29881
|
+
page,
|
|
29882
|
+
limit,
|
|
29883
|
+
org
|
|
29884
|
+
});
|
|
29885
|
+
res.json(plantillas);
|
|
29886
|
+
return;
|
|
29887
|
+
} catch (error2) {
|
|
29888
|
+
next(error2);
|
|
29889
|
+
}
|
|
29890
|
+
}
|
|
29891
|
+
async function getPlantillaById(req, res, next) {
|
|
29892
|
+
const id = req.params.id;
|
|
29893
|
+
const validation = Joi42.object({
|
|
29894
|
+
id: Joi42.string().hex().required()
|
|
29895
|
+
});
|
|
29896
|
+
const { error } = validation.validate({ id });
|
|
29897
|
+
if (error) {
|
|
29898
|
+
next(new BadRequestError76(error.message));
|
|
29899
|
+
return;
|
|
29900
|
+
}
|
|
29901
|
+
try {
|
|
29902
|
+
const plantilla = await _getPlantillaById(id);
|
|
29903
|
+
if (!plantilla) {
|
|
29904
|
+
next(new BadRequestError76("Plantilla not found."));
|
|
29905
|
+
return;
|
|
29906
|
+
}
|
|
29907
|
+
res.json(plantilla);
|
|
29908
|
+
return;
|
|
29909
|
+
} catch (error2) {
|
|
29910
|
+
next(error2);
|
|
29911
|
+
}
|
|
29912
|
+
}
|
|
29913
|
+
async function updatePlantilla(req, res, next) {
|
|
29914
|
+
const id = req.params.id;
|
|
29915
|
+
const value = req.body;
|
|
29916
|
+
const validation = Joi42.object({
|
|
29917
|
+
id: Joi42.string().hex().required(),
|
|
29918
|
+
employeeId: Joi42.string().hex().optional().allow(null, ""),
|
|
29919
|
+
status: Joi42.string().optional(),
|
|
29920
|
+
positionTitle: Joi42.string().optional()
|
|
29921
|
+
});
|
|
29922
|
+
const { error } = validation.validate({ id, ...value });
|
|
29923
|
+
if (error) {
|
|
29924
|
+
next(new BadRequestError76(error.message));
|
|
29925
|
+
return;
|
|
29926
|
+
}
|
|
29927
|
+
try {
|
|
29928
|
+
const result = await _updatePlantillaById(id, value);
|
|
29929
|
+
if (result.matchedCount === 0) {
|
|
29930
|
+
next(new BadRequestError76("Plantilla not found."));
|
|
29931
|
+
return;
|
|
29932
|
+
}
|
|
29933
|
+
res.json({ message: "Plantilla updated successfully" });
|
|
29934
|
+
return;
|
|
29935
|
+
} catch (error2) {
|
|
29936
|
+
next(error2);
|
|
29937
|
+
}
|
|
29938
|
+
}
|
|
29939
|
+
async function deletePlantilla(req, res, next) {
|
|
29940
|
+
const id = req.params.id;
|
|
29941
|
+
const validation = Joi42.object({
|
|
29942
|
+
id: Joi42.string().hex().required()
|
|
29943
|
+
});
|
|
29944
|
+
const { error } = validation.validate({ id });
|
|
29945
|
+
if (error) {
|
|
29946
|
+
next(new BadRequestError76(error.message));
|
|
29947
|
+
return;
|
|
29948
|
+
}
|
|
29949
|
+
try {
|
|
29950
|
+
const result = await _deletePlantillaById(id);
|
|
29951
|
+
if (result.matchedCount === 0) {
|
|
29952
|
+
next(new BadRequestError76("Plantilla not found."));
|
|
29953
|
+
return;
|
|
29954
|
+
}
|
|
29955
|
+
res.json({ message: "Plantilla deleted successfully" });
|
|
29956
|
+
return;
|
|
29957
|
+
} catch (error2) {
|
|
29958
|
+
next(error2);
|
|
29959
|
+
}
|
|
29960
|
+
}
|
|
29961
|
+
return {
|
|
29962
|
+
createPlantilla,
|
|
29963
|
+
getAllPlantillas,
|
|
29964
|
+
getPlantillaById,
|
|
29965
|
+
updatePlantilla,
|
|
29966
|
+
deletePlantilla
|
|
29967
|
+
};
|
|
29968
|
+
}
|
|
29259
29969
|
export {
|
|
29260
29970
|
ACCESS_TOKEN_EXPIRY,
|
|
29261
29971
|
ACCESS_TOKEN_SECRET,
|
|
@@ -29286,6 +29996,7 @@ export {
|
|
|
29286
29996
|
MOrder,
|
|
29287
29997
|
MOrg,
|
|
29288
29998
|
MPaymentMethod,
|
|
29999
|
+
MPlantilla,
|
|
29289
30000
|
MPromoCode,
|
|
29290
30001
|
MRegion,
|
|
29291
30002
|
MRole,
|
|
@@ -29323,6 +30034,7 @@ export {
|
|
|
29323
30034
|
schemaBuilding,
|
|
29324
30035
|
schemaBuildingUnit,
|
|
29325
30036
|
schemaDivision,
|
|
30037
|
+
schemaPlantilla,
|
|
29326
30038
|
schemaRegion,
|
|
29327
30039
|
schemaSchool,
|
|
29328
30040
|
schemaStockCard,
|
|
@@ -29347,6 +30059,7 @@ export {
|
|
|
29347
30059
|
useFileController,
|
|
29348
30060
|
useFileRepo,
|
|
29349
30061
|
useFileService,
|
|
30062
|
+
useGitHubService,
|
|
29350
30063
|
useInvoiceController,
|
|
29351
30064
|
useInvoiceModel,
|
|
29352
30065
|
useInvoiceRepo,
|
|
@@ -29365,6 +30078,8 @@ export {
|
|
|
29365
30078
|
usePaymentModel,
|
|
29366
30079
|
usePaymentRepo,
|
|
29367
30080
|
usePaypalService,
|
|
30081
|
+
usePlantillaController,
|
|
30082
|
+
usePlantillaRepo,
|
|
29368
30083
|
usePriceController,
|
|
29369
30084
|
usePriceModel,
|
|
29370
30085
|
usePriceRepo,
|
|
@@ -29387,6 +30102,7 @@ export {
|
|
|
29387
30102
|
useUserController,
|
|
29388
30103
|
useUserRepo,
|
|
29389
30104
|
useUserService,
|
|
30105
|
+
useUtilController,
|
|
29390
30106
|
useVerificationController,
|
|
29391
30107
|
useVerificationRepo,
|
|
29392
30108
|
useVerificationService,
|