@litusarchieve18/agricore-utils 1.0.12 → 1.0.13
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 +2 -0
- package/dist/chunk-QI4YXI4P.mjs +585 -0
- package/dist/constants-DxCjnH4L.d.mts +402 -0
- package/dist/constants-DxCjnH4L.d.ts +402 -0
- package/dist/constants.d.mts +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +654 -0
- package/dist/constants.mjs +96 -0
- package/dist/index.d.mts +16 -417
- package/dist/index.d.ts +16 -417
- package/dist/index.js +281 -272
- package/dist/index.mjs +75 -555
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ __export(index_exports, {
|
|
|
32
32
|
CAT: () => CAT,
|
|
33
33
|
Converter: () => Converter,
|
|
34
34
|
CropCycleStatus: () => CropCycleStatus,
|
|
35
|
+
DOCUMENT_MENU_MAP: () => DOCUMENT_MENU_MAP,
|
|
35
36
|
DocumentType: () => DocumentType,
|
|
36
37
|
ERROR_DICTIONARY: () => ERROR_DICTIONARY,
|
|
37
38
|
EVERYONE: () => EVERYONE,
|
|
@@ -287,7 +288,7 @@ var Converter = {
|
|
|
287
288
|
}
|
|
288
289
|
};
|
|
289
290
|
|
|
290
|
-
// src/
|
|
291
|
+
// src/constants.ts
|
|
291
292
|
var MOD = {
|
|
292
293
|
OPERATIONS: "OPR",
|
|
293
294
|
EQUIPMENT: "EQP",
|
|
@@ -301,7 +302,6 @@ var MOD = {
|
|
|
301
302
|
ALERTS: "ALT",
|
|
302
303
|
INFRA: "INF",
|
|
303
304
|
SESSION: "SES"
|
|
304
|
-
// ← added: used in generateSessionContext but was missing from errorRegistry.js
|
|
305
305
|
};
|
|
306
306
|
var CAT = {
|
|
307
307
|
SUBSCRIPTION: "1",
|
|
@@ -318,43 +318,6 @@ var ACT = {
|
|
|
318
318
|
UPLOAD: "05"
|
|
319
319
|
};
|
|
320
320
|
var SENTINEL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
321
|
-
var AppError = class extends Error {
|
|
322
|
-
status;
|
|
323
|
-
appCode;
|
|
324
|
-
isOperational;
|
|
325
|
-
constructor(status, mod, cat, act, message) {
|
|
326
|
-
super(message);
|
|
327
|
-
this.status = status;
|
|
328
|
-
this.appCode = `${mod}-${status}-${cat}${act}`;
|
|
329
|
-
this.isOperational = true;
|
|
330
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
var ErrorFactory = {
|
|
334
|
-
unauthorized: (mod, msg = "Authentication required") => new AppError(401, mod, CAT.PERMISSION, ACT.GENERIC, msg),
|
|
335
|
-
forbidden: (mod, act, msg = "Access denied") => new AppError(403, mod, CAT.PERMISSION, act, msg),
|
|
336
|
-
badRequest: (mod, act, msg = "Bad request") => new AppError(400, mod, CAT.VALIDATION, act, msg),
|
|
337
|
-
notFound: (mod, act = ACT.GENERIC, msg = "Record not found") => new AppError(404, mod, CAT.VALIDATION, act, msg),
|
|
338
|
-
conflict: (mod, act, msg = "Record already exists") => new AppError(409, mod, CAT.INTEGRITY, act, msg),
|
|
339
|
-
integrity: (mod, act = ACT.GENERIC, msg = "Data integrity violation") => new AppError(409, mod, CAT.INTEGRITY, act, msg),
|
|
340
|
-
subscription: (mod, msg = "Module locked or subscription required") => new AppError(403, mod, CAT.SUBSCRIPTION, ACT.GENERIC, msg),
|
|
341
|
-
internal: (mod, msg = "Internal server error") => new AppError(500, mod, CAT.INTEGRITY, ACT.GENERIC, msg)
|
|
342
|
-
};
|
|
343
|
-
var handleAppErrorResponse = (error, mod = MOD.ADMIN) => {
|
|
344
|
-
if (error instanceof AppError && error.isOperational) {
|
|
345
|
-
return Response.json(
|
|
346
|
-
{ error: { appCode: error.appCode, message: error.message } },
|
|
347
|
-
{ status: error.status }
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
const e = error;
|
|
351
|
-
console.error(`[${mod}] UNEXPECTED ERROR:`, e?.message);
|
|
352
|
-
console.error(`[${mod}] STACK:`, e?.stack);
|
|
353
|
-
return Response.json(
|
|
354
|
-
{ error: { appCode: `${mod}-500-000`, message: "An unexpected server error occurred. Please try again." } },
|
|
355
|
-
{ status: 500 }
|
|
356
|
-
);
|
|
357
|
-
};
|
|
358
321
|
var MODULE_LABELS = {
|
|
359
322
|
[MOD.OPERATIONS]: "Operations",
|
|
360
323
|
[MOD.EQUIPMENT]: "Equipment & Fleet",
|
|
@@ -392,147 +355,6 @@ var ERROR_DICTIONARY = {
|
|
|
392
355
|
"403": { title: "Edit Conflict", text: "This record was recently updated by someone else. Please refresh and try again." },
|
|
393
356
|
"404": { title: "Record In Use", text: "This record cannot be deleted because it is referenced by other data." }
|
|
394
357
|
};
|
|
395
|
-
var FALLBACK = {
|
|
396
|
-
title: "Something Went Wrong",
|
|
397
|
-
text: "An unexpected error occurred. Please try again or contact your administrator."
|
|
398
|
-
};
|
|
399
|
-
var resolveAppError = (appCode) => {
|
|
400
|
-
if (!appCode || typeof appCode !== "string") {
|
|
401
|
-
return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
|
|
402
|
-
}
|
|
403
|
-
const parts = appCode.split("-");
|
|
404
|
-
if (parts.length !== 3) {
|
|
405
|
-
return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
|
|
406
|
-
}
|
|
407
|
-
const [mod, status, catAct] = parts;
|
|
408
|
-
const details = ERROR_DICTIONARY[catAct] || FALLBACK;
|
|
409
|
-
return {
|
|
410
|
-
title: details.title,
|
|
411
|
-
text: details.text,
|
|
412
|
-
module: mod,
|
|
413
|
-
moduleLabel: MODULE_LABELS[mod] || mod,
|
|
414
|
-
status: parseInt(status, 10),
|
|
415
|
-
catAct,
|
|
416
|
-
isSubscriptionIssue: catAct.startsWith("1"),
|
|
417
|
-
isPermissionIssue: catAct.startsWith("2")
|
|
418
|
-
};
|
|
419
|
-
};
|
|
420
|
-
var extractAppCode = (error) => {
|
|
421
|
-
const e = error;
|
|
422
|
-
return e?.response?.data?.error?.appCode ?? e?.data?.error?.appCode ?? null;
|
|
423
|
-
};
|
|
424
|
-
var resolveError = (error) => {
|
|
425
|
-
const appCode = extractAppCode(error);
|
|
426
|
-
if (appCode) return resolveAppError(appCode);
|
|
427
|
-
const e = error;
|
|
428
|
-
return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: e?.status || 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
|
|
429
|
-
};
|
|
430
|
-
function generateCanonicalId() {
|
|
431
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
432
|
-
return crypto.randomUUID();
|
|
433
|
-
}
|
|
434
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
435
|
-
const r = Math.random() * 16 | 0;
|
|
436
|
-
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
function generateInfrastructureFields(activeScope, availableScopes) {
|
|
440
|
-
if (!activeScope || !availableScopes?.length) {
|
|
441
|
-
throw ErrorFactory.unauthorized("[generateInfrastructureFields] Missing scope context.");
|
|
442
|
-
}
|
|
443
|
-
let companyId = null;
|
|
444
|
-
let legalEntityId = null;
|
|
445
|
-
let facilityId = null;
|
|
446
|
-
let pointer = activeScope;
|
|
447
|
-
while (pointer) {
|
|
448
|
-
if (pointer.type === "company") companyId = pointer.base44Id;
|
|
449
|
-
if (pointer.type === "legalEntity") legalEntityId = pointer.base44Id;
|
|
450
|
-
if (pointer.type === "facility") facilityId = pointer.base44Id;
|
|
451
|
-
const parentId = pointer.parentId ?? null;
|
|
452
|
-
pointer = parentId ? availableScopes.find((s) => s.base44Id === parentId) || null : null;
|
|
453
|
-
}
|
|
454
|
-
if (!companyId) {
|
|
455
|
-
throw ErrorFactory.unauthorized("[generateInfrastructureFields] Could not resolve companyId from scope tree.");
|
|
456
|
-
}
|
|
457
|
-
return {
|
|
458
|
-
canonicalId: crypto.randomUUID(),
|
|
459
|
-
companyId,
|
|
460
|
-
legalEntityId,
|
|
461
|
-
facilityId,
|
|
462
|
-
authScopeId: activeScope.authScopeId
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
function buildRlsFilter(session, extra = {}) {
|
|
466
|
-
return { ...extra, authScopeId: { $in: session.readScopes || [] } };
|
|
467
|
-
}
|
|
468
|
-
function canRead(session, authScopeId) {
|
|
469
|
-
return session.readScopes?.includes(authScopeId) ?? false;
|
|
470
|
-
}
|
|
471
|
-
function canWrite(session, authScopeId, resourcePath) {
|
|
472
|
-
const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
|
|
473
|
-
if (override === "WRITE") return true;
|
|
474
|
-
if (override === "NONE" || override === "READ") return false;
|
|
475
|
-
return session.writeScopes?.includes(authScopeId) ?? false;
|
|
476
|
-
}
|
|
477
|
-
function assertCanWrite(session, authScopeId, resourcePath) {
|
|
478
|
-
const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
|
|
479
|
-
if (override === "WRITE") return;
|
|
480
|
-
if (override === "NONE" || override === "READ") {
|
|
481
|
-
throw new AppError(
|
|
482
|
-
403,
|
|
483
|
-
MOD.SESSION,
|
|
484
|
-
CAT.PERMISSION,
|
|
485
|
-
ACT.GENERIC,
|
|
486
|
-
`You do not have write access to "${resourcePath}" in this scope.`
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
if (session.writeScopes?.includes(authScopeId)) return;
|
|
490
|
-
throw new AppError(
|
|
491
|
-
403,
|
|
492
|
-
MOD.SESSION,
|
|
493
|
-
CAT.PERMISSION,
|
|
494
|
-
ACT.GENERIC,
|
|
495
|
-
"You do not have permission to modify records in this scope."
|
|
496
|
-
);
|
|
497
|
-
}
|
|
498
|
-
function resolveAccess(session, activeScopeId, tabConfig) {
|
|
499
|
-
const resourcePath = tabConfig?.resourceId;
|
|
500
|
-
const overrides = session.resourceOverrides?.[activeScopeId] ?? {};
|
|
501
|
-
if (resourcePath) {
|
|
502
|
-
const segments = resourcePath.split(".");
|
|
503
|
-
for (let len = segments.length; len >= 1; len--) {
|
|
504
|
-
const path = segments.slice(0, len).join(".");
|
|
505
|
-
const override = overrides[path];
|
|
506
|
-
if (override === "NONE" || override === "READ" || override === "WRITE") return override;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
const allowedRoles = tabConfig?.allowedRoles ?? [];
|
|
510
|
-
const requiredPrivileges = tabConfig?.requiredPrivileges ?? [];
|
|
511
|
-
const hasRestrictions = allowedRoles.length > 0 || requiredPrivileges.length > 0;
|
|
512
|
-
if (hasRestrictions) {
|
|
513
|
-
const role = session?.role ?? "";
|
|
514
|
-
const privileges = session?.privileges ?? [];
|
|
515
|
-
const passesRole = allowedRoles.length > 0 && allowedRoles.includes(role);
|
|
516
|
-
const passesPrivilege = requiredPrivileges.length > 0 && requiredPrivileges.some((p) => privileges.includes(p));
|
|
517
|
-
return passesRole || passesPrivilege ? "WRITE" : "NONE";
|
|
518
|
-
}
|
|
519
|
-
return "READ";
|
|
520
|
-
}
|
|
521
|
-
function resolveMenuVisibility(session, authScopeId, resourcePath) {
|
|
522
|
-
const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
|
|
523
|
-
if (override === "NONE") return "hidden";
|
|
524
|
-
if (override === "READ") return "read_only";
|
|
525
|
-
if (override === "WRITE") return "active";
|
|
526
|
-
if (session.writeScopes?.includes(authScopeId)) return "active";
|
|
527
|
-
if (session.readScopes?.includes(authScopeId)) return "read_only";
|
|
528
|
-
return "hidden";
|
|
529
|
-
}
|
|
530
|
-
function isTabVisible(session, activeScopeId, tabConfig) {
|
|
531
|
-
return resolveAccess(session, activeScopeId, tabConfig) !== "NONE";
|
|
532
|
-
}
|
|
533
|
-
function isTabWritable(session, activeScopeId, tabConfig) {
|
|
534
|
-
return resolveAccess(session, activeScopeId, tabConfig) === "WRITE";
|
|
535
|
-
}
|
|
536
358
|
var UserRole = {
|
|
537
359
|
OWNER: "owner",
|
|
538
360
|
MANAGER: "manager",
|
|
@@ -752,17 +574,6 @@ var FORM_REGISTRY = {
|
|
|
752
574
|
// ── Audit & Compliance ───────────────────────────────────────────────────
|
|
753
575
|
auditProjectForm: { label: "Audit Project", menuUrl: "/admin", module: "Audit & Compliance" }
|
|
754
576
|
};
|
|
755
|
-
function getFormMeta(componentId) {
|
|
756
|
-
return FORM_REGISTRY[componentId] ?? null;
|
|
757
|
-
}
|
|
758
|
-
function getFormsGroupedByModule() {
|
|
759
|
-
const groups = {};
|
|
760
|
-
for (const [id, meta] of Object.entries(FORM_REGISTRY)) {
|
|
761
|
-
if (!groups[meta.module]) groups[meta.module] = [];
|
|
762
|
-
groups[meta.module].push({ id, ...meta });
|
|
763
|
-
}
|
|
764
|
-
return groups;
|
|
765
|
-
}
|
|
766
577
|
var TASK_TYPE_REGISTRY = {
|
|
767
578
|
INVOICE_OCR: {
|
|
768
579
|
label: "Invoice / Receipt OCR",
|
|
@@ -797,20 +608,6 @@ var TASK_TYPE_REGISTRY = {
|
|
|
797
608
|
approveAction: "ATTACH_REPORT_FILE"
|
|
798
609
|
}
|
|
799
610
|
};
|
|
800
|
-
var getTaskTypeOptions = () => Object.entries(TASK_TYPE_REGISTRY).map(([value, config]) => ({
|
|
801
|
-
value,
|
|
802
|
-
label: config.label,
|
|
803
|
-
description: config.description,
|
|
804
|
-
mimeTypes: config.mimeTypes,
|
|
805
|
-
icon: config.icon
|
|
806
|
-
}));
|
|
807
|
-
var getAcceptedMimeTypes = (taskType) => {
|
|
808
|
-
const config = TASK_TYPE_REGISTRY[taskType];
|
|
809
|
-
return config ? config.mimeTypes.join(",") : "*/*";
|
|
810
|
-
};
|
|
811
|
-
var getApproveAction = (taskType) => {
|
|
812
|
-
return TASK_TYPE_REGISTRY[taskType]?.approveAction ?? null;
|
|
813
|
-
};
|
|
814
611
|
var RESOURCE_PATHS = {
|
|
815
612
|
// ── Top-level menu sections ────────────────────────────────────────────────
|
|
816
613
|
dashboard: "dashboard",
|
|
@@ -862,7 +659,6 @@ var AGRI_ONLY = [
|
|
|
862
659
|
];
|
|
863
660
|
var RESOURCE_MODULE_MAP = {
|
|
864
661
|
// ── Top-level menu sections ────────────────────────────────────────────────
|
|
865
|
-
// CORE features (accessible to everyone with an account)
|
|
866
662
|
[RESOURCE_PATHS.dashboard]: [],
|
|
867
663
|
[RESOURCE_PATHS.operations]: ALL_OPERATIONS,
|
|
868
664
|
[RESOURCE_PATHS.equipment]: ALL_OPERATIONS,
|
|
@@ -917,17 +713,8 @@ var ROLE_SECTIONS_BY_KEY = {
|
|
|
917
713
|
};
|
|
918
714
|
var EVERYONE = Object.values(UserRole);
|
|
919
715
|
var RESOURCE_REQUIREMENTS = {
|
|
920
|
-
[RESOURCE_PATHS.dashboard]: {
|
|
921
|
-
|
|
922
|
-
},
|
|
923
|
-
[RESOURCE_PATHS.operations]: {
|
|
924
|
-
allowedRoles: EVERYONE
|
|
925
|
-
},
|
|
926
|
-
// [RESOURCE_PATHS.equipment]: EVERYONE,
|
|
927
|
-
// [RESOURCE_PATHS.safety]: ALL_OPERATIONS,
|
|
928
|
-
// [RESOURCE_PATHS.team]: ALL_OPERATIONS,
|
|
929
|
-
// [RESOURCE_PATHS.records]: ALL_OPERATIONS,
|
|
930
|
-
// [RESOURCE_PATHS.adminSettings]: ALL_OPERATIONS,
|
|
716
|
+
[RESOURCE_PATHS.dashboard]: { allowedRoles: EVERYONE },
|
|
717
|
+
[RESOURCE_PATHS.operations]: { allowedRoles: EVERYONE },
|
|
931
718
|
// ── Records & Reports ──────────────────────────────────────────────────────
|
|
932
719
|
[RESOURCE_PATHS.documentHub]: {
|
|
933
720
|
allowedRoles: [UserRole.OWNER, UserRole.MANAGER, UserRole.SUPERVISOR],
|
|
@@ -949,7 +736,6 @@ var RESOURCE_REQUIREMENTS = {
|
|
|
949
736
|
allowedRoles: [UserRole.OWNER, UserRole.MANAGER, UserRole.SUPERVISOR],
|
|
950
737
|
requiredPrivileges: [UserPrivilege.ADMIN, UserPrivilege.AUDIT_COMPLIANCE, UserPrivilege.FINANCE, UserPrivilege.HR]
|
|
951
738
|
},
|
|
952
|
-
// [RESOURCE_PATHS.analytics]: ALL_OPERATIONS,
|
|
953
739
|
// ── Admin Settings ─────────────────────────────────────────────────────────
|
|
954
740
|
[RESOURCE_PATHS.adminUserRoster]: {
|
|
955
741
|
allowedRoles: [UserRole.OWNER],
|
|
@@ -966,25 +752,258 @@ var RESOURCE_REQUIREMENTS = {
|
|
|
966
752
|
[RESOURCE_PATHS.adminCompanySettings]: {
|
|
967
753
|
allowedRoles: [UserRole.OWNER]
|
|
968
754
|
}
|
|
969
|
-
// // ── Operations ────────────────────────────────────────────────────────────
|
|
970
|
-
// [RESOURCE_PATHS.farmManagement]: [EnabledModule.FARM_MANAGEMENT],
|
|
971
|
-
// [RESOURCE_PATHS.packhouse]: [EnabledModule.PACKHOUSE],
|
|
972
|
-
// [RESOURCE_PATHS.accommodation]: [EnabledModule.ACCOMMODATION],
|
|
973
|
-
// // ── Equipment & Fleet ──────────────────────────────────────────────────────
|
|
974
|
-
// [RESOURCE_PATHS.equipPreStart]: ALL_OPERATIONS,
|
|
975
|
-
// [RESOURCE_PATHS.equipMaintenance]: ALL_OPERATIONS,
|
|
976
|
-
// [RESOURCE_PATHS.equipFuelRegister]: ALL_OPERATIONS,
|
|
977
|
-
// [RESOURCE_PATHS.equipCalibration]: AGRI_ONLY,
|
|
978
|
-
// [RESOURCE_PATHS.equipFleet]: ALL_OPERATIONS,
|
|
979
|
-
// // ── Safety, Quality & Compliance ──────────────────────────────────────────
|
|
980
|
-
// [RESOURCE_PATHS.safetyAuditing]: ALL_OPERATIONS,
|
|
981
|
-
// [RESOURCE_PATHS.safetyFood]: AGRI_ONLY,
|
|
982
|
-
// [RESOURCE_PATHS.safetyWhs]: ALL_OPERATIONS,
|
|
983
|
-
// [RESOURCE_PATHS.safetyCleaning]: ALL_OPERATIONS,
|
|
984
|
-
// // ── Team & HR ──────────────────────────────────────────────────────────────
|
|
985
|
-
// [RESOURCE_PATHS.teamStaff]: ALL_OPERATIONS,
|
|
986
|
-
// [RESOURCE_PATHS.teamTraining]: ALL_OPERATIONS,
|
|
987
755
|
};
|
|
756
|
+
var DocumentType = /* @__PURE__ */ ((DocumentType2) => {
|
|
757
|
+
DocumentType2["SPRAY_RECORD"] = "SPRAY_RECORD";
|
|
758
|
+
DocumentType2["FERTIGATION_RECORD"] = "FERTIGATION_RECORD";
|
|
759
|
+
DocumentType2["FERTILIZER_RECORD"] = "FERTILIZER_RECORD";
|
|
760
|
+
DocumentType2["QA"] = "QA";
|
|
761
|
+
DocumentType2["CLEANING"] = "CLEANING";
|
|
762
|
+
DocumentType2["PEST"] = "PEST";
|
|
763
|
+
DocumentType2["EQUIPMENT_CALIBRATION_RECORD"] = "EQUIPMENT_CALIBRATION_RECORD";
|
|
764
|
+
DocumentType2["INVENTORY_CONSUMABLES"] = "INVENTORY_CONSUMABLES";
|
|
765
|
+
DocumentType2["INVENTORY_BOX_CARTON"] = "INVENTORY_BOX_CARTON";
|
|
766
|
+
DocumentType2["INVENTORY_CHEMICALS"] = "INVENTORY_CHEMICALS";
|
|
767
|
+
DocumentType2["STOCKTAKE"] = "STOCKTAKE";
|
|
768
|
+
DocumentType2["STOCKTAKE_MSDS"] = "STOCKTAKE_MSDS";
|
|
769
|
+
DocumentType2["MAPPING_FARM_MAPS"] = "MAPPING_FARM_MAPS";
|
|
770
|
+
DocumentType2["MAPPING_TRAFIC_MANAGEMENT"] = "MAPPING_TRAFIC_MANAGEMENT";
|
|
771
|
+
DocumentType2["MAPPING_EMERGENCY"] = "MAPPING_EMERGENCY";
|
|
772
|
+
DocumentType2["INCIDENT_REPORT"] = "INCIDENT_REPORT";
|
|
773
|
+
DocumentType2["TRAINING_RECORDS"] = "TRAINING_RECORDS";
|
|
774
|
+
DocumentType2["SOPS"] = "SOPS";
|
|
775
|
+
DocumentType2["RISK_ASSESSMENTS"] = "RISK_ASSESSMENTS";
|
|
776
|
+
DocumentType2["SERVICING_MAINTENANCE"] = "SERVICING_MAINTENANCE";
|
|
777
|
+
DocumentType2["SOIL_TEST"] = "SOIL_TEST";
|
|
778
|
+
DocumentType2["LEAF_TEST"] = "LEAF_TEST";
|
|
779
|
+
DocumentType2["WATER_TEST"] = "WATER_TEST";
|
|
780
|
+
DocumentType2["MRL_TESTING"] = "MRL_TESTING";
|
|
781
|
+
DocumentType2["HEAVY_METAL"] = "HEAVY_METAL";
|
|
782
|
+
DocumentType2["MICROBIAL"] = "MICROBIAL";
|
|
783
|
+
DocumentType2["HARVEST_LOG"] = "HARVEST_LOG";
|
|
784
|
+
DocumentType2["PACKHOUSE_INSPECTION"] = "PACKHOUSE_INSPECTION";
|
|
785
|
+
DocumentType2["TRAINING_CERTIFICATE"] = "TRAINING_CERTIFICATE";
|
|
786
|
+
DocumentType2["INVOICE"] = "INVOICE";
|
|
787
|
+
DocumentType2["LEGAL_CONTRACT"] = "LEGAL_CONTRACT";
|
|
788
|
+
DocumentType2["AUDIT_REPORT"] = "AUDIT_REPORT";
|
|
789
|
+
DocumentType2["SENSITIVE_IDENTITY"] = "SENSITIVE_IDENTITY";
|
|
790
|
+
return DocumentType2;
|
|
791
|
+
})(DocumentType || {});
|
|
792
|
+
var DOCUMENT_MENU_MAP = {
|
|
793
|
+
["SPRAY_RECORD" /* SPRAY_RECORD */]: [RESOURCE_PATHS.farmManagement],
|
|
794
|
+
["FERTIGATION_RECORD" /* FERTIGATION_RECORD */]: [RESOURCE_PATHS.farmManagement],
|
|
795
|
+
["FERTILIZER_RECORD" /* FERTILIZER_RECORD */]: [RESOURCE_PATHS.farmManagement],
|
|
796
|
+
["QA" /* QA */]: [RESOURCE_PATHS.safetyAuditing],
|
|
797
|
+
["CLEANING" /* CLEANING */]: [RESOURCE_PATHS.safetyCleaning],
|
|
798
|
+
["PEST" /* PEST */]: [RESOURCE_PATHS.farmManagement],
|
|
799
|
+
["EQUIPMENT_CALIBRATION_RECORD" /* EQUIPMENT_CALIBRATION_RECORD */]: [RESOURCE_PATHS.equipCalibration],
|
|
800
|
+
["SERVICING_MAINTENANCE" /* SERVICING_MAINTENANCE */]: [RESOURCE_PATHS.equipMaintenance],
|
|
801
|
+
["INVENTORY_CONSUMABLES" /* INVENTORY_CONSUMABLES */]: [RESOURCE_PATHS.packhouse],
|
|
802
|
+
["INVENTORY_BOX_CARTON" /* INVENTORY_BOX_CARTON */]: [RESOURCE_PATHS.packhouse],
|
|
803
|
+
["INVENTORY_CHEMICALS" /* INVENTORY_CHEMICALS */]: [RESOURCE_PATHS.packhouse, RESOURCE_PATHS.farmManagement],
|
|
804
|
+
["STOCKTAKE" /* STOCKTAKE */]: [RESOURCE_PATHS.packhouse],
|
|
805
|
+
["STOCKTAKE_MSDS" /* STOCKTAKE_MSDS */]: [RESOURCE_PATHS.safetyWhs],
|
|
806
|
+
["MAPPING_FARM_MAPS" /* MAPPING_FARM_MAPS */]: [RESOURCE_PATHS.adminBlueprintsSites],
|
|
807
|
+
["MAPPING_TRAFIC_MANAGEMENT" /* MAPPING_TRAFIC_MANAGEMENT */]: [RESOURCE_PATHS.adminBlueprintsSites],
|
|
808
|
+
["MAPPING_EMERGENCY" /* MAPPING_EMERGENCY */]: [RESOURCE_PATHS.adminBlueprintsSites],
|
|
809
|
+
["INCIDENT_REPORT" /* INCIDENT_REPORT */]: [RESOURCE_PATHS.safetyWhs],
|
|
810
|
+
["RISK_ASSESSMENTS" /* RISK_ASSESSMENTS */]: [RESOURCE_PATHS.safetyWhs],
|
|
811
|
+
["TRAINING_RECORDS" /* TRAINING_RECORDS */]: [RESOURCE_PATHS.teamTraining],
|
|
812
|
+
["TRAINING_CERTIFICATE" /* TRAINING_CERTIFICATE */]: [RESOURCE_PATHS.teamTraining],
|
|
813
|
+
["SOPS" /* SOPS */]: [RESOURCE_PATHS.documentHubTemplates],
|
|
814
|
+
["SOIL_TEST" /* SOIL_TEST */]: [RESOURCE_PATHS.farmManagement],
|
|
815
|
+
["LEAF_TEST" /* LEAF_TEST */]: [RESOURCE_PATHS.farmManagement],
|
|
816
|
+
["WATER_TEST" /* WATER_TEST */]: [RESOURCE_PATHS.farmManagement, RESOURCE_PATHS.safetyFood],
|
|
817
|
+
["MRL_TESTING" /* MRL_TESTING */]: [RESOURCE_PATHS.safetyFood],
|
|
818
|
+
["HEAVY_METAL" /* HEAVY_METAL */]: [RESOURCE_PATHS.safetyFood],
|
|
819
|
+
["MICROBIAL" /* MICROBIAL */]: [RESOURCE_PATHS.safetyFood],
|
|
820
|
+
["HARVEST_LOG" /* HARVEST_LOG */]: [RESOURCE_PATHS.farmManagement],
|
|
821
|
+
["PACKHOUSE_INSPECTION" /* PACKHOUSE_INSPECTION */]: [RESOURCE_PATHS.packhouse],
|
|
822
|
+
["INVOICE" /* INVOICE */]: [RESOURCE_PATHS.documentHub],
|
|
823
|
+
["LEGAL_CONTRACT" /* LEGAL_CONTRACT */]: [RESOURCE_PATHS.documentHub],
|
|
824
|
+
["AUDIT_REPORT" /* AUDIT_REPORT */]: [RESOURCE_PATHS.safetyAuditing, RESOURCE_PATHS.dashboard],
|
|
825
|
+
["SENSITIVE_IDENTITY" /* SENSITIVE_IDENTITY */]: [RESOURCE_PATHS.adminUserRoster]
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
// src/index.ts
|
|
829
|
+
var AppError = class extends Error {
|
|
830
|
+
status;
|
|
831
|
+
appCode;
|
|
832
|
+
isOperational;
|
|
833
|
+
constructor(status, mod, cat, act, message) {
|
|
834
|
+
super(message);
|
|
835
|
+
this.status = status;
|
|
836
|
+
this.appCode = `${mod}-${status}-${cat}${act}`;
|
|
837
|
+
this.isOperational = true;
|
|
838
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
var ErrorFactory = {
|
|
842
|
+
unauthorized: (mod, msg = "Authentication required") => new AppError(401, mod, CAT.PERMISSION, ACT.GENERIC, msg),
|
|
843
|
+
forbidden: (mod, act, msg = "Access denied") => new AppError(403, mod, CAT.PERMISSION, act, msg),
|
|
844
|
+
badRequest: (mod, act, msg = "Bad request") => new AppError(400, mod, CAT.VALIDATION, act, msg),
|
|
845
|
+
notFound: (mod, act = ACT.GENERIC, msg = "Record not found") => new AppError(404, mod, CAT.VALIDATION, act, msg),
|
|
846
|
+
conflict: (mod, act, msg = "Record already exists") => new AppError(409, mod, CAT.INTEGRITY, act, msg),
|
|
847
|
+
integrity: (mod, act = ACT.GENERIC, msg = "Data integrity violation") => new AppError(409, mod, CAT.INTEGRITY, act, msg),
|
|
848
|
+
subscription: (mod, msg = "Module locked or subscription required") => new AppError(403, mod, CAT.SUBSCRIPTION, ACT.GENERIC, msg),
|
|
849
|
+
internal: (mod, msg = "Internal server error") => new AppError(500, mod, CAT.INTEGRITY, ACT.GENERIC, msg)
|
|
850
|
+
};
|
|
851
|
+
var handleAppErrorResponse = (error, mod = MOD.ADMIN) => {
|
|
852
|
+
if (error instanceof AppError && error.isOperational) {
|
|
853
|
+
return Response.json(
|
|
854
|
+
{ error: { appCode: error.appCode, message: error.message } },
|
|
855
|
+
{ status: error.status }
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
const e = error;
|
|
859
|
+
console.error(`[${mod}] UNEXPECTED ERROR:`, e?.message);
|
|
860
|
+
console.error(`[${mod}] STACK:`, e?.stack);
|
|
861
|
+
return Response.json(
|
|
862
|
+
{ error: { appCode: `${mod}-500-000`, message: "An unexpected server error occurred. Please try again." } },
|
|
863
|
+
{ status: 500 }
|
|
864
|
+
);
|
|
865
|
+
};
|
|
866
|
+
var FALLBACK = {
|
|
867
|
+
title: "Something Went Wrong",
|
|
868
|
+
text: "An unexpected error occurred. Please try again or contact your administrator."
|
|
869
|
+
};
|
|
870
|
+
var resolveAppError = (appCode) => {
|
|
871
|
+
if (!appCode || typeof appCode !== "string") {
|
|
872
|
+
return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
|
|
873
|
+
}
|
|
874
|
+
const parts = appCode.split("-");
|
|
875
|
+
if (parts.length !== 3) {
|
|
876
|
+
return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
|
|
877
|
+
}
|
|
878
|
+
const [mod, status, catAct] = parts;
|
|
879
|
+
const details = ERROR_DICTIONARY[catAct] || FALLBACK;
|
|
880
|
+
return {
|
|
881
|
+
title: details.title,
|
|
882
|
+
text: details.text,
|
|
883
|
+
module: mod,
|
|
884
|
+
moduleLabel: MODULE_LABELS[mod] || mod,
|
|
885
|
+
status: parseInt(status, 10),
|
|
886
|
+
catAct,
|
|
887
|
+
isSubscriptionIssue: catAct.startsWith("1"),
|
|
888
|
+
isPermissionIssue: catAct.startsWith("2")
|
|
889
|
+
};
|
|
890
|
+
};
|
|
891
|
+
var extractAppCode = (error) => {
|
|
892
|
+
const e = error;
|
|
893
|
+
return e?.response?.data?.error?.appCode ?? e?.data?.error?.appCode ?? null;
|
|
894
|
+
};
|
|
895
|
+
var resolveError = (error) => {
|
|
896
|
+
const appCode = extractAppCode(error);
|
|
897
|
+
if (appCode) return resolveAppError(appCode);
|
|
898
|
+
const e = error;
|
|
899
|
+
return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: e?.status || 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
|
|
900
|
+
};
|
|
901
|
+
function generateCanonicalId() {
|
|
902
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
903
|
+
return crypto.randomUUID();
|
|
904
|
+
}
|
|
905
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
906
|
+
const r = Math.random() * 16 | 0;
|
|
907
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
function generateInfrastructureFields(activeScope, availableScopes) {
|
|
911
|
+
if (!activeScope || !availableScopes?.length) {
|
|
912
|
+
throw ErrorFactory.unauthorized("[generateInfrastructureFields] Missing scope context.");
|
|
913
|
+
}
|
|
914
|
+
let companyId = null;
|
|
915
|
+
let legalEntityId = null;
|
|
916
|
+
let facilityId = null;
|
|
917
|
+
let pointer = activeScope;
|
|
918
|
+
while (pointer) {
|
|
919
|
+
if (pointer.type === "company") companyId = pointer.base44Id;
|
|
920
|
+
if (pointer.type === "legalEntity") legalEntityId = pointer.base44Id;
|
|
921
|
+
if (pointer.type === "facility") facilityId = pointer.base44Id;
|
|
922
|
+
const parentId = pointer.parentId ?? null;
|
|
923
|
+
pointer = parentId ? availableScopes.find((s) => s.base44Id === parentId) || null : null;
|
|
924
|
+
}
|
|
925
|
+
if (!companyId) {
|
|
926
|
+
throw ErrorFactory.unauthorized("[generateInfrastructureFields] Could not resolve companyId from scope tree.");
|
|
927
|
+
}
|
|
928
|
+
return {
|
|
929
|
+
canonicalId: crypto.randomUUID(),
|
|
930
|
+
companyId,
|
|
931
|
+
legalEntityId,
|
|
932
|
+
facilityId,
|
|
933
|
+
authScopeId: activeScope.authScopeId
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
function buildRlsFilter(session, extra = {}) {
|
|
937
|
+
return { ...extra, authScopeId: { $in: session.readScopes || [] } };
|
|
938
|
+
}
|
|
939
|
+
function canRead(session, authScopeId) {
|
|
940
|
+
return session.readScopes?.includes(authScopeId) ?? false;
|
|
941
|
+
}
|
|
942
|
+
function canWrite(session, authScopeId, resourcePath) {
|
|
943
|
+
const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
|
|
944
|
+
if (override === "WRITE") return true;
|
|
945
|
+
if (override === "NONE" || override === "READ") return false;
|
|
946
|
+
return session.writeScopes?.includes(authScopeId) ?? false;
|
|
947
|
+
}
|
|
948
|
+
function assertCanWrite(session, authScopeId, resourcePath) {
|
|
949
|
+
const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
|
|
950
|
+
if (override === "WRITE") return;
|
|
951
|
+
if (override === "NONE" || override === "READ") {
|
|
952
|
+
throw new AppError(
|
|
953
|
+
403,
|
|
954
|
+
MOD.SESSION,
|
|
955
|
+
CAT.PERMISSION,
|
|
956
|
+
ACT.GENERIC,
|
|
957
|
+
`You do not have write access to "${resourcePath}" in this scope.`
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
if (session.writeScopes?.includes(authScopeId)) return;
|
|
961
|
+
throw new AppError(
|
|
962
|
+
403,
|
|
963
|
+
MOD.SESSION,
|
|
964
|
+
CAT.PERMISSION,
|
|
965
|
+
ACT.GENERIC,
|
|
966
|
+
"You do not have permission to modify records in this scope."
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
function resolveAccess(session, activeScopeId, tabConfig) {
|
|
970
|
+
const resourcePath = tabConfig?.resourceId;
|
|
971
|
+
const overrides = session.resourceOverrides?.[activeScopeId] ?? {};
|
|
972
|
+
if (resourcePath) {
|
|
973
|
+
const segments = resourcePath.split(".");
|
|
974
|
+
for (let len = segments.length; len >= 1; len--) {
|
|
975
|
+
const path = segments.slice(0, len).join(".");
|
|
976
|
+
const override = overrides[path];
|
|
977
|
+
if (override === "NONE" || override === "READ" || override === "WRITE") return override;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
const allowedRoles = tabConfig?.allowedRoles ?? [];
|
|
981
|
+
const requiredPrivileges = tabConfig?.requiredPrivileges ?? [];
|
|
982
|
+
const hasRestrictions = allowedRoles.length > 0 || requiredPrivileges.length > 0;
|
|
983
|
+
if (hasRestrictions) {
|
|
984
|
+
const role = session?.role ?? "";
|
|
985
|
+
const privileges = session?.privileges ?? [];
|
|
986
|
+
const passesRole = allowedRoles.length > 0 && allowedRoles.includes(role);
|
|
987
|
+
const passesPrivilege = requiredPrivileges.length > 0 && requiredPrivileges.some((p) => privileges.includes(p));
|
|
988
|
+
return passesRole || passesPrivilege ? "WRITE" : "NONE";
|
|
989
|
+
}
|
|
990
|
+
return "READ";
|
|
991
|
+
}
|
|
992
|
+
function resolveMenuVisibility(session, authScopeId, resourcePath) {
|
|
993
|
+
const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
|
|
994
|
+
if (override === "NONE") return "hidden";
|
|
995
|
+
if (override === "READ") return "read_only";
|
|
996
|
+
if (override === "WRITE") return "active";
|
|
997
|
+
if (session.writeScopes?.includes(authScopeId)) return "active";
|
|
998
|
+
if (session.readScopes?.includes(authScopeId)) return "read_only";
|
|
999
|
+
return "hidden";
|
|
1000
|
+
}
|
|
1001
|
+
function isTabVisible(session, activeScopeId, tabConfig) {
|
|
1002
|
+
return resolveAccess(session, activeScopeId, tabConfig) !== "NONE";
|
|
1003
|
+
}
|
|
1004
|
+
function isTabWritable(session, activeScopeId, tabConfig) {
|
|
1005
|
+
return resolveAccess(session, activeScopeId, tabConfig) === "WRITE";
|
|
1006
|
+
}
|
|
988
1007
|
function evaluateBaseAccess(resourcePath, session, requirements = {}) {
|
|
989
1008
|
if (!session?.role) return "NONE";
|
|
990
1009
|
if (session.role === UserRole.OWNER) return "WRITE";
|
|
@@ -1061,42 +1080,31 @@ async function verifyAndExtractSession(token, secret) {
|
|
|
1061
1080
|
throw ErrorFactory.unauthorized(MOD.SESSION, "UNAUTHORIZED: No secure session token provided.");
|
|
1062
1081
|
}
|
|
1063
1082
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
DocumentType2["HEAVY_METAL"] = "HEAVY_METAL";
|
|
1090
|
-
DocumentType2["MICROBIAL"] = "MICROBIAL";
|
|
1091
|
-
DocumentType2["HARVEST_LOG"] = "HARVEST_LOG";
|
|
1092
|
-
DocumentType2["PACKHOUSE_INSPECTION"] = "PACKHOUSE_INSPECTION";
|
|
1093
|
-
DocumentType2["TRAINING_CERTIFICATE"] = "TRAINING_CERTIFICATE";
|
|
1094
|
-
DocumentType2["INVOICE"] = "INVOICE";
|
|
1095
|
-
DocumentType2["LEGAL_CONTRACT"] = "LEGAL_CONTRACT";
|
|
1096
|
-
DocumentType2["AUDIT_REPORT"] = "AUDIT_REPORT";
|
|
1097
|
-
DocumentType2["SENSITIVE_IDENTITY"] = "SENSITIVE_IDENTITY";
|
|
1098
|
-
return DocumentType2;
|
|
1099
|
-
})(DocumentType || {});
|
|
1083
|
+
function getFormMeta(componentId) {
|
|
1084
|
+
return FORM_REGISTRY[componentId] ?? null;
|
|
1085
|
+
}
|
|
1086
|
+
function getFormsGroupedByModule() {
|
|
1087
|
+
const groups = {};
|
|
1088
|
+
for (const [id, meta] of Object.entries(FORM_REGISTRY)) {
|
|
1089
|
+
if (!groups[meta.module]) groups[meta.module] = [];
|
|
1090
|
+
groups[meta.module].push({ id, ...meta });
|
|
1091
|
+
}
|
|
1092
|
+
return groups;
|
|
1093
|
+
}
|
|
1094
|
+
var getTaskTypeOptions = () => Object.entries(TASK_TYPE_REGISTRY).map(([value, config]) => ({
|
|
1095
|
+
value,
|
|
1096
|
+
label: config.label,
|
|
1097
|
+
description: config.description,
|
|
1098
|
+
mimeTypes: config.mimeTypes,
|
|
1099
|
+
icon: config.icon
|
|
1100
|
+
}));
|
|
1101
|
+
var getAcceptedMimeTypes = (taskType) => {
|
|
1102
|
+
const config = TASK_TYPE_REGISTRY[taskType];
|
|
1103
|
+
return config ? config.mimeTypes.join(",") : "*/*";
|
|
1104
|
+
};
|
|
1105
|
+
var getApproveAction = (taskType) => {
|
|
1106
|
+
return TASK_TYPE_REGISTRY[taskType]?.approveAction ?? null;
|
|
1107
|
+
};
|
|
1100
1108
|
function generateDocumentPath(params) {
|
|
1101
1109
|
const sanitizedName = params.siteName.replace(/[^a-z0-9]/gi, "_");
|
|
1102
1110
|
if (params.isStatic) {
|
|
@@ -1148,6 +1156,7 @@ function calculateFileMetadataMatch(criteria, fileMetadata, auditContext) {
|
|
|
1148
1156
|
CAT,
|
|
1149
1157
|
Converter,
|
|
1150
1158
|
CropCycleStatus,
|
|
1159
|
+
DOCUMENT_MENU_MAP,
|
|
1151
1160
|
DocumentType,
|
|
1152
1161
|
ERROR_DICTIONARY,
|
|
1153
1162
|
EVERYONE,
|