@mojro/frontend-utils
v0.3.3
Published
Shared frontend utilities for Mojro micro-frontends.
Downloads
1,163
Readme
@mojro/frontend-utils
Shared frontend utilities for Mojro micro-frontends. The package is published as a public npm library with focused subpath exports for UOM, date/time, analytics, cache, and hierarchy helpers.
Installation
npm install @mojro/frontend-utils convert-units date-fnsPeer dependencies
This package expects the following peer dependencies in the consuming app:
convert-units^3.0.0date-fns^4.0.0
Available subpaths
| Import | Purpose |
| ---------------------------------- | ---------------------------------------------------------------------------------- |
| @mojro/frontend-utils | Version constant only (MOJRO_UTILS_VERSION) |
| @mojro/frontend-utils/uom | Unit conversion, formatting, hierarchy-scoped UOM preferences |
| @mojro/frontend-utils/hierarchy | Generic hierarchy resolution (resolveUpHierarchy) |
| @mojro/frontend-utils/cache | Platform-agnostic cache (CacheService) + IndexedDB / memory / key-value adapters |
| @mojro/frontend-utils/core | Zero-dependency primitives |
| @mojro/frontend-utils/dateTime | Date, time, and timezone utilities |
| @mojro/frontend-utils/analytics | GA4 analytics service factory (taxonomy stays in the app) |
| @mojro/frontend-utils/masterdata | Placeholder — reference-data fetch/cache (coming later) |
| @mojro/frontend-utils/map | Placeholder — geofence/location utilities |
React Native (Driver app)
Web consumers are unchanged: createHierarchyUomService still defaults to IndexedDB via createUomIndexDbCache when no cache is passed.
React Native has no IndexedDB — pass an MMKV-backed cache explicitly:
import { MMKV } from 'react-native-mmkv';
import {
createUomCache,
createHierarchyUomService,
createUomRuntime,
createGetFormattedUnit,
} from '@mojro/frontend-utils/uom';
const mmkv = new MMKV({ id: 'mojro-uom-cache' });
const hierarchyService = createHierarchyUomService({
fetchHierarchyUom: (hierarchyId) => api.getHierarchyUom(hierarchyId),
// Required for RN persistence — web apps can omit this and keep IndexedDB default
cache: createUomCache({
storage: {
getItem: (key) => mmkv.getString(key) ?? null,
setItem: (key, value) => mmkv.set(key, value),
removeItem: (key) => mmkv.delete(key),
getAllKeys: () => mmkv.getAllKeys(),
},
}),
});| Environment | Default when cache omitted |
| ------------- | -------------------------------------- |
| Browser (web) | IndexedDB — no code changes needed |
| React Native | Pass createUomCache({ storage }) |
See docs/react-native.md for a full integration guide.
Quick usage
import { createUomRuntime, createGetFormattedUnit, UOM_ENTITY } from '@mojro/frontend-utils/uom';
const runtime = createUomRuntime({
entityIds: {
sku: 1,
vehicleCategory: 2,
},
getSelectedHierarchyId: () => activeHierarchyId,
getLocale: () => 'en-IN',
});
const getFormattedUnit = createGetFormattedUnit({
runtime,
getCachedHierarchyUom: (hierarchyId) => cachedHierarchyUnits.get(hierarchyId),
});
getFormattedUnit({ amount: 1000, unit: 'g' }, UOM_ENTITY.TRIP, true, true);DateTime usage
import {
createDateTimeRuntime,
createFormatDateTime,
formatTimeOnly,
} from '@mojro/frontend-utils/dateTime';
const runtime = createDateTimeRuntime({
getLocale: () => 'en-IN',
});
const formatDateTime = createFormatDateTime({ runtime });
formatDateTime('2026-07-16T14:30:00.000+05:30', {
timeZone: 'Asia/Kolkata',
});
formatTimeOnly({
dateTime: '2026-07-16T14:30:00.000+05:30',
timeZone: 'Asia/Kolkata',
options: { format: 'HH:mm' },
});Analytics usage
import { createAnalyticsService } from '@mojro/frontend-utils/analytics';
// Event taxonomy (EVENTS) lives in the consuming app — pass name strings here.
const analytics = createAnalyticsService({
measurementId: 'G-XXXXXXXX',
});
analytics.initialize({
application: 'app-mojro',
environment: 'production',
});
analytics.identifyUser({
userId: '123',
properties: { role: 'admin', enterprise_id: 'ent-1' },
});
analytics.trackEvent('order_created'); // use your own taxonomy
analytics.trackPageView({
path: '/orders/details/abc',
title: 'Mojro',
pageName: 'Order Details', // stable label for aggregation across dynamic IDs
});trackPageView sends GA4 page_view with custom keys (path, title, page_url, page_name, previous_page) — not reserved page_path / page_title / page_location — so they appear in the Parameters table with common + user params.
