npm package: @reforgium/internal
Description: Hidden Reforgium foundation package for shared primitives, tokens, and infrastructure.
Author: rtommievich
Latest version: 2.0.4

# @reforgium/internal

[![npm version](https://badge.fury.io/js/%40reforgium%2Finternal.svg)](https://www.npmjs.com/package/@reforgium/internal)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Shared infrastructure package for Reforgium Angular libraries.

- foundation primitives belong here
- feature semantics do not
- legacy compatibility for `angular-common-kit` does not

`@reforgium/internal` is infrastructure for Reforgium packages and is not intended as a user-facing product package.

## Install

`internal` is primarily consumed transitively by other `@reforgium/*` packages.
Direct installation is possible for workspace and low-level internal use, but it is not the recommended first entrypoint for app code.

```bash
npm i @reforgium/internal
```

## Public API

`@reforgium/internal` exports:

- `models`
- `codecs`
- `storage`
- `tokens`
- `utils`

### Models

Main model groups:

- `query.models.ts`: `SortToken`, `SortDirection`, `SortRule`, `SortInput`, `QueryArrayMode`, `QueryFieldModes`, `QueryParams`, `Query`
- `transport.models.ts`: `RestMethods`, `PageableRequest`, `PageableResponse<T>`, `ErrorResponse`
- `elements.ts`: `Direction`, `ElementRect`, `ElementSize`, `ElementPosition`, `ElementEdges`
- `util.ts`: `AnyType`, `AnyDict`, `LiteralOf`, `ValueOf`, `Nullable`, `Nullish`, `NullableProps`, `OptionalExcept`, `RequiredExcept`, `Mutable`, JSON helper types

Compatibility-only model surface:

- `components.ts`: `Appearance`, `SelectOption`, `SelectIconOption`
- `api.ts`: deprecated mixed facade kept for compatibility; prefer explicit query and transport types

### Codecs

Main codec exports:

- `Serializer`
- `SerializerFieldError`
- `SerializerConfig`
- `FieldConfig`
- `SerializedType`

These are shared bidirectional transform primitives used by `statum` and `regula`.

### Storage

Main storage exports:

- `StorageInterface`
- `StorageStrategy`, `StorageStrategyOptions`
- `MemoryStorage`
- `LocalStorage`
- `SessionStorage`
- `LruCache`
- `storageStrategy(...)`

### Tokens

Language tokens:

- `SELECTED_LANG: InjectionToken<Signal<Langs>>`
- `CHANGE_LANG: InjectionToken<(lang: Langs) => void>`
- `TRANSLATION`
- `REGISTER_LANG` (multi-token)
- `BUILTIN_LANGS`
- `provideLangs(...langs: string[])`
- `Langs = BuiltInLangs | (string & {})`

Theme/device/validation tokens:

- `SELECTED_THEME`, `CHANGE_THEME`, `Themes`
- `CURRENT_DEVICE`, `Devices`
- `VALIDATION_MESSAGES`, `ValidationMessages`, `ValidationErrorData`:
  compatibility-only legacy validation token surface

Example:

```ts
import { provideLangs } from '@reforgium/internal';

export const appConfig = {
  providers: [provideLangs('de', 'fr')],
};
```

### Utilities

Exported utilities:

- `web.utils.ts`: `downloadByBlob`, `downloadByUrl`, `copyText`, `base64ToBlob`
- `timers.utils.ts`: `throttleSignal`, `debounceSignal`
- `date.utils.ts`: `toDate`, `formatDate`, `formatToLocaledDate`, `parseToDate`, `parseToDatePeriod`, `isDatePeriod`, `reformatDateToISO`
- `types.utils.ts`: `isNumber`, `isNullable`, `isObject`, `parseQueryArray`, `concatArray`
- `format.utils.ts`: `formatToSpacedNumber`, `truncate`
- `positions.utils.ts`: `getCorrectedPosition`
- `available-height.utils.ts`: `getAvailableHeight`
- `get-chained-value.utils.ts`: `getChainedValue`
- `query.utils.ts`: `buildQueryParams`, `appendQueryParamsByMode`, `parseQueryParams`, `parseQueryParamsByMode`, `mergeQueryParams`, `makeQuery`
- `sort.utils.ts`: `toSortToken`, `sortRuleToToken`, `parseSortToken`, `normalizeSortInput`, `sortInputToTokens`
- `urls.utils.ts`: `normalizeUrl`, `fillUrlWithParams`, `appendQueryParams`, `parseQueryParams`
- `routes.utils.ts`: `materializeRoutePath`, `compareRoutes`, `makeQuery`
- `deep-equal.utils.ts`: `deepEqual`
- `generate.utils.ts`: `generateId`

Recommended entrypoints:

- prefer `query.utils.ts` for new query-string work;
- prefer `sort.utils.ts` for new sort serialization/parsing work;
- keep `urls.utils.ts` and `routes.utils.ts` for narrower low-level cases.

`query.utils.ts` example:

```ts
import { buildQueryParams, mergeQueryParams, parseQueryParamsByMode } from '@reforgium/internal';

const query = buildQueryParams(
  {
    tags: ['angular', 'signals'],
    sort: ['name,asc', 'createdAt,desc'],
    page: 2,
  },
  'comma',
  { sort: 'multi' },
);
// tags=angular%2Csignals&page=2&sort=name%2Casc&sort=createdAt%2Cdesc

const next = mergeQueryParams(
  { page: 1, tags: ['angular'], tenant: 'kg' },
  { page: 2, tenant: null, sort: ['name,asc'] },
);
// { page: 2, tags: ['angular'], sort: ['name,asc'] }

const parsed = parseQueryParamsByMode(query, 'comma', { sort: 'multi' });
// { tags: ['angular', 'signals'], sort: ['name,asc', 'createdAt,desc'], page: '2' }
```

`sort.utils.ts` example:

```ts
import { parseSortToken, sortInputToTokens, toSortToken } from '@reforgium/internal';

toSortToken('name', 'asc');
// 'name,asc'

sortInputToTokens([
  { sort: 'name', order: 'asc' },
  { sort: 'createdAt', order: 'desc' },
]);
// ['name,asc', 'createdAt,desc']

parseSortToken('createdAt,desc');
// { sort: 'createdAt', order: 'desc' }
```

Low-level `makeQuery(..., 'multi')` behavior:

```ts
import { makeQuery } from '@reforgium/internal';

makeQuery({ ids: [1, 2, 3], q: 'ok' }, 'multi');
// ids=1&ids=2&ids=3&q=ok
```

`storage` example:

```ts
import { LruCache, storageStrategy } from '@reforgium/internal';

const pages = new LruCache<number, string[]>(5);
pages.set(1, ['a', 'b']);

const persisted = storageStrategy<string, { updatedAt: number }>('persist');
persisted.set('users', { updatedAt: Date.now() });
```

`codecs` example:

```ts
import { Serializer } from '@reforgium/internal';

const serializer = new Serializer<{
  search: string;
  createdAt: Date;
}>({
  mapFields: {
    createdAt: { type: 'date' },
  },
});

serializer.serialize({
  search: '  regula  ',
  createdAt: new Date('2026-04-04'),
});
// { search: 'regula', createdAt: '2026-04-04' }
```

## License

MIT