New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@docyrus/app-utils

Package Overview
Dependencies
Maintainers
4
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@docyrus/app-utils

Utility functions for frontend applications using Docyrus as backend

latest
Source
npmnpm
Version
0.4.0
Version published
Maintainers
4
Created
Source

@docyrus/app-utils

Framework-agnostic utility functions for frontend applications using Docyrus as backend. Provides date/number formatting, template compilation (Handlebars + JSONata), and a comprehensive set of expression helpers — all configured from tenant preferences.

Features

  • Tenant Preferences: Fetch tenant configuration from the Docyrus API
  • Date Formatting: PHP-style date formatting with timezone support (Y-m-d, H:i:s, etc.)
  • Number Formatting: Locale-aware number formatting with custom separators and precision
  • Number to Words: Convert numbers to words in Turkish and English with currency labels
  • Duration Formatting: Format seconds as HH:MM, decimal hours, or human-readable words
  • App Config: Get, upsert, and delete a per-app JSON configuration (1:1 per app)
  • Data Views: CRUD for saved data source view configurations (columns, filters, sort, color rules)
  • Template Engine: Handlebars compilation with async support and inline JSONata formulas
  • Formula Evaluation: JSONata expression evaluation with 70+ built-in helper functions
  • JSONata Helpers: Date arithmetic (date-fns), string manipulation, number formatting, equality checks, and more
  • TypeScript: Full type definitions included
  • Framework-Agnostic: No Vue, React, or Angular dependency — works everywhere

Installation

npm install @docyrus/app-utils
pnpm add @docyrus/app-utils

Peer Dependencies

PackageVersionRequired
@docyrus/api-client>= 0.1.0Yes (for getTenantPreferences)
handlebars>= 4.7.0Yes (for template engine)
jsonata>= 2.0.0Yes (for formula evaluation)
date-fns>= 3.0.0Yes (for JSONata date helpers)

Quick Start

import {
  getTenantPreferences,
  createDateUtils,
  createNumberUtils,
  createTemplateEngine
} from '@docyrus/app-utils';

// 1. Fetch tenant preferences
const preferences = await getTenantPreferences(apiClient);

// 2. Create utility instances
const dateUtils = createDateUtils({
  preferences,
  userTimezone: currentUser.timeZone?.id // e.g. 'Europe/Istanbul'
});

const numberUtils = createNumberUtils({ preferences });

// 3. Create template engine (optional)
const engine = createTemplateEngine({
  dateUtils,
  numberUtils,
  user: currentUser,
  extraJsonataBindings: { hasRole }
});

// 4. Use utilities
dateUtils.formatDate('2024-01-15');           // '15.01.2024' (tenant format)
numberUtils.formatNumber(1234.5);             // '1.234,50'   (tenant locale)
await engine.compileFormula('$sum(items.price)', data);

App Config & Data Views

createAppConfigClient(client, appId)

Manages the single JSON configuration object for an app (1:1 relationship — no config IDs).

import { createAppConfigClient } from '@docyrus/app-utils';

const config = createAppConfigClient(apiClient, appId);

config.get()

Returns the app's configuration. Throws 404 if none exists.

const appConfig = await config.get();
// { id: '...', data: { theme: 'dark', ... }, status: 1, tenant_app_id: '...', ... }

config.upsert(body)

Creates the config if it doesn't exist, or updates it if it does.

const updated = await config.upsert({
  data: { theme: 'dark', sidebar: { collapsed: false } },
  status: 1
});

config.remove()

Hard deletes the config (irreversible).

await config.remove();

createDataViewClient(client, appId)

Manages saved view configurations for data source tables (1:many). Views define columns, filters, sorting, color rules, and quick-filter shortcuts.

import { createDataViewClient } from '@docyrus/app-utils';

const dataViews = createDataViewClient(apiClient, appId);

dataViews.list(params?)

Returns all non-archived views. Optionally filter by data source.

const views = await dataViews.list();
const filtered = await dataViews.list({ dataSourceId: 'ds-uuid' });

dataViews.get(viewId)

Returns a single non-archived view by ID.

const view = await dataViews.get('view-uuid');

dataViews.create(body)

Creates a new data view. name and tenant_data_source_id are required.

const view = await dataViews.create({
  name: 'High Priority',
  tenant_data_source_id: 'ds-uuid',
  columns: { visible: ['title', 'priority', 'assignee'] },
  filters: { priority: 'high' },
  sort: { field: 'due_date', direction: 'asc' },
  color: '#E74C3C',
  icon: 'alert-triangle',
  is_default: false,
  sort_order: 2
});

dataViews.update(viewId, body)

Partially updates a view. Use archived: true to soft-delete.

await dataViews.update('view-uuid', { name: 'Renamed View' });
await dataViews.update('view-uuid', { archived: true }); // soft-delete

dataViews.remove(viewId)

Hard deletes a view (irreversible).

await dataViews.remove('view-uuid');

API Reference

getTenantPreferences(client)

Fetches tenant preferences from the Docyrus API.

import { getTenantPreferences } from '@docyrus/app-utils';

const preferences = await getTenantPreferences(apiClient);
// { date_format: 'd.m.Y', decimal_separator: ',', thousand_separator: '.', ... }

Parameters:

  • client — A configured RestApiClient from @docyrus/api-client

Returns: Promise<TenantPreferences>

createDateUtils(config)

Creates date formatting utilities configured from tenant preferences.

import { createDateUtils } from '@docyrus/app-utils';

const dateUtils = createDateUtils({
  preferences,
  userTimezone: 'Europe/Istanbul' // defaults to 'UTC'
});

dateUtils.formatDate(date, options?)

Formats a date using the tenant's date_format (default Y-m-d).

dateUtils.formatDate('2024-06-15');                         // uses tenant format
dateUtils.formatDate(new Date(), { format: 'd/m/Y' });     // custom format
dateUtils.formatDate('2024-06-15', { timezone: 'US/Eastern' }); // custom timezone

dateUtils.formatDateTime(date, options?)

Formats a datetime using the tenant's date_time_format (default Y-m-d H:i:s). Handles timezone-aware parsing — appends Z to strings without a timezone suffix.

dateUtils.formatDateTime('2024-06-15T14:30:00');     // parses as UTC
dateUtils.formatDateTime('2024-06-15T14:30:00+03:00'); // respects offset

dateUtils.formatDateLong(date, options?)

Formats a date using the tenant's long_date_format (default Y-m-d H:i:s).

dateUtils.toUserTimezone(date)

Converts a date to the user's timezone without formatting.

const localDate = dateUtils.toUserTimezone('2024-06-15T12:00:00Z');

Format strings use PHP date format syntax (via php-date-formatter):

TokenOutputExample
Y4-digit year2024
mMonth (01-12)06
dDay (01-31)15
HHours 24h (00-23)14
iMinutes (00-59)30
sSeconds (00-59)00
DShort day nameSat
lFull day nameSaturday
FFull month nameJune

createNumberUtils(config)

Creates number formatting utilities configured from tenant preferences.

import { createNumberUtils } from '@docyrus/app-utils';

const numberUtils = createNumberUtils({ preferences });

numberUtils.formatNumber(value, options?)

Formats a number using the tenant's locale, separators, and precision.

numberUtils.formatNumber(1234567.89);
// With tenant settings: thousand_separator='.', decimal_separator=',', decimal_precision=2
// → '1.234.567,89'

// Override per call:
numberUtils.formatNumber(1234.5, {
  decimalPrecision: 3,
  decimalSeparator: '.',
  thousandSeparator: ','
});
// → '1,234.500'

Formatting logic:

  • If both thousandSeparator and decimalSeparator are set → manual formatting with regex
  • Otherwise → toLocaleString() with the tenant's locale
  • Pass thousandSeparator: '' to disable grouping

formatNumberToWords(value, options?)

Converts a number to words with currency labels. Standalone function (no config needed).

import { formatNumberToWords } from '@docyrus/app-utils';

formatNumberToWords(1234.56);
// → 'BİNİKİYÜZOTUZDÖRT TÜRK LİRASI ELLİALTI KURUŞ'

formatNumberToWords(1234.56, { lang: 'EN', currency: 'USD' });
// → 'ONE THOUSAND TWO HUNDRED THIRTY FOUR DOLAR FIFTY SIX CENT'

formatNumberToWords(1234.56, { lang: 'TR', currency: 'EUR', useSpaces: true });
// → 'BİN İKİ YÜZ OTUZ DÖRT EURO ELLİ ALTI CENT'

Options:

OptionTypeDefaultDescription
lang'TR' | 'EN''TR'Word language
currency'TRY' | 'EUR' | 'USD' | 'GBP' | 'JPY''TRY'Currency labels
useSpacesbooleanfalseAdd spaces between word groups

Duration Formatters

Standalone functions for formatting durations (in seconds).

import {
  formatDurationAsTime,
  formatDurationAsHours,
  formatDurationAsWords
} from '@docyrus/app-utils';

formatDurationAsTime(5461);        // → '01:31'
formatDurationAsHours(5461);       // → '1.52'
formatDurationAsHours(5461, 1);    // → '1.5'
formatDurationAsWords(5461);       // → '1 hr 31 mins'
formatDurationAsWords(45);         // → '0 mins'

createTemplateEngine(config?)

Creates a template engine combining Handlebars (with async support) and JSONata formula evaluation.

import { createTemplateEngine } from '@docyrus/app-utils';

const engine = createTemplateEngine({
  dateUtils,                         // from createDateUtils()
  numberUtils,                       // from createNumberUtils()
  user: currentUser,                 // injected as metadata.user in formulas
  extraJsonataBindings: { hasRole }  // additional JSONata bindings
});

Each createTemplateEngine call creates an isolated Handlebars instance, so multiple engines (e.g., different tenants) won't conflict.

engine.compileTpl(templateString)

Preprocesses and compiles a Handlebars template. Returns an async function.

const tpl = engine.compileTpl('Hello {{name}}, total: {{formatNumber amount}}');
const html = await tpl({ name: 'John', amount: 1234.5 });
// → 'Hello John, total: 1.234,50'

Template preprocessing:

  • {{formula $expr}} → wraps expression in quotes for the formula helper
  • {{#if $expr}} → converts to {{#if (formula '$expr')}} for JSONata evaluation
  • {{<content}} → strips HTML tags from inline content

engine.compileFormula(expression, data?)

Evaluates a JSONata expression with all helpers bound. Injects metadata.user from config.

const total = await engine.compileFormula('$sum(items.price)', { items });
const greeting = await engine.compileFormula('"Hello " & name', { name: 'World' });

engine.jsonataHelpers

Direct access to the full bindings object (all built-in helpers + extraJsonataBindings).

Handlebars Helpers

The following helpers are registered automatically when using compileTpl:

Formatting Helpers

HelperUsageDescription
formatDate{{formatDate dateField format="d/m/Y"}}Format date (uses tenant date_format by default)
formatDateTime{{formatDateTime dateField}}Format datetime (uses tenant date_time_format)
formatNumber{{formatNumber amount decimalPrecision=2}}Format number with tenant settings
formatNumberToWords{{formatNumberToWords amount lang="TR" currency="TRY"}}Number to words
formatDurationAsTime{{formatDurationAsTime seconds}}Duration as HH:MM
formatDurationAsWords{{formatDurationAsWords seconds}}Duration as X hrs Y mins
formatDurationAsHours{{formatDurationAsHours seconds decimalPrecision=1}}Duration as decimal hours

Logic & Data Helpers

HelperUsageDescription
formula{{formula "$sum(items.price)"}} or {{#formula}}$expr{{/formula}}Evaluate JSONata expression
path{{#path "$.items[0]"}}...{{/path}}JSONPath query — sets context to result
repeat{{#repeat 5}}...{{/repeat}}Repeat block N times
sum{{sum items "price"}} or {{sum 1 2 3}}Sum array field or values
json{{json data}}Pretty-print JSON

JSONata Helpers

All helpers are available inside compileFormula and {{formula}} blocks. They are also exported as jsonataHelpers for direct use.

import { jsonataHelpers } from '@docyrus/app-utils';

Date Functions (date-fns, null-safe wrapped)

All date functions accept strings or Date objects. Returns null for null/empty input.

Formatting: formatDate, formatDistance, formatDistanceStrict, formatDistanceToNow, formatDistanceToNowStrict, formatDuration, formatISO, formatRelative

Arithmetic: addYears, addMonths, addWeeks, addDays, addHours, addMinutes, addSeconds, addMilliseconds, subYears, subMonths, subWeeks, subDays, subHours, subMinutes, subSeconds, subMilliseconds

Comparison: isAfter, isBefore, isDatesEqual, isPast

Difference: differenceInYears, differenceInMonths, differenceInWeeks, differenceInDays, differenceInHours, differenceInMinutes, differenceInSeconds, differenceInBusinessDays, differenceInBusinessDaysCustom

Period boundaries: startOfDay, startOfMonth, startOfWeek, startOfToday, startOfQuarter, endOfDay, endOfMonth, endOfWeek, endOfToday, endOfQuarter

differenceInBusinessDaysCustom(startDate, endDate, options?)

Calculates business days with configurable work hours and lunch breaks.

$differenceInBusinessDaysCustom(startDate, endDate, {
  "workStartHour": 9,
  "workEndHour": 18,
  "lunchBreakHours": 1,
  "lunchStartHour": 12.5,
  "lunchEndHour": 13.5,
  "includePartialDays": true
})

Number / Format Functions

FunctionSignatureDescription
formatDecimal(number, precision?, decSep?, thousandSep?)Format decimal with separators
formatMoney(number, precision?, decSep?, thousandSep?, currency?, position?)Format as currency
percentage(value, total, decimals)Calculate percentage
truncate(text, limit)Truncate with ...
join(array, separator)Join array to string
formatDurationInSeconds(seconds)Human-readable duration via date-fns

String Functions

FunctionSignatureDescription
sha256(message)SHA-256 hash (async)
ascii(str)Strip accents and non-ASCII characters
slug(str, separator?)URL-friendly slug
extractNameFromEmail(email, fallback?)Extract name from email (e.g. john.doe@...John Doe)
filterEmpty(array)Remove null/undefined/empty from array
padLeft(value, length, char?)Left-pad string
padRight(value, length, char?)Right-pad string
ifNull(value, alternative)Null coalescing
objectToString(object)Convert object to key:value string
startsWith(haystack, needle)String starts with
endsWith(haystack, needle)String ends with
includes(haystack, needle)String includes (null-safe)

Equality / DB Helpers

FunctionSignatureDescription
isEqual(a, b)Deep equality — compares by id, Date, JSON, or strict
isEqualOrContained(needle, haystack)Check if value is equal to or contained in array
isNotEqualOrContained(needle, haystack)Negation of isEqualOrContained
getDbValue(value)Extract id from object or first item of array

TypeScript

All types are exported:

import type {
  TenantPreferences,
  DateUtils,
  DateUtilsConfig,
  FormatOptions,
  NumberUtils,
  NumberUtilsConfig,
  NumberFormatOptions,
  NumberToWordsOptions,
  NumberWordLang,
  CurrencyCode,
  TemplateEngine,
  TemplateEngineConfig,
  AppConfig,
  UpsertAppConfigBody,
  AppConfigClient,
  DataView,
  CreateDataViewBody,
  UpdateDataViewBody,
  ListDataViewsParams,
  DataViewClient,
  AppUtilsConfig
} from '@docyrus/app-utils';

License

MIT

FAQs

Package last updated on 30 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts