@gatekeeper_technology/report-utils
Version:
Gatekeeper's pdf/email Utils - shared in NPM
477 lines (320 loc) • 11.8 kB
Markdown
# Gatekeeper Report Utils
Shared PDF, email, date, attachment, and display helpers for Gatekeeper JourneyApps reports.
## Install
Add the package to a JourneyApps CloudCode task:
```json
{
"dependencies": {
"@gatekeeper_technology/report-utils": "1.3.3"
}
}
```
Create a `.npmrc` file in the CloudCode task with the read-only npm token from 1Password:
```text
//registry.npmjs.org/:_authToken=<read-only-npm-token>
```
Then import the helpers:
```js
const reportUtils = require("@gatekeeper_technology/report-utils");
```
## Common Examples
### Format Dates
```js
const {
displayDate,
displayDateTime,
displayTime,
displayTimeWithSeconds,
getOffsetDate,
getStartOfWeek,
getEndOfWeek,
getWeekNumber,
isSameDay,
compareDates,
} = require("@gatekeeper_technology/report-utils");
const date = new Date(2026, 6, 10, 8, 30, 0);
displayDate(date); // "10 Jul 2026"
displayDate(date, "long"); // "10 July 2026"
displayTime(date); // "08:30"
displayTimeWithSeconds(date); // "08:30:00"
displayDateTime(date); // "10 Jul 2026, 08:30"
getOffsetDate(date, 7); // date plus 7 days
getStartOfWeek(date); // Monday start, ISO mode by default
getEndOfWeek(date); // Sunday end, ISO mode by default
getWeekNumber(date); // calendar week number
isSameDay(date, new Date()); // true/false
compareDates(date, new Date()); // -1, 0, or 1
```
Non-Date inputs generally return `null` for date comparison helpers and `"-"` for display helpers.
### Prepare SendGrid Recipients
```js
const {
getToEmailsArray,
setCheckWhitelistEnvironments,
} = require("@gatekeeper_technology/report-utils");
const recipients = getToEmailsArray(
[" Manager@Example.com ", "auditor@example.com; area@example.com"],
["manager@example.com", "ops@example.com"],
"staging",
["manager@example.com", "area@example.com"]
);
// recipients:
// {
// to: [{ email: "manager@example.com" }, { email: "area@example.com" }],
// cc: []
// }
```
`getToEmailsArray` trims, lowercases, de-duplicates, splits comma/semicolon separated strings, removes CC addresses that are already in TO, and filters by whitelist in `staging` and `testing`.
To change which environments use the whitelist:
```js
setCheckWhitelistEnvironments(["testing", "staging", "production"]);
```
### Generate HTML And Save A PDF Attachment
```js
const {
generateHTML,
postToJourneyBackend,
} = require("@gatekeeper_technology/report-utils");
async function createReport(request, data) {
const html = generateHTML(data, __dirname, "templates/report.html");
const saved = await postToJourneyBackend(
request,
"report_pdf",
html,
`report-${request.id}.pdf`,
process.env.JOURNEY_PDF_REPORTS_TOKEN
);
if (!saved) {
throw new Error("Report PDF could not be generated or saved");
}
}
```
`generateHTML` reads and compiles a Handlebars template. `postToJourneyBackend` generates a PDF with `@journeyapps/pdf-reports`, creates a JourneyApps `Attachment`, assigns it to the requested field, and saves the object.
### Use Photos And Signatures In Reports
```js
const {
getImageContentForPDF,
isAttachmentsUploaded,
loadAttachments,
loadPhotoOrSignature,
} = require("@gatekeeper_technology/report-utils");
async function buildReportData(inspection) {
try {
isAttachmentsUploaded(inspection);
} catch (error) {
if (error.cause === "attachments-uploading") {
// Reschedule the CloudCode task using the app's normal retry pattern.
throw error;
}
throw error;
}
return loadAttachments({}, inspection);
}
async function addSignature(inspection) {
return loadPhotoOrSignature(inspection, "customer_signature");
}
async function addImage(inspection) {
return {
image_url: await getImageContentForPDF(inspection.photo, "url"),
image_base64: await getImageContentForPDF(inspection.photo, "base64"),
};
}
```
Attachment helpers throw with `cause: "attachments-uploading"` when a JourneyApps attachment has not finished uploading. Catch that error and reschedule the task from the calling app.
When `type` is `"base64"`, `getImageContentForPDF` detects the image MIME type from the base64 payload (PNG, JPEG, GIF, WebP, SVG), falling back to the attachment URL extension, then to PNG.
### Display JourneyApps Fields And Sort Data
```js
const {
formatText,
getDisplayLabel,
getDisplayValue,
sortArrayByField,
} = require("@gatekeeper_technology/report-utils");
const label = getDisplayLabel(store, "store_type");
const value = getDisplayValue(store, "store_type");
formatText(" Store Visit / Audit "); // "store_visit_audit"
formatText(" Store Visit / Audit ", "higher"); // "STORE_VISIT_AUDIT"
const stores = [
{ name: "Cape Town", score: 88 },
{ name: "Durban", score: 72 },
];
sortArrayByField(stores, "score", -1); // sorts highest score first
```
`sortArrayByField` uses JavaScript's native `Array.sort`, so it mutates the original array.
## Exported Helpers
### Date And Time
- `displayDate(date, monthLength)`
- `displayDateTime(date, monthLength)`
- `displayTime(date)`
- `displayTimeWithSeconds(date)`
- `getOffsetDate(originalDate, offsetDays)`
- `getStartOfWeek(date, iso)`
- `getEndOfWeek(date, iso)`
- `getWeekNumber(date, iso)`
- `isSameDay(date1, date2)`
- `compareDates(date1, date2)`
### Email
- `getToEmailsArray(toArray, ccArray, env, whitelist)`
- `setCheckWhitelistEnvironments(environments)`
- `storeValidEmail(emailObject, email)`
- `validateEmail(email)`
### Attachments And PDFs
- `getImageContentForPDF(image, type)`
- `loadImageBase64(path)`
- `loadAttachments(target, objectToCheck)`
- `loadPhotoOrSignature(object, fieldName)`
- `isAttachmentsUploaded(objectToCheck)`
- `isAttachmentUploaded(object, fieldName)`
- `generateHTML(data, dirName, fileName)`
- `postToJourneyBackend(object, fieldName, pdfHtml, fileName, token)`
### General
- `getDisplayValue(object, field)`
- `getDisplayLabel(object, field)`
- `formatText(text, type)`
- `sortArrayByField(objectArray, fieldName, sortDirection)`
## Development
Install with the publish npm token from 1Password:
```text
//registry.npmjs.org/:_authToken=<publish-npm-token>
```
Release checklist:
1. Make code changes in `src/*.ts` and export new helpers from `index.ts`.
2. Add or update Jest tests when behavior changes.
3. Update the version in `package.json`.
4. Add a changelog entry below.
5. Run `npm test`.
6. Publish with `npm publish`.
7. Commit and push the release.
## Changelog
### [1.3.3]
#### Fixed
- `getImageContentForPDF` now detects the correct MIME type for base64 data URIs (PNG, JPEG, GIF, WebP, SVG) instead of treating non-SVG attachments as PNG.
- Date helpers now treat Invalid Date values as invalid and return `null` / `"-"` as documented.
#### Changed
- Rewrote the README with install steps, usage examples, and an exported helpers reference.
- Replaced outdated photo attachment tests with coverage for MIME detection, upload checks, and local image loading.
- Aligned general and date tests with current behavior, and added email utility coverage.
- Added Jest + `ts-jest` so TypeScript sources can be tested directly.
### [1.3.2]
#### Changed
- Bumped `@journeyapps/db` from `^8.0.10` to `^8.1.1`.
### [1.3.1]
#### Changed
- Bumped `@gatekeeper_technology/rollbar-utils` to `^1.2.4`.
### [1.3.0]
#### Changed
- Bumped the package version to `1.3.0`.
- Bumped `@gatekeeper_technology/rollbar-utils` to `^1.2.3`.
- Bumped `@journeyapps/db` to `^8.0.10`.
- Removed the unused `@journeyapps/cloudcode` dependency.
### [1.2.3]
#### Changed
- Bumped `@gatekeeper_technology/rollbar-utils` from `1.1.1` to `^1.2.2`.
### [1.2.2]
#### Fixed
- Fixed `postToJourneyBackend` so it throws when the target field is missing, instead of throwing when the field exists.
#### Changed
- Added parameter documentation for `generateHTML`.
### [1.2.1]
#### Removed
- `dist` ignore file in `.npmignore`.
### [1.2.0]
#### Added
- Added `postToJourneyBackend` function
- Added `journeyApps` npm packages as dependencies to assist with the reportUtil package.
- Added `sortArrayByField` function
- Added `generateHTML` function
- Added `formatText` function
- Added `getImageContentForPDF` function
#### Changed
- Migrated to TypeScript
- All date functions should now be able to accept `Day` variables.
- `.gitignore` file now ignores compiled files.
- `isAttachment(s)Uploaded` functions no longer reschedules. It now throws an error with the cause = `attachments-uploading`
### [1.1.10]
#### Removed
- Removed `loadBase64` function in a race against time.
### [1.1.9]
#### Added
- Jest Test cases
- formatText, sortArrayByField and generateHTML functions
- .d.ts files.
### [1.1.8]
#### Changed
- Added more validation on general utils
#### Added
- Unit Tests on General Utils.
#### Removed
- console.error() on date Utils.
### [1.1.7]
#### Changed
- Fixed funky way of throwing errors
- Added a new utils folder with small internal utils
### [1.1.6]
#### Changed
- When retrying a task, we don't need to specify the CloudCode task name as we can access it programmatically
### [1.1.5]
#### Added
- isSameDay: Checks if the given two dates falls on the same day (second date value defaults to now).
- compareDates: Checks if the given two dates falls on the same date and time (return 0), date 1 is before date 2 (returns -1), otherwise returns 1 (second date value defaults to now).
#### Removed
- isToday: Can be used via the isSameDay() function
- isPastDate and isFutureDate: Can be user via the compareDates() function
#### Changed
- Improved Test file (WIP)
### [1.1.4]
#### Added
- areEqualDates
- areEqualDateTimes
- isToday
- getStartOfWeek
- getEndOfWeek
- getWeekNumber
- isFutureDate
- isPastDate
### [1.1.3]
#### Fixed
- A bug where you cannot import the `report-utils` package in the `/mobile` side of an App.
### [1.1.2]
#### Changed
- [TESTING] Moved the `loadImageBase64` function to `index.js` to see if the required("fs") problem is fixed.
### [1.1.1]
#### Changed
- [TESTING] Moved the require("fs") out of the function.
### [1.1.0]
#### Changed
- Refactored the file structure to separate the concerns.
- Replaced `displayPhoto` with `journeyPhotoToBase64`, it now has a more descriptive name
- Replaced `loadPhotoOrSignature` with `getPhotoOrSignatureData`, it's now up to the developer to load the data into a data hash.
- Replaced `loadSignatureBase64` with `encodeBase64ImagePNG`, renamed function and changed the input parameter to the actual image data.
### [1.00.07]
#### Added
- `index.js`: Added the ability to specify in which environments to enable email whitelisting.
### [1.00.06]
#### Changed
- `index.js`: Emails are first trimmed and toLowerCase'd before checking if it is valid.
### [1.00.05]
#### Changed
- `index.js`: Changed the way `loadAttachments` function receives retry_count value.
### [1.00.04]
#### Fixed
- `index.js`: a Bug where the `loadPhotoOrSignature` function was out of date.
### [1.00.03]
#### Changed
- `index.js`: Emails check now convert all emails to lowercase before checking for duplicates.
### [1.00.02]
#### Added
- `index.js`: Added function `displayTimeWithSeconds`.
#### Changed
- `index.js`: improved javadocs commenting .
### [1.00.01]
#### Changed
- `Readme.md`: explanation improved.
- `index.js`: Added functions `displayDateTime` and `displayTime`.
### [1.00.00]
#### Added
- `package.json`: Added.
- `index.js`: Added and populated with Gatekeeper's handlebarUtil functions.
- `.npmignore`: Added.
- `.gitignore`: Added.
- `README.md`: Added with description, set-up and change-log.