@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/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/index.ts
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
- allowedRoles: EVERYONE
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
- var DocumentType = /* @__PURE__ */ ((DocumentType2) => {
1065
- DocumentType2["SPRAY_RECORD"] = "SPRAY_RECORD";
1066
- DocumentType2["FERTIGATION_RECORD"] = "FERTIGATION_RECORD";
1067
- DocumentType2["FERTILIZER_RECORD"] = "FERTILIZER_RECORD";
1068
- DocumentType2["QA"] = "QA";
1069
- DocumentType2["CLEANING"] = "CLEANING";
1070
- DocumentType2["PEST"] = "PEST";
1071
- DocumentType2["EQUIPMENT_CALIBRATION_RECORD"] = "EQUIPMENT_CALIBRATION_RECORD";
1072
- DocumentType2["INVENTORY_CONSUMABLES"] = "INVENTORY_CONSUMABLES";
1073
- DocumentType2["INVENTORY_BOX_CARTON"] = "INVENTORY_BOX_CARTON";
1074
- DocumentType2["INVENTORY_CHEMICALS"] = "INVENTORY_CHEMICALS";
1075
- DocumentType2["STOCKTAKE"] = "STOCKTAKE";
1076
- DocumentType2["STOCKTAKE_MSDS"] = "STOCKTAKE_MSDS";
1077
- DocumentType2["MAPPING_FARM_MAPS"] = "MAPPING_FARM_MAPS";
1078
- DocumentType2["MAPPING_TRAFIC_MANAGEMENT"] = "MAPPING_TRAFIC_MANAGEMENT";
1079
- DocumentType2["MAPPING_EMERGENCY"] = "MAPPING_EMERGENCY";
1080
- DocumentType2["INCIDENT_REPORT"] = "INCIDENT_REPORT";
1081
- DocumentType2["TRAINING_RECORDS"] = "TRAINING_RECORDS";
1082
- DocumentType2["SOPS"] = "SOPS";
1083
- DocumentType2["RISK_ASSESSMENTS"] = "RISK_ASSESSMENTS";
1084
- DocumentType2["SERVICING_MAINTENANCE"] = "SERVICING_MAINTENANCE";
1085
- DocumentType2["SOIL_TEST"] = "SOIL_TEST";
1086
- DocumentType2["LEAF_TEST"] = "LEAF_TEST";
1087
- DocumentType2["WATER_TEST"] = "WATER_TEST";
1088
- DocumentType2["MRL_TESTING"] = "MRL_TESTING";
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,