@litusarchieve18/agricore-utils 1.0.10 → 1.0.12
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 +58 -0
- package/dist/index.d.mts +55 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +79 -0
- package/dist/index.mjs +76 -0
- package/package.json +37 -37
package/README.md
CHANGED
|
@@ -65,6 +65,8 @@ The universal vocabulary of the AgriCore platform, ensuring type-safety across a
|
|
|
65
65
|
🔐 Security & Access Control
|
|
66
66
|
The library now includes a centralized logic layer to enforce granular permissions across all AgriCore services.
|
|
67
67
|
|
|
68
|
+
---------------------------------------------------------------------
|
|
69
|
+
|
|
68
70
|
evaluateBaseAccess: Automatically determines a user's base permission level (NONE, READ, or WRITE) for a specific resource path (e.g., records.financials). It respects the OWNER role "God Mode" bypass and uses ROLE_SECTIONS_BY_KEY to provide sensible defaults for different app sections.
|
|
69
71
|
|
|
70
72
|
Access Ranking (resolveEffectiveAccess): Implements an additive permission model. By ranking levels (NONE < READ < WRITE), it allows the system to compare base permissions against specific user overrides and resolve the highest authorized access level.
|
|
@@ -92,6 +94,8 @@ const recordToSave = {
|
|
|
92
94
|
|
|
93
95
|
To completely eliminate database bottlenecks and solve serverless rate-limiting, AgriCore has migrated to a state-of-the-art, "Zero-DB" authorization architecture. By decoupling our security rules from the database SDK, our backend API endpoints now resolve complex multi-tenant boundaries and granular role-based access controls in roughly 1 millisecond.
|
|
94
96
|
|
|
97
|
+
---------------------------------------------------------------------
|
|
98
|
+
|
|
95
99
|
Key Features of the New Security Engine:
|
|
96
100
|
|
|
97
101
|
One-Time Session Generation: On login, the backend dynamically aggregates a user's full hierarchical profile—including role assignments, availableScopes (Company > Legal Entity > Facility), and granular resourceOverrides—into a single, cryptographically signed JSON Web Token (JWT).
|
|
@@ -102,6 +106,56 @@ Smart Frontend Interceptor: A centralized React hook (useApiClient) acts as an a
|
|
|
102
106
|
|
|
103
107
|
Instant Context Switching: Because the JWT securely holds the user's entire "VIP List" of permitted scopes, users can instantly switch between farms, legal entities, and facilities in the frontend global dropdown without triggering a new authentication handshake or database query.
|
|
104
108
|
|
|
109
|
+
---------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
This Document Management Engine provides a standardized, compliant, and migration-ready architecture for handling agricultural records. It ensures that files are stored predictably and matched against audit requirements with high precision.
|
|
112
|
+
|
|
113
|
+
Document Management & Compliance Engine
|
|
114
|
+
This module handles the lifecycle of file assets, from standardized naming and path generation to intelligent metadata matching for compliance audits.
|
|
115
|
+
|
|
116
|
+
1. Standardized Taxonomy (DocumentType)
|
|
117
|
+
The DocumentType enum serves as the single source of truth for the AgriCore document ecosystem. It categorizes every record—from SPRAY_RECORD to MAPPING_FARM_MAPS—ensuring that the database remains searchable and consistent across different farms and legal entities.
|
|
118
|
+
|
|
119
|
+
2. Smart Routing (generateDocumentPath)
|
|
120
|
+
This function enforces the "Core vs. Seasonal" storage architecture. It ensures that permanent files (Fixed Assets) and crop-cycle files (Working Assets) are physically and logically separated:
|
|
121
|
+
|
|
122
|
+
Static Assets (isStatic: true): Routed to {SiteName}/_CORE/{DocumentType}.
|
|
123
|
+
|
|
124
|
+
Seasonal Assets: Routed to a strict temporal hierarchy: {SiteName}/_SEASONAL/{Year}/{DocumentType}/{Crop}.
|
|
125
|
+
|
|
126
|
+
3. Intelligence Engine (calculateFileMetadataMatch)
|
|
127
|
+
A 3-tier matching algorithm used to automatically suggest evidence for audit questions. It evaluates the relevance of a file based on three layers:
|
|
128
|
+
|
|
129
|
+
Static Hard Fails: Strict equality checks for properties like documentType.
|
|
130
|
+
|
|
131
|
+
Dynamic Hard Fails (mustMatchContext): Ensures files belong to the correct boundaries (e.g., siteId array inclusion) based on the current AuditHeader.
|
|
132
|
+
|
|
133
|
+
Soft Relevance Scoring (contextMatch): Calculates a percentage score based on environmental tags like seasonId or crop, allowing the UI to surface the "best matches" first.
|
|
134
|
+
|
|
135
|
+
Quick Example
|
|
136
|
+
TypeScript
|
|
137
|
+
// 1. Generate a path for a seasonal spray record
|
|
138
|
+
const path = generateDocumentPath({
|
|
139
|
+
siteName: "North Farm",
|
|
140
|
+
docType: DocumentType.SPRAY_RECORD,
|
|
141
|
+
year: 2026,
|
|
142
|
+
crop: "Mango"
|
|
143
|
+
});
|
|
144
|
+
// Output: North_Farm/_SEASONAL/2026/SPRAY_RECORD/MANGO
|
|
145
|
+
|
|
146
|
+
// 2. Score a file against an audit requirement
|
|
147
|
+
const score = calculateFileMetadataMatch(
|
|
148
|
+
{
|
|
149
|
+
mustMatch: { documentType: "SPRAY_RECORD" },
|
|
150
|
+
mustMatchContext: ["siteId"], // Hard fail if wrong farm
|
|
151
|
+
contextMatch: ["seasonId"] // Soft score for season relevance
|
|
152
|
+
},
|
|
153
|
+
file.metadata,
|
|
154
|
+
auditHeader.context
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
============================================================================
|
|
158
|
+
|
|
105
159
|
🛠️ Development & Publishing Guide
|
|
106
160
|
Zero Dependencies
|
|
107
161
|
To keep the package ultra-lightweight (~30KB), this library has zero runtime dependencies. All build tools (tsup, typescript) are strictly kept in devDependencies, and the package.json uses the "files": ["dist"] array to ensure only compiled code is uploaded.
|
|
@@ -129,6 +183,10 @@ Run the publish command:
|
|
|
129
183
|
Bash
|
|
130
184
|
npm publish --access public
|
|
131
185
|
📝 Version History
|
|
186
|
+
V1.0.12 — add some functionality to add a file tag
|
|
187
|
+
|
|
188
|
+
V1.0.11 — add userName and userEmail to AgriCoreSession
|
|
189
|
+
|
|
132
190
|
V1.0.10 — add an explicit exports map
|
|
133
191
|
|
|
134
192
|
V1.0.9 — added jwt function
|
package/dist/index.d.mts
CHANGED
|
@@ -23,6 +23,8 @@ interface ResourceOverrides {
|
|
|
23
23
|
*/
|
|
24
24
|
interface AgriCoreSession {
|
|
25
25
|
userId: string;
|
|
26
|
+
userName: string;
|
|
27
|
+
userEmail: string;
|
|
26
28
|
companyId: string;
|
|
27
29
|
activeScopeId: string | null;
|
|
28
30
|
companyConfig: CompanyConfig;
|
|
@@ -518,5 +520,57 @@ targets: {
|
|
|
518
520
|
expectedScopeType?: 'company' | 'legalEntity' | 'facility';
|
|
519
521
|
}): Promise<boolean>;
|
|
520
522
|
declare function verifyAndExtractSession(token: string, secret: string): Promise<AgriCoreSession>;
|
|
523
|
+
declare enum DocumentType {
|
|
524
|
+
SPRAY_RECORD = "SPRAY_RECORD",
|
|
525
|
+
FERTIGATION_RECORD = "FERTIGATION_RECORD",
|
|
526
|
+
FERTILIZER_RECORD = "FERTILIZER_RECORD",
|
|
527
|
+
QA = "QA",
|
|
528
|
+
CLEANING = "CLEANING",
|
|
529
|
+
PEST = "PEST",
|
|
530
|
+
EQUIPMENT_CALIBRATION_RECORD = "EQUIPMENT_CALIBRATION_RECORD",
|
|
531
|
+
INVENTORY_CONSUMABLES = "INVENTORY_CONSUMABLES",
|
|
532
|
+
INVENTORY_BOX_CARTON = "INVENTORY_BOX_CARTON",
|
|
533
|
+
INVENTORY_CHEMICALS = "INVENTORY_CHEMICALS",
|
|
534
|
+
STOCKTAKE = "STOCKTAKE",
|
|
535
|
+
STOCKTAKE_MSDS = "STOCKTAKE_MSDS",
|
|
536
|
+
MAPPING_FARM_MAPS = "MAPPING_FARM_MAPS",
|
|
537
|
+
MAPPING_TRAFIC_MANAGEMENT = "MAPPING_TRAFIC_MANAGEMENT",
|
|
538
|
+
MAPPING_EMERGENCY = "MAPPING_EMERGENCY",
|
|
539
|
+
INCIDENT_REPORT = "INCIDENT_REPORT",
|
|
540
|
+
TRAINING_RECORDS = "TRAINING_RECORDS",
|
|
541
|
+
SOPS = "SOPS",
|
|
542
|
+
RISK_ASSESSMENTS = "RISK_ASSESSMENTS",
|
|
543
|
+
SERVICING_MAINTENANCE = "SERVICING_MAINTENANCE",
|
|
544
|
+
SOIL_TEST = "SOIL_TEST",
|
|
545
|
+
LEAF_TEST = "LEAF_TEST",
|
|
546
|
+
WATER_TEST = "WATER_TEST",
|
|
547
|
+
MRL_TESTING = "MRL_TESTING",
|
|
548
|
+
HEAVY_METAL = "HEAVY_METAL",
|
|
549
|
+
MICROBIAL = "MICROBIAL",
|
|
550
|
+
HARVEST_LOG = "HARVEST_LOG",
|
|
551
|
+
PACKHOUSE_INSPECTION = "PACKHOUSE_INSPECTION",
|
|
552
|
+
TRAINING_CERTIFICATE = "TRAINING_CERTIFICATE",
|
|
553
|
+
INVOICE = "INVOICE",
|
|
554
|
+
LEGAL_CONTRACT = "LEGAL_CONTRACT",
|
|
555
|
+
AUDIT_REPORT = "AUDIT_REPORT",
|
|
556
|
+
SENSITIVE_IDENTITY = "SENSITIVE_IDENTITY"
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Generates a full folder path matching strict business requirements.
|
|
560
|
+
* Static: {SiteName}/_CORE/{DocumentType}
|
|
561
|
+
* Dynamic: {SiteName}/_SEASONAL/{Year}/{DocumentType}/{Crop}
|
|
562
|
+
*/
|
|
563
|
+
declare function generateDocumentPath(params: {
|
|
564
|
+
siteName: string;
|
|
565
|
+
docType: DocumentType;
|
|
566
|
+
isStatic?: boolean;
|
|
567
|
+
year?: number | string;
|
|
568
|
+
crop?: string;
|
|
569
|
+
}): string;
|
|
570
|
+
declare function calculateFileMetadataMatch(criteria: {
|
|
571
|
+
mustMatch: Record<string, any>;
|
|
572
|
+
mustMatchContext?: string[];
|
|
573
|
+
contextMatch?: string[];
|
|
574
|
+
}, fileMetadata: Record<string, any>, auditContext: Record<string, any>): number;
|
|
521
575
|
|
|
522
|
-
export { ACCESS_RANK, ACT, AccessLevel, type AccessLevelType, type AgriCoreSession, AgriLogger, AppError, ApprovalStatus, ApprovalType, AuditStatus, AuditType, type AuthScopeFields, type AvailableScope, CAT, type CompanyConfig, Converter, CropCycleStatus, ERROR_DICTIONARY, EVERYONE, EmitterType, EnabledModule, ErrorFactory, FORM_REGISTRY, FacilityType, type FormMeta, HarvestMethod, type InfrastructureFields, LinkedStatus, MOD, MODULE_LABELS, MicroclimateZone, MimeType, type ModCode, NettingType, NotificationMode, OrderStatus, type PermissionLevel, PhysicalState, PlantingMethod, RESOURCE_MODULE_MAP, RESOURCE_PATHS, RESOURCE_REQUIREMENTS, ROLE_SECTIONS_BY_KEY, RelationshipType, type ResolvedError, type ResourceOverrides, type ResourceRequirement, RowOrientation, SENTINEL_UUID, type ScopeType, SoilTexture, TASK_TYPE_REGISTRY, type TabConfig, TargetEntityType, TaskStatus, TaskType, type TaskTypeConfig, TransactionType, TrellisType, UserPrivilege, UserRole, type UserRoleType, Validator, VigorRating, WaterSource, assertCanWrite, assertTenantBoundary, buildRlsFilter, canRead, canWrite, evaluateBaseAccess, extractAppCode, findSpecificOverride, generateCanonicalId, generateInfrastructureFields, getAcceptedMimeTypes, getApproveAction, getFormMeta, getFormsGroupedByModule, getTaskTypeOptions, handleAppErrorResponse, isTabVisible, isTabWritable, resolveAccess, resolveAppError, resolveEffectiveAccess, resolveError, resolveMenuVisibility, verifyAndExtractSession, withAgriLogging };
|
|
576
|
+
export { ACCESS_RANK, ACT, AccessLevel, type AccessLevelType, type AgriCoreSession, AgriLogger, AppError, ApprovalStatus, ApprovalType, AuditStatus, AuditType, type AuthScopeFields, type AvailableScope, CAT, type CompanyConfig, Converter, CropCycleStatus, DocumentType, ERROR_DICTIONARY, EVERYONE, EmitterType, EnabledModule, ErrorFactory, FORM_REGISTRY, FacilityType, type FormMeta, HarvestMethod, type InfrastructureFields, LinkedStatus, MOD, MODULE_LABELS, MicroclimateZone, MimeType, type ModCode, NettingType, NotificationMode, OrderStatus, type PermissionLevel, PhysicalState, PlantingMethod, RESOURCE_MODULE_MAP, RESOURCE_PATHS, RESOURCE_REQUIREMENTS, ROLE_SECTIONS_BY_KEY, RelationshipType, type ResolvedError, type ResourceOverrides, type ResourceRequirement, RowOrientation, SENTINEL_UUID, type ScopeType, SoilTexture, TASK_TYPE_REGISTRY, type TabConfig, TargetEntityType, TaskStatus, TaskType, type TaskTypeConfig, TransactionType, TrellisType, UserPrivilege, UserRole, type UserRoleType, Validator, VigorRating, WaterSource, assertCanWrite, assertTenantBoundary, buildRlsFilter, calculateFileMetadataMatch, canRead, canWrite, evaluateBaseAccess, extractAppCode, findSpecificOverride, generateCanonicalId, generateDocumentPath, generateInfrastructureFields, getAcceptedMimeTypes, getApproveAction, getFormMeta, getFormsGroupedByModule, getTaskTypeOptions, handleAppErrorResponse, isTabVisible, isTabWritable, resolveAccess, resolveAppError, resolveEffectiveAccess, resolveError, resolveMenuVisibility, verifyAndExtractSession, withAgriLogging };
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ interface ResourceOverrides {
|
|
|
23
23
|
*/
|
|
24
24
|
interface AgriCoreSession {
|
|
25
25
|
userId: string;
|
|
26
|
+
userName: string;
|
|
27
|
+
userEmail: string;
|
|
26
28
|
companyId: string;
|
|
27
29
|
activeScopeId: string | null;
|
|
28
30
|
companyConfig: CompanyConfig;
|
|
@@ -518,5 +520,57 @@ targets: {
|
|
|
518
520
|
expectedScopeType?: 'company' | 'legalEntity' | 'facility';
|
|
519
521
|
}): Promise<boolean>;
|
|
520
522
|
declare function verifyAndExtractSession(token: string, secret: string): Promise<AgriCoreSession>;
|
|
523
|
+
declare enum DocumentType {
|
|
524
|
+
SPRAY_RECORD = "SPRAY_RECORD",
|
|
525
|
+
FERTIGATION_RECORD = "FERTIGATION_RECORD",
|
|
526
|
+
FERTILIZER_RECORD = "FERTILIZER_RECORD",
|
|
527
|
+
QA = "QA",
|
|
528
|
+
CLEANING = "CLEANING",
|
|
529
|
+
PEST = "PEST",
|
|
530
|
+
EQUIPMENT_CALIBRATION_RECORD = "EQUIPMENT_CALIBRATION_RECORD",
|
|
531
|
+
INVENTORY_CONSUMABLES = "INVENTORY_CONSUMABLES",
|
|
532
|
+
INVENTORY_BOX_CARTON = "INVENTORY_BOX_CARTON",
|
|
533
|
+
INVENTORY_CHEMICALS = "INVENTORY_CHEMICALS",
|
|
534
|
+
STOCKTAKE = "STOCKTAKE",
|
|
535
|
+
STOCKTAKE_MSDS = "STOCKTAKE_MSDS",
|
|
536
|
+
MAPPING_FARM_MAPS = "MAPPING_FARM_MAPS",
|
|
537
|
+
MAPPING_TRAFIC_MANAGEMENT = "MAPPING_TRAFIC_MANAGEMENT",
|
|
538
|
+
MAPPING_EMERGENCY = "MAPPING_EMERGENCY",
|
|
539
|
+
INCIDENT_REPORT = "INCIDENT_REPORT",
|
|
540
|
+
TRAINING_RECORDS = "TRAINING_RECORDS",
|
|
541
|
+
SOPS = "SOPS",
|
|
542
|
+
RISK_ASSESSMENTS = "RISK_ASSESSMENTS",
|
|
543
|
+
SERVICING_MAINTENANCE = "SERVICING_MAINTENANCE",
|
|
544
|
+
SOIL_TEST = "SOIL_TEST",
|
|
545
|
+
LEAF_TEST = "LEAF_TEST",
|
|
546
|
+
WATER_TEST = "WATER_TEST",
|
|
547
|
+
MRL_TESTING = "MRL_TESTING",
|
|
548
|
+
HEAVY_METAL = "HEAVY_METAL",
|
|
549
|
+
MICROBIAL = "MICROBIAL",
|
|
550
|
+
HARVEST_LOG = "HARVEST_LOG",
|
|
551
|
+
PACKHOUSE_INSPECTION = "PACKHOUSE_INSPECTION",
|
|
552
|
+
TRAINING_CERTIFICATE = "TRAINING_CERTIFICATE",
|
|
553
|
+
INVOICE = "INVOICE",
|
|
554
|
+
LEGAL_CONTRACT = "LEGAL_CONTRACT",
|
|
555
|
+
AUDIT_REPORT = "AUDIT_REPORT",
|
|
556
|
+
SENSITIVE_IDENTITY = "SENSITIVE_IDENTITY"
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Generates a full folder path matching strict business requirements.
|
|
560
|
+
* Static: {SiteName}/_CORE/{DocumentType}
|
|
561
|
+
* Dynamic: {SiteName}/_SEASONAL/{Year}/{DocumentType}/{Crop}
|
|
562
|
+
*/
|
|
563
|
+
declare function generateDocumentPath(params: {
|
|
564
|
+
siteName: string;
|
|
565
|
+
docType: DocumentType;
|
|
566
|
+
isStatic?: boolean;
|
|
567
|
+
year?: number | string;
|
|
568
|
+
crop?: string;
|
|
569
|
+
}): string;
|
|
570
|
+
declare function calculateFileMetadataMatch(criteria: {
|
|
571
|
+
mustMatch: Record<string, any>;
|
|
572
|
+
mustMatchContext?: string[];
|
|
573
|
+
contextMatch?: string[];
|
|
574
|
+
}, fileMetadata: Record<string, any>, auditContext: Record<string, any>): number;
|
|
521
575
|
|
|
522
|
-
export { ACCESS_RANK, ACT, AccessLevel, type AccessLevelType, type AgriCoreSession, AgriLogger, AppError, ApprovalStatus, ApprovalType, AuditStatus, AuditType, type AuthScopeFields, type AvailableScope, CAT, type CompanyConfig, Converter, CropCycleStatus, ERROR_DICTIONARY, EVERYONE, EmitterType, EnabledModule, ErrorFactory, FORM_REGISTRY, FacilityType, type FormMeta, HarvestMethod, type InfrastructureFields, LinkedStatus, MOD, MODULE_LABELS, MicroclimateZone, MimeType, type ModCode, NettingType, NotificationMode, OrderStatus, type PermissionLevel, PhysicalState, PlantingMethod, RESOURCE_MODULE_MAP, RESOURCE_PATHS, RESOURCE_REQUIREMENTS, ROLE_SECTIONS_BY_KEY, RelationshipType, type ResolvedError, type ResourceOverrides, type ResourceRequirement, RowOrientation, SENTINEL_UUID, type ScopeType, SoilTexture, TASK_TYPE_REGISTRY, type TabConfig, TargetEntityType, TaskStatus, TaskType, type TaskTypeConfig, TransactionType, TrellisType, UserPrivilege, UserRole, type UserRoleType, Validator, VigorRating, WaterSource, assertCanWrite, assertTenantBoundary, buildRlsFilter, canRead, canWrite, evaluateBaseAccess, extractAppCode, findSpecificOverride, generateCanonicalId, generateInfrastructureFields, getAcceptedMimeTypes, getApproveAction, getFormMeta, getFormsGroupedByModule, getTaskTypeOptions, handleAppErrorResponse, isTabVisible, isTabWritable, resolveAccess, resolveAppError, resolveEffectiveAccess, resolveError, resolveMenuVisibility, verifyAndExtractSession, withAgriLogging };
|
|
576
|
+
export { ACCESS_RANK, ACT, AccessLevel, type AccessLevelType, type AgriCoreSession, AgriLogger, AppError, ApprovalStatus, ApprovalType, AuditStatus, AuditType, type AuthScopeFields, type AvailableScope, CAT, type CompanyConfig, Converter, CropCycleStatus, DocumentType, ERROR_DICTIONARY, EVERYONE, EmitterType, EnabledModule, ErrorFactory, FORM_REGISTRY, FacilityType, type FormMeta, HarvestMethod, type InfrastructureFields, LinkedStatus, MOD, MODULE_LABELS, MicroclimateZone, MimeType, type ModCode, NettingType, NotificationMode, OrderStatus, type PermissionLevel, PhysicalState, PlantingMethod, RESOURCE_MODULE_MAP, RESOURCE_PATHS, RESOURCE_REQUIREMENTS, ROLE_SECTIONS_BY_KEY, RelationshipType, type ResolvedError, type ResourceOverrides, type ResourceRequirement, RowOrientation, SENTINEL_UUID, type ScopeType, SoilTexture, TASK_TYPE_REGISTRY, type TabConfig, TargetEntityType, TaskStatus, TaskType, type TaskTypeConfig, TransactionType, TrellisType, UserPrivilege, UserRole, type UserRoleType, Validator, VigorRating, WaterSource, assertCanWrite, assertTenantBoundary, buildRlsFilter, calculateFileMetadataMatch, canRead, canWrite, evaluateBaseAccess, extractAppCode, findSpecificOverride, generateCanonicalId, generateDocumentPath, generateInfrastructureFields, getAcceptedMimeTypes, getApproveAction, getFormMeta, getFormsGroupedByModule, getTaskTypeOptions, handleAppErrorResponse, isTabVisible, isTabWritable, resolveAccess, resolveAppError, resolveEffectiveAccess, resolveError, resolveMenuVisibility, verifyAndExtractSession, withAgriLogging };
|
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
|
+
DocumentType: () => DocumentType,
|
|
35
36
|
ERROR_DICTIONARY: () => ERROR_DICTIONARY,
|
|
36
37
|
EVERYONE: () => EVERYONE,
|
|
37
38
|
EmitterType: () => EmitterType,
|
|
@@ -72,12 +73,14 @@ __export(index_exports, {
|
|
|
72
73
|
assertCanWrite: () => assertCanWrite,
|
|
73
74
|
assertTenantBoundary: () => assertTenantBoundary,
|
|
74
75
|
buildRlsFilter: () => buildRlsFilter,
|
|
76
|
+
calculateFileMetadataMatch: () => calculateFileMetadataMatch,
|
|
75
77
|
canRead: () => canRead,
|
|
76
78
|
canWrite: () => canWrite,
|
|
77
79
|
evaluateBaseAccess: () => evaluateBaseAccess,
|
|
78
80
|
extractAppCode: () => extractAppCode,
|
|
79
81
|
findSpecificOverride: () => findSpecificOverride,
|
|
80
82
|
generateCanonicalId: () => generateCanonicalId,
|
|
83
|
+
generateDocumentPath: () => generateDocumentPath,
|
|
81
84
|
generateInfrastructureFields: () => generateInfrastructureFields,
|
|
82
85
|
getAcceptedMimeTypes: () => getAcceptedMimeTypes,
|
|
83
86
|
getApproveAction: () => getApproveAction,
|
|
@@ -1058,6 +1061,79 @@ async function verifyAndExtractSession(token, secret) {
|
|
|
1058
1061
|
throw ErrorFactory.unauthorized(MOD.SESSION, "UNAUTHORIZED: No secure session token provided.");
|
|
1059
1062
|
}
|
|
1060
1063
|
}
|
|
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 || {});
|
|
1100
|
+
function generateDocumentPath(params) {
|
|
1101
|
+
const sanitizedName = params.siteName.replace(/[^a-z0-9]/gi, "_");
|
|
1102
|
+
if (params.isStatic) {
|
|
1103
|
+
return `${sanitizedName}/_CORE/${params.docType}`;
|
|
1104
|
+
} else {
|
|
1105
|
+
const folderYear = params.year || (/* @__PURE__ */ new Date()).getUTCFullYear();
|
|
1106
|
+
const folderCrop = params.crop ? `/${params.crop.toUpperCase()}` : "";
|
|
1107
|
+
return `${sanitizedName}/_SEASONAL/${folderYear}/${params.docType}${folderCrop}`;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function isValueMatch(fileValue, expectedValue) {
|
|
1111
|
+
if (Array.isArray(expectedValue)) return expectedValue.includes(fileValue);
|
|
1112
|
+
return fileValue === expectedValue;
|
|
1113
|
+
}
|
|
1114
|
+
function calculateFileMetadataMatch(criteria, fileMetadata, auditContext) {
|
|
1115
|
+
for (const [key, expectedValue] of Object.entries(criteria.mustMatch)) {
|
|
1116
|
+
if (!isValueMatch(fileMetadata[key], expectedValue)) return 0;
|
|
1117
|
+
}
|
|
1118
|
+
if (criteria.mustMatchContext) {
|
|
1119
|
+
for (const field of criteria.mustMatchContext) {
|
|
1120
|
+
const contextValue = auditContext[field];
|
|
1121
|
+
if (contextValue === void 0) continue;
|
|
1122
|
+
if (!isValueMatch(fileMetadata[field], contextValue)) return 0;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
if (fileMetadata.isStatic === true) return 100;
|
|
1126
|
+
if (!criteria.contextMatch || criteria.contextMatch.length === 0) return 100;
|
|
1127
|
+
let matches = 0;
|
|
1128
|
+
let validChecks = 0;
|
|
1129
|
+
criteria.contextMatch.forEach((field) => {
|
|
1130
|
+
const contextValue = auditContext[field];
|
|
1131
|
+
if (contextValue === void 0) return;
|
|
1132
|
+
validChecks++;
|
|
1133
|
+
if (isValueMatch(fileMetadata[field], contextValue)) matches++;
|
|
1134
|
+
});
|
|
1135
|
+
return validChecks > 0 ? Math.round(matches / validChecks * 100) : 100;
|
|
1136
|
+
}
|
|
1061
1137
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1062
1138
|
0 && (module.exports = {
|
|
1063
1139
|
ACCESS_RANK,
|
|
@@ -1072,6 +1148,7 @@ async function verifyAndExtractSession(token, secret) {
|
|
|
1072
1148
|
CAT,
|
|
1073
1149
|
Converter,
|
|
1074
1150
|
CropCycleStatus,
|
|
1151
|
+
DocumentType,
|
|
1075
1152
|
ERROR_DICTIONARY,
|
|
1076
1153
|
EVERYONE,
|
|
1077
1154
|
EmitterType,
|
|
@@ -1112,12 +1189,14 @@ async function verifyAndExtractSession(token, secret) {
|
|
|
1112
1189
|
assertCanWrite,
|
|
1113
1190
|
assertTenantBoundary,
|
|
1114
1191
|
buildRlsFilter,
|
|
1192
|
+
calculateFileMetadataMatch,
|
|
1115
1193
|
canRead,
|
|
1116
1194
|
canWrite,
|
|
1117
1195
|
evaluateBaseAccess,
|
|
1118
1196
|
extractAppCode,
|
|
1119
1197
|
findSpecificOverride,
|
|
1120
1198
|
generateCanonicalId,
|
|
1199
|
+
generateDocumentPath,
|
|
1121
1200
|
generateInfrastructureFields,
|
|
1122
1201
|
getAcceptedMimeTypes,
|
|
1123
1202
|
getApproveAction,
|
package/dist/index.mjs
CHANGED
|
@@ -961,6 +961,79 @@ async function verifyAndExtractSession(token, secret) {
|
|
|
961
961
|
throw ErrorFactory.unauthorized(MOD.SESSION, "UNAUTHORIZED: No secure session token provided.");
|
|
962
962
|
}
|
|
963
963
|
}
|
|
964
|
+
var DocumentType = /* @__PURE__ */ ((DocumentType2) => {
|
|
965
|
+
DocumentType2["SPRAY_RECORD"] = "SPRAY_RECORD";
|
|
966
|
+
DocumentType2["FERTIGATION_RECORD"] = "FERTIGATION_RECORD";
|
|
967
|
+
DocumentType2["FERTILIZER_RECORD"] = "FERTILIZER_RECORD";
|
|
968
|
+
DocumentType2["QA"] = "QA";
|
|
969
|
+
DocumentType2["CLEANING"] = "CLEANING";
|
|
970
|
+
DocumentType2["PEST"] = "PEST";
|
|
971
|
+
DocumentType2["EQUIPMENT_CALIBRATION_RECORD"] = "EQUIPMENT_CALIBRATION_RECORD";
|
|
972
|
+
DocumentType2["INVENTORY_CONSUMABLES"] = "INVENTORY_CONSUMABLES";
|
|
973
|
+
DocumentType2["INVENTORY_BOX_CARTON"] = "INVENTORY_BOX_CARTON";
|
|
974
|
+
DocumentType2["INVENTORY_CHEMICALS"] = "INVENTORY_CHEMICALS";
|
|
975
|
+
DocumentType2["STOCKTAKE"] = "STOCKTAKE";
|
|
976
|
+
DocumentType2["STOCKTAKE_MSDS"] = "STOCKTAKE_MSDS";
|
|
977
|
+
DocumentType2["MAPPING_FARM_MAPS"] = "MAPPING_FARM_MAPS";
|
|
978
|
+
DocumentType2["MAPPING_TRAFIC_MANAGEMENT"] = "MAPPING_TRAFIC_MANAGEMENT";
|
|
979
|
+
DocumentType2["MAPPING_EMERGENCY"] = "MAPPING_EMERGENCY";
|
|
980
|
+
DocumentType2["INCIDENT_REPORT"] = "INCIDENT_REPORT";
|
|
981
|
+
DocumentType2["TRAINING_RECORDS"] = "TRAINING_RECORDS";
|
|
982
|
+
DocumentType2["SOPS"] = "SOPS";
|
|
983
|
+
DocumentType2["RISK_ASSESSMENTS"] = "RISK_ASSESSMENTS";
|
|
984
|
+
DocumentType2["SERVICING_MAINTENANCE"] = "SERVICING_MAINTENANCE";
|
|
985
|
+
DocumentType2["SOIL_TEST"] = "SOIL_TEST";
|
|
986
|
+
DocumentType2["LEAF_TEST"] = "LEAF_TEST";
|
|
987
|
+
DocumentType2["WATER_TEST"] = "WATER_TEST";
|
|
988
|
+
DocumentType2["MRL_TESTING"] = "MRL_TESTING";
|
|
989
|
+
DocumentType2["HEAVY_METAL"] = "HEAVY_METAL";
|
|
990
|
+
DocumentType2["MICROBIAL"] = "MICROBIAL";
|
|
991
|
+
DocumentType2["HARVEST_LOG"] = "HARVEST_LOG";
|
|
992
|
+
DocumentType2["PACKHOUSE_INSPECTION"] = "PACKHOUSE_INSPECTION";
|
|
993
|
+
DocumentType2["TRAINING_CERTIFICATE"] = "TRAINING_CERTIFICATE";
|
|
994
|
+
DocumentType2["INVOICE"] = "INVOICE";
|
|
995
|
+
DocumentType2["LEGAL_CONTRACT"] = "LEGAL_CONTRACT";
|
|
996
|
+
DocumentType2["AUDIT_REPORT"] = "AUDIT_REPORT";
|
|
997
|
+
DocumentType2["SENSITIVE_IDENTITY"] = "SENSITIVE_IDENTITY";
|
|
998
|
+
return DocumentType2;
|
|
999
|
+
})(DocumentType || {});
|
|
1000
|
+
function generateDocumentPath(params) {
|
|
1001
|
+
const sanitizedName = params.siteName.replace(/[^a-z0-9]/gi, "_");
|
|
1002
|
+
if (params.isStatic) {
|
|
1003
|
+
return `${sanitizedName}/_CORE/${params.docType}`;
|
|
1004
|
+
} else {
|
|
1005
|
+
const folderYear = params.year || (/* @__PURE__ */ new Date()).getUTCFullYear();
|
|
1006
|
+
const folderCrop = params.crop ? `/${params.crop.toUpperCase()}` : "";
|
|
1007
|
+
return `${sanitizedName}/_SEASONAL/${folderYear}/${params.docType}${folderCrop}`;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
function isValueMatch(fileValue, expectedValue) {
|
|
1011
|
+
if (Array.isArray(expectedValue)) return expectedValue.includes(fileValue);
|
|
1012
|
+
return fileValue === expectedValue;
|
|
1013
|
+
}
|
|
1014
|
+
function calculateFileMetadataMatch(criteria, fileMetadata, auditContext) {
|
|
1015
|
+
for (const [key, expectedValue] of Object.entries(criteria.mustMatch)) {
|
|
1016
|
+
if (!isValueMatch(fileMetadata[key], expectedValue)) return 0;
|
|
1017
|
+
}
|
|
1018
|
+
if (criteria.mustMatchContext) {
|
|
1019
|
+
for (const field of criteria.mustMatchContext) {
|
|
1020
|
+
const contextValue = auditContext[field];
|
|
1021
|
+
if (contextValue === void 0) continue;
|
|
1022
|
+
if (!isValueMatch(fileMetadata[field], contextValue)) return 0;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
if (fileMetadata.isStatic === true) return 100;
|
|
1026
|
+
if (!criteria.contextMatch || criteria.contextMatch.length === 0) return 100;
|
|
1027
|
+
let matches = 0;
|
|
1028
|
+
let validChecks = 0;
|
|
1029
|
+
criteria.contextMatch.forEach((field) => {
|
|
1030
|
+
const contextValue = auditContext[field];
|
|
1031
|
+
if (contextValue === void 0) return;
|
|
1032
|
+
validChecks++;
|
|
1033
|
+
if (isValueMatch(fileMetadata[field], contextValue)) matches++;
|
|
1034
|
+
});
|
|
1035
|
+
return validChecks > 0 ? Math.round(matches / validChecks * 100) : 100;
|
|
1036
|
+
}
|
|
964
1037
|
export {
|
|
965
1038
|
ACCESS_RANK,
|
|
966
1039
|
ACT,
|
|
@@ -974,6 +1047,7 @@ export {
|
|
|
974
1047
|
CAT,
|
|
975
1048
|
Converter,
|
|
976
1049
|
CropCycleStatus,
|
|
1050
|
+
DocumentType,
|
|
977
1051
|
ERROR_DICTIONARY,
|
|
978
1052
|
EVERYONE,
|
|
979
1053
|
EmitterType,
|
|
@@ -1014,12 +1088,14 @@ export {
|
|
|
1014
1088
|
assertCanWrite,
|
|
1015
1089
|
assertTenantBoundary,
|
|
1016
1090
|
buildRlsFilter,
|
|
1091
|
+
calculateFileMetadataMatch,
|
|
1017
1092
|
canRead,
|
|
1018
1093
|
canWrite,
|
|
1019
1094
|
evaluateBaseAccess,
|
|
1020
1095
|
extractAppCode,
|
|
1021
1096
|
findSpecificOverride,
|
|
1022
1097
|
generateCanonicalId,
|
|
1098
|
+
generateDocumentPath,
|
|
1023
1099
|
generateInfrastructureFields,
|
|
1024
1100
|
getAcceptedMimeTypes,
|
|
1025
1101
|
getApproveAction,
|
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@litusarchieve18/agricore-utils",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Canonical Backend Utility Library for AgriCore",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.mjs",
|
|
12
|
-
"require": "./dist/index.js",
|
|
13
|
-
"default": "./dist/index.mjs"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"dist"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
21
|
-
"prepublishOnly": "npm run build"
|
|
22
|
-
},
|
|
23
|
-
"keywords": [
|
|
24
|
-
"agricore",
|
|
25
|
-
"utils",
|
|
26
|
-
"backend"
|
|
27
|
-
],
|
|
28
|
-
"author": "Vincent",
|
|
29
|
-
"license": "ISC",
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"tsup": "^8.0.0",
|
|
32
|
-
"typescript": "^5.0.0"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"jose": "^6.2.2"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@litusarchieve18/agricore-utils",
|
|
3
|
+
"version": "1.0.12",
|
|
4
|
+
"description": "Canonical Backend Utility Library for AgriCore",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"agricore",
|
|
25
|
+
"utils",
|
|
26
|
+
"backend"
|
|
27
|
+
],
|
|
28
|
+
"author": "Vincent",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"tsup": "^8.0.0",
|
|
32
|
+
"typescript": "^5.0.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"jose": "^6.2.2"
|
|
36
|
+
}
|
|
37
|
+
}
|