@litusarchieve18/agricore-utils 1.0.11 → 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,8 @@ __export(index_exports, {
32
32
  CAT: () => CAT,
33
33
  Converter: () => Converter,
34
34
  CropCycleStatus: () => CropCycleStatus,
35
+ DOCUMENT_MENU_MAP: () => DOCUMENT_MENU_MAP,
36
+ DocumentType: () => DocumentType,
35
37
  ERROR_DICTIONARY: () => ERROR_DICTIONARY,
36
38
  EVERYONE: () => EVERYONE,
37
39
  EmitterType: () => EmitterType,
@@ -72,12 +74,14 @@ __export(index_exports, {
72
74
  assertCanWrite: () => assertCanWrite,
73
75
  assertTenantBoundary: () => assertTenantBoundary,
74
76
  buildRlsFilter: () => buildRlsFilter,
77
+ calculateFileMetadataMatch: () => calculateFileMetadataMatch,
75
78
  canRead: () => canRead,
76
79
  canWrite: () => canWrite,
77
80
  evaluateBaseAccess: () => evaluateBaseAccess,
78
81
  extractAppCode: () => extractAppCode,
79
82
  findSpecificOverride: () => findSpecificOverride,
80
83
  generateCanonicalId: () => generateCanonicalId,
84
+ generateDocumentPath: () => generateDocumentPath,
81
85
  generateInfrastructureFields: () => generateInfrastructureFields,
82
86
  getAcceptedMimeTypes: () => getAcceptedMimeTypes,
83
87
  getApproveAction: () => getApproveAction,
@@ -284,7 +288,7 @@ var Converter = {
284
288
  }
285
289
  };
286
290
 
287
- // src/index.ts
291
+ // src/constants.ts
288
292
  var MOD = {
289
293
  OPERATIONS: "OPR",
290
294
  EQUIPMENT: "EQP",
@@ -298,7 +302,6 @@ var MOD = {
298
302
  ALERTS: "ALT",
299
303
  INFRA: "INF",
300
304
  SESSION: "SES"
301
- // ← added: used in generateSessionContext but was missing from errorRegistry.js
302
305
  };
303
306
  var CAT = {
304
307
  SUBSCRIPTION: "1",
@@ -315,43 +318,6 @@ var ACT = {
315
318
  UPLOAD: "05"
316
319
  };
317
320
  var SENTINEL_UUID = "00000000-0000-0000-0000-000000000000";
318
- var AppError = class extends Error {
319
- status;
320
- appCode;
321
- isOperational;
322
- constructor(status, mod, cat, act, message) {
323
- super(message);
324
- this.status = status;
325
- this.appCode = `${mod}-${status}-${cat}${act}`;
326
- this.isOperational = true;
327
- Object.setPrototypeOf(this, new.target.prototype);
328
- }
329
- };
330
- var ErrorFactory = {
331
- unauthorized: (mod, msg = "Authentication required") => new AppError(401, mod, CAT.PERMISSION, ACT.GENERIC, msg),
332
- forbidden: (mod, act, msg = "Access denied") => new AppError(403, mod, CAT.PERMISSION, act, msg),
333
- badRequest: (mod, act, msg = "Bad request") => new AppError(400, mod, CAT.VALIDATION, act, msg),
334
- notFound: (mod, act = ACT.GENERIC, msg = "Record not found") => new AppError(404, mod, CAT.VALIDATION, act, msg),
335
- conflict: (mod, act, msg = "Record already exists") => new AppError(409, mod, CAT.INTEGRITY, act, msg),
336
- integrity: (mod, act = ACT.GENERIC, msg = "Data integrity violation") => new AppError(409, mod, CAT.INTEGRITY, act, msg),
337
- subscription: (mod, msg = "Module locked or subscription required") => new AppError(403, mod, CAT.SUBSCRIPTION, ACT.GENERIC, msg),
338
- internal: (mod, msg = "Internal server error") => new AppError(500, mod, CAT.INTEGRITY, ACT.GENERIC, msg)
339
- };
340
- var handleAppErrorResponse = (error, mod = MOD.ADMIN) => {
341
- if (error instanceof AppError && error.isOperational) {
342
- return Response.json(
343
- { error: { appCode: error.appCode, message: error.message } },
344
- { status: error.status }
345
- );
346
- }
347
- const e = error;
348
- console.error(`[${mod}] UNEXPECTED ERROR:`, e?.message);
349
- console.error(`[${mod}] STACK:`, e?.stack);
350
- return Response.json(
351
- { error: { appCode: `${mod}-500-000`, message: "An unexpected server error occurred. Please try again." } },
352
- { status: 500 }
353
- );
354
- };
355
321
  var MODULE_LABELS = {
356
322
  [MOD.OPERATIONS]: "Operations",
357
323
  [MOD.EQUIPMENT]: "Equipment & Fleet",
@@ -389,147 +355,6 @@ var ERROR_DICTIONARY = {
389
355
  "403": { title: "Edit Conflict", text: "This record was recently updated by someone else. Please refresh and try again." },
390
356
  "404": { title: "Record In Use", text: "This record cannot be deleted because it is referenced by other data." }
391
357
  };
392
- var FALLBACK = {
393
- title: "Something Went Wrong",
394
- text: "An unexpected error occurred. Please try again or contact your administrator."
395
- };
396
- var resolveAppError = (appCode) => {
397
- if (!appCode || typeof appCode !== "string") {
398
- return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
399
- }
400
- const parts = appCode.split("-");
401
- if (parts.length !== 3) {
402
- return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
403
- }
404
- const [mod, status, catAct] = parts;
405
- const details = ERROR_DICTIONARY[catAct] || FALLBACK;
406
- return {
407
- title: details.title,
408
- text: details.text,
409
- module: mod,
410
- moduleLabel: MODULE_LABELS[mod] || mod,
411
- status: parseInt(status, 10),
412
- catAct,
413
- isSubscriptionIssue: catAct.startsWith("1"),
414
- isPermissionIssue: catAct.startsWith("2")
415
- };
416
- };
417
- var extractAppCode = (error) => {
418
- const e = error;
419
- return e?.response?.data?.error?.appCode ?? e?.data?.error?.appCode ?? null;
420
- };
421
- var resolveError = (error) => {
422
- const appCode = extractAppCode(error);
423
- if (appCode) return resolveAppError(appCode);
424
- const e = error;
425
- return { ...FALLBACK, module: "UNK", moduleLabel: "Unknown", status: e?.status || 500, catAct: "000", isSubscriptionIssue: false, isPermissionIssue: false };
426
- };
427
- function generateCanonicalId() {
428
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
429
- return crypto.randomUUID();
430
- }
431
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
432
- const r = Math.random() * 16 | 0;
433
- return (c === "x" ? r : r & 3 | 8).toString(16);
434
- });
435
- }
436
- function generateInfrastructureFields(activeScope, availableScopes) {
437
- if (!activeScope || !availableScopes?.length) {
438
- throw ErrorFactory.unauthorized("[generateInfrastructureFields] Missing scope context.");
439
- }
440
- let companyId = null;
441
- let legalEntityId = null;
442
- let facilityId = null;
443
- let pointer = activeScope;
444
- while (pointer) {
445
- if (pointer.type === "company") companyId = pointer.base44Id;
446
- if (pointer.type === "legalEntity") legalEntityId = pointer.base44Id;
447
- if (pointer.type === "facility") facilityId = pointer.base44Id;
448
- const parentId = pointer.parentId ?? null;
449
- pointer = parentId ? availableScopes.find((s) => s.base44Id === parentId) || null : null;
450
- }
451
- if (!companyId) {
452
- throw ErrorFactory.unauthorized("[generateInfrastructureFields] Could not resolve companyId from scope tree.");
453
- }
454
- return {
455
- canonicalId: crypto.randomUUID(),
456
- companyId,
457
- legalEntityId,
458
- facilityId,
459
- authScopeId: activeScope.authScopeId
460
- };
461
- }
462
- function buildRlsFilter(session, extra = {}) {
463
- return { ...extra, authScopeId: { $in: session.readScopes || [] } };
464
- }
465
- function canRead(session, authScopeId) {
466
- return session.readScopes?.includes(authScopeId) ?? false;
467
- }
468
- function canWrite(session, authScopeId, resourcePath) {
469
- const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
470
- if (override === "WRITE") return true;
471
- if (override === "NONE" || override === "READ") return false;
472
- return session.writeScopes?.includes(authScopeId) ?? false;
473
- }
474
- function assertCanWrite(session, authScopeId, resourcePath) {
475
- const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
476
- if (override === "WRITE") return;
477
- if (override === "NONE" || override === "READ") {
478
- throw new AppError(
479
- 403,
480
- MOD.SESSION,
481
- CAT.PERMISSION,
482
- ACT.GENERIC,
483
- `You do not have write access to "${resourcePath}" in this scope.`
484
- );
485
- }
486
- if (session.writeScopes?.includes(authScopeId)) return;
487
- throw new AppError(
488
- 403,
489
- MOD.SESSION,
490
- CAT.PERMISSION,
491
- ACT.GENERIC,
492
- "You do not have permission to modify records in this scope."
493
- );
494
- }
495
- function resolveAccess(session, activeScopeId, tabConfig) {
496
- const resourcePath = tabConfig?.resourceId;
497
- const overrides = session.resourceOverrides?.[activeScopeId] ?? {};
498
- if (resourcePath) {
499
- const segments = resourcePath.split(".");
500
- for (let len = segments.length; len >= 1; len--) {
501
- const path = segments.slice(0, len).join(".");
502
- const override = overrides[path];
503
- if (override === "NONE" || override === "READ" || override === "WRITE") return override;
504
- }
505
- }
506
- const allowedRoles = tabConfig?.allowedRoles ?? [];
507
- const requiredPrivileges = tabConfig?.requiredPrivileges ?? [];
508
- const hasRestrictions = allowedRoles.length > 0 || requiredPrivileges.length > 0;
509
- if (hasRestrictions) {
510
- const role = session?.role ?? "";
511
- const privileges = session?.privileges ?? [];
512
- const passesRole = allowedRoles.length > 0 && allowedRoles.includes(role);
513
- const passesPrivilege = requiredPrivileges.length > 0 && requiredPrivileges.some((p) => privileges.includes(p));
514
- return passesRole || passesPrivilege ? "WRITE" : "NONE";
515
- }
516
- return "READ";
517
- }
518
- function resolveMenuVisibility(session, authScopeId, resourcePath) {
519
- const override = session.resourceOverrides?.[authScopeId]?.[resourcePath];
520
- if (override === "NONE") return "hidden";
521
- if (override === "READ") return "read_only";
522
- if (override === "WRITE") return "active";
523
- if (session.writeScopes?.includes(authScopeId)) return "active";
524
- if (session.readScopes?.includes(authScopeId)) return "read_only";
525
- return "hidden";
526
- }
527
- function isTabVisible(session, activeScopeId, tabConfig) {
528
- return resolveAccess(session, activeScopeId, tabConfig) !== "NONE";
529
- }
530
- function isTabWritable(session, activeScopeId, tabConfig) {
531
- return resolveAccess(session, activeScopeId, tabConfig) === "WRITE";
532
- }
533
358
  var UserRole = {
534
359
  OWNER: "owner",
535
360
  MANAGER: "manager",
@@ -749,17 +574,6 @@ var FORM_REGISTRY = {
749
574
  // ── Audit & Compliance ───────────────────────────────────────────────────
750
575
  auditProjectForm: { label: "Audit Project", menuUrl: "/admin", module: "Audit & Compliance" }
751
576
  };
752
- function getFormMeta(componentId) {
753
- return FORM_REGISTRY[componentId] ?? null;
754
- }
755
- function getFormsGroupedByModule() {
756
- const groups = {};
757
- for (const [id, meta] of Object.entries(FORM_REGISTRY)) {
758
- if (!groups[meta.module]) groups[meta.module] = [];
759
- groups[meta.module].push({ id, ...meta });
760
- }
761
- return groups;
762
- }
763
577
  var TASK_TYPE_REGISTRY = {
764
578
  INVOICE_OCR: {
765
579
  label: "Invoice / Receipt OCR",
@@ -794,20 +608,6 @@ var TASK_TYPE_REGISTRY = {
794
608
  approveAction: "ATTACH_REPORT_FILE"
795
609
  }
796
610
  };
797
- var getTaskTypeOptions = () => Object.entries(TASK_TYPE_REGISTRY).map(([value, config]) => ({
798
- value,
799
- label: config.label,
800
- description: config.description,
801
- mimeTypes: config.mimeTypes,
802
- icon: config.icon
803
- }));
804
- var getAcceptedMimeTypes = (taskType) => {
805
- const config = TASK_TYPE_REGISTRY[taskType];
806
- return config ? config.mimeTypes.join(",") : "*/*";
807
- };
808
- var getApproveAction = (taskType) => {
809
- return TASK_TYPE_REGISTRY[taskType]?.approveAction ?? null;
810
- };
811
611
  var RESOURCE_PATHS = {
812
612
  // ── Top-level menu sections ────────────────────────────────────────────────
813
613
  dashboard: "dashboard",
@@ -859,7 +659,6 @@ var AGRI_ONLY = [
859
659
  ];
860
660
  var RESOURCE_MODULE_MAP = {
861
661
  // ── Top-level menu sections ────────────────────────────────────────────────
862
- // CORE features (accessible to everyone with an account)
863
662
  [RESOURCE_PATHS.dashboard]: [],
864
663
  [RESOURCE_PATHS.operations]: ALL_OPERATIONS,
865
664
  [RESOURCE_PATHS.equipment]: ALL_OPERATIONS,
@@ -914,17 +713,8 @@ var ROLE_SECTIONS_BY_KEY = {
914
713
  };
915
714
  var EVERYONE = Object.values(UserRole);
916
715
  var RESOURCE_REQUIREMENTS = {
917
- [RESOURCE_PATHS.dashboard]: {
918
- allowedRoles: EVERYONE
919
- },
920
- [RESOURCE_PATHS.operations]: {
921
- allowedRoles: EVERYONE
922
- },
923
- // [RESOURCE_PATHS.equipment]: EVERYONE,
924
- // [RESOURCE_PATHS.safety]: ALL_OPERATIONS,
925
- // [RESOURCE_PATHS.team]: ALL_OPERATIONS,
926
- // [RESOURCE_PATHS.records]: ALL_OPERATIONS,
927
- // [RESOURCE_PATHS.adminSettings]: ALL_OPERATIONS,
716
+ [RESOURCE_PATHS.dashboard]: { allowedRoles: EVERYONE },
717
+ [RESOURCE_PATHS.operations]: { allowedRoles: EVERYONE },
928
718
  // ── Records & Reports ──────────────────────────────────────────────────────
929
719
  [RESOURCE_PATHS.documentHub]: {
930
720
  allowedRoles: [UserRole.OWNER, UserRole.MANAGER, UserRole.SUPERVISOR],
@@ -946,7 +736,6 @@ var RESOURCE_REQUIREMENTS = {
946
736
  allowedRoles: [UserRole.OWNER, UserRole.MANAGER, UserRole.SUPERVISOR],
947
737
  requiredPrivileges: [UserPrivilege.ADMIN, UserPrivilege.AUDIT_COMPLIANCE, UserPrivilege.FINANCE, UserPrivilege.HR]
948
738
  },
949
- // [RESOURCE_PATHS.analytics]: ALL_OPERATIONS,
950
739
  // ── Admin Settings ─────────────────────────────────────────────────────────
951
740
  [RESOURCE_PATHS.adminUserRoster]: {
952
741
  allowedRoles: [UserRole.OWNER],
@@ -963,25 +752,258 @@ var RESOURCE_REQUIREMENTS = {
963
752
  [RESOURCE_PATHS.adminCompanySettings]: {
964
753
  allowedRoles: [UserRole.OWNER]
965
754
  }
966
- // // ── Operations ────────────────────────────────────────────────────────────
967
- // [RESOURCE_PATHS.farmManagement]: [EnabledModule.FARM_MANAGEMENT],
968
- // [RESOURCE_PATHS.packhouse]: [EnabledModule.PACKHOUSE],
969
- // [RESOURCE_PATHS.accommodation]: [EnabledModule.ACCOMMODATION],
970
- // // ── Equipment & Fleet ──────────────────────────────────────────────────────
971
- // [RESOURCE_PATHS.equipPreStart]: ALL_OPERATIONS,
972
- // [RESOURCE_PATHS.equipMaintenance]: ALL_OPERATIONS,
973
- // [RESOURCE_PATHS.equipFuelRegister]: ALL_OPERATIONS,
974
- // [RESOURCE_PATHS.equipCalibration]: AGRI_ONLY,
975
- // [RESOURCE_PATHS.equipFleet]: ALL_OPERATIONS,
976
- // // ── Safety, Quality & Compliance ──────────────────────────────────────────
977
- // [RESOURCE_PATHS.safetyAuditing]: ALL_OPERATIONS,
978
- // [RESOURCE_PATHS.safetyFood]: AGRI_ONLY,
979
- // [RESOURCE_PATHS.safetyWhs]: ALL_OPERATIONS,
980
- // [RESOURCE_PATHS.safetyCleaning]: ALL_OPERATIONS,
981
- // // ── Team & HR ──────────────────────────────────────────────────────────────
982
- // [RESOURCE_PATHS.teamStaff]: ALL_OPERATIONS,
983
- // [RESOURCE_PATHS.teamTraining]: ALL_OPERATIONS,
984
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
+ }
985
1007
  function evaluateBaseAccess(resourcePath, session, requirements = {}) {
986
1008
  if (!session?.role) return "NONE";
987
1009
  if (session.role === UserRole.OWNER) return "WRITE";
@@ -1058,6 +1080,68 @@ async function verifyAndExtractSession(token, secret) {
1058
1080
  throw ErrorFactory.unauthorized(MOD.SESSION, "UNAUTHORIZED: No secure session token provided.");
1059
1081
  }
1060
1082
  }
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
+ };
1108
+ function generateDocumentPath(params) {
1109
+ const sanitizedName = params.siteName.replace(/[^a-z0-9]/gi, "_");
1110
+ if (params.isStatic) {
1111
+ return `${sanitizedName}/_CORE/${params.docType}`;
1112
+ } else {
1113
+ const folderYear = params.year || (/* @__PURE__ */ new Date()).getUTCFullYear();
1114
+ const folderCrop = params.crop ? `/${params.crop.toUpperCase()}` : "";
1115
+ return `${sanitizedName}/_SEASONAL/${folderYear}/${params.docType}${folderCrop}`;
1116
+ }
1117
+ }
1118
+ function isValueMatch(fileValue, expectedValue) {
1119
+ if (Array.isArray(expectedValue)) return expectedValue.includes(fileValue);
1120
+ return fileValue === expectedValue;
1121
+ }
1122
+ function calculateFileMetadataMatch(criteria, fileMetadata, auditContext) {
1123
+ for (const [key, expectedValue] of Object.entries(criteria.mustMatch)) {
1124
+ if (!isValueMatch(fileMetadata[key], expectedValue)) return 0;
1125
+ }
1126
+ if (criteria.mustMatchContext) {
1127
+ for (const field of criteria.mustMatchContext) {
1128
+ const contextValue = auditContext[field];
1129
+ if (contextValue === void 0) continue;
1130
+ if (!isValueMatch(fileMetadata[field], contextValue)) return 0;
1131
+ }
1132
+ }
1133
+ if (fileMetadata.isStatic === true) return 100;
1134
+ if (!criteria.contextMatch || criteria.contextMatch.length === 0) return 100;
1135
+ let matches = 0;
1136
+ let validChecks = 0;
1137
+ criteria.contextMatch.forEach((field) => {
1138
+ const contextValue = auditContext[field];
1139
+ if (contextValue === void 0) return;
1140
+ validChecks++;
1141
+ if (isValueMatch(fileMetadata[field], contextValue)) matches++;
1142
+ });
1143
+ return validChecks > 0 ? Math.round(matches / validChecks * 100) : 100;
1144
+ }
1061
1145
  // Annotate the CommonJS export names for ESM import in node:
1062
1146
  0 && (module.exports = {
1063
1147
  ACCESS_RANK,
@@ -1072,6 +1156,8 @@ async function verifyAndExtractSession(token, secret) {
1072
1156
  CAT,
1073
1157
  Converter,
1074
1158
  CropCycleStatus,
1159
+ DOCUMENT_MENU_MAP,
1160
+ DocumentType,
1075
1161
  ERROR_DICTIONARY,
1076
1162
  EVERYONE,
1077
1163
  EmitterType,
@@ -1112,12 +1198,14 @@ async function verifyAndExtractSession(token, secret) {
1112
1198
  assertCanWrite,
1113
1199
  assertTenantBoundary,
1114
1200
  buildRlsFilter,
1201
+ calculateFileMetadataMatch,
1115
1202
  canRead,
1116
1203
  canWrite,
1117
1204
  evaluateBaseAccess,
1118
1205
  extractAppCode,
1119
1206
  findSpecificOverride,
1120
1207
  generateCanonicalId,
1208
+ generateDocumentPath,
1121
1209
  generateInfrastructureFields,
1122
1210
  getAcceptedMimeTypes,
1123
1211
  getApproveAction,