# @joktec/core

> JokTec - Core library

Latest version **0.2.17** (published 2026-07-06) · MIT license · 0 weekly downloads

## Install

```sh
npm install @joktec/core
pnpm add @joktec/core
yarn add @joktec/core
bun add @joktec/core
```

Provides the commands `publish-helm`, `publish-docker`, `client-generator`.

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads; no esm support; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.2.17 |
| Published | 2026-07-06 |
| First published | 2023-03-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Node | >=14.0.0 |
| Dependencies | 53 |
| Unpacked size | 1.2 MB |
| Known vulnerabilities | 0 (+5 in 2 direct dependencies) |
| Install scripts | no |
| Author | JokTec |
| Maintainers | joktec_dev |
| Keywords | nestjs, restful, graphql, core |

## Links

- npm: https://www.npmjs.com/package/@joktec/core
- npm.io page: https://npm.io/package/@joktec/core

## Dependencies (53)

- [ms](https://npm.io/package/ms.md) ^2.1.3
- [hbs](https://npm.io/package/hbs.md) ^4.2.1
- [glob](https://npm.io/package/glob.md) ^13.0.6
- [pino](https://npm.io/package/pino.md) ^10.3.1
- [rxjs](https://npm.io/package/rxjs.md) ^7.8.2
- [async](https://npm.io/package/async.md) ^3.2.6
- [csurf](https://npm.io/package/csurf.md) ^1.11.0
- [retry](https://npm.io/package/retry.md) ^0.13.1
- [bullmq](https://npm.io/package/bullmq.md) ^5.79.1
- [helmet](https://npm.io/package/helmet.md) ^8.2.0
- [lodash](https://npm.io/package/lodash.md) ^4.18.1
- [multer](https://npm.io/package/multer.md) ^2.2.0
- [express](https://npm.io/package/express.md) ^5.2.1
- [graphql](https://npm.io/package/graphql.md) ^16.14.2
- [js-yaml](https://npm.io/package/js-yaml.md) 5.1.0
- [opossum](https://npm.io/package/opossum.md) ^9.0.0
- [pino-http](https://npm.io/package/pino-http.md) ^11.0.0
- [useragent](https://npm.io/package/useragent.md) ^2.3.0
- [dataloader](https://npm.io/package/dataloader.md) ^2.2.3
- [geoip-lite](https://npm.io/package/geoip-lite.md) ^1.4.10
- [request-ip](https://npm.io/package/request-ip.md) ^3.3.0
- [async-retry](https://npm.io/package/async-retry.md) ^1.3.3
- [body-parser](https://npm.io/package/body-parser.md) ^2.3.0
- [nestjs-pino](https://npm.io/package/nestjs-pino.md) ^4.6.1
- [pino-pretty](https://npm.io/package/pino-pretty.md) ^13.1.3
- [pino-socket](https://npm.io/package/pino-socket.md) ^8.0.0
- [prom-client](https://npm.io/package/prom-client.md) ^15.1.3
- [@nestjs/core](https://npm.io/package/@nestjs/core.md) ^11.1.27
- [@nestjs/cqrs](https://npm.io/package/@nestjs/cqrs.md) ^11.0.3
- [jsonwebtoken](https://npm.io/package/jsonwebtoken.md) ^9.0.3
- [@joktec/utils](https://npm.io/package/@joktec/utils.md) 0.1.5
- [@bull-board/ui](https://npm.io/package/@bull-board/ui.md) ^8.0.1
- [@nestjs/bullmq](https://npm.io/package/@nestjs/bullmq.md) ^11.0.4
- [@nestjs/common](https://npm.io/package/@nestjs/common.md) ^11.1.27
- [@nestjs/config](https://npm.io/package/@nestjs/config.md) ^4.0.4
- [@bull-board/api](https://npm.io/package/@bull-board/api.md) ^8.0.1
- [@nestjs/graphql](https://npm.io/package/@nestjs/graphql.md) ^13.4.2
- [@nestjs/swagger](https://npm.io/package/@nestjs/swagger.md) ^11.4.4
- [@nestjs/testing](https://npm.io/package/@nestjs/testing.md) ^11.1.27
- [@nestjs/terminus](https://npm.io/package/@nestjs/terminus.md) ^11.1.1
- [reflect-metadata](https://npm.io/package/reflect-metadata.md) ^0.2.2
- [@nestjs/throttler](https://npm.io/package/@nestjs/throttler.md) ^6.5.0
- [express-basic-auth](https://npm.io/package/express-basic-auth.md) ^1.2.1
- [swagger-ui-express](https://npm.io/package/swagger-ui-express.md) ^5.0.1
- [@aws-sdk/client-sts](https://npm.io/package/@aws-sdk/client-sts.md) ^3.1075.0
- [@bull-board/express](https://npm.io/package/@bull-board/express.md) ^8.0.1
- [@nestjs/mapped-types](https://npm.io/package/@nestjs/mapped-types.md) ^2.1.1
- [@nestjs/serve-static](https://npm.io/package/@nestjs/serve-static.md) ^5.0.5
- [@nestjs/event-emitter](https://npm.io/package/@nestjs/event-emitter.md) ^3.1.0
- [@nestjs/microservices](https://npm.io/package/@nestjs/microservices.md) ^11.1.27
- [@nestjs/platform-express](https://npm.io/package/@nestjs/platform-express.md) ^11.1.27
- [@willsoto/nestjs-prometheus](https://npm.io/package/@willsoto/nestjs-prometheus.md) ^6.1.0
- [@aws-sdk/credential-providers](https://npm.io/package/@aws-sdk/credential-providers.md) ^3.1075.0

## Alternatives

- [apollo-link-http-common](https://npm.io/package/apollo-link-http-common.md) — 879.0K weekly downloads
- [react-relay](https://npm.io/package/react-relay.md) — 336.8K weekly downloads
- [relay-test-utils](https://npm.io/package/relay-test-utils.md) — 181.6K weekly downloads
- [@vendure/core](https://npm.io/package/@vendure/core.md) — 14.8K weekly downloads
- [@pnpm/deps.graph-sequencer](https://npm.io/package/@pnpm/deps.graph-sequencer.md) — 13.4K weekly downloads

## Recent versions

- 0.2.17 (latest) — 2026-07-06
- 0.2.16 — 2026-06-29
- 0.2.15 — 2026-06-27
- 0.2.14 — 2026-06-26
- 0.2.13 — 2026-06-26
- 0.2.12 — 2026-06-24
- 0.2.11 — 2025-10-31
- 0.2.10 — 2025-07-29
- 0.2.9 — 2025-07-03
- 0.2.8 — 2025-07-01
- 0.2.7 — 2025-06-25
- 0.2.6 — 2025-06-05
- 0.2.5 — 2025-05-26
- 0.2.4 — 2025-05-22
- 0.2.3 — 2025-05-22
- … 171 more at https://npm.io/package/@joktec/core/versions

## README

# @joktec/core

Core framework package for JokTec applications and reusable packages.

`@joktec/core` contains the shared NestJS infrastructure used by the rest of the framework: application bootstrap, gateway and microservice runtime factories, config, logging, metrics, exceptions, base CRUD abstractions, microservice client helpers, Swagger decorators, and pagination contracts.

## Install

```bash
yarn add @joktec/core
```

## Public Surface

- bootstrap:
  - `Application.bootstrap`
  - `GatewayModule`
  - `MicroModule`
- framework modules:
  - `ConfigModule`
  - `LoggerModule`
  - `MetricModule`
  - `JwtModule`
  - `BullModule`
  - `StaticModule`
- base abstractions:
- `BaseService`
- `BaseController`
- `SubController`
- `BaseResolver`
- `ClientController`
- `ClientService`
- `SubClientController`
- `SubClientService`
- `AbstractClientService`
- shared contracts:
- `IBaseRequest`
- `IBaseRepository`
- `IBaseService`
- `IBaseSubService`
- `IPaginationResponse`
  - `PaginationMode`
- pagination DTO factories:
  - `PagePaginationResponse`
  - `OffsetPaginationResponse`
  - `CursorPaginationResponse`
  - `BasePaginationResponse`
- cursor utility:
  - `CursorPagination`
- decorators, exceptions, interceptors, pipes, transport models, and selected NestJS exports.

## Bootstrap Usage

```ts
import { Application, ConfigModule, GatewayModule, LoggerModule, Module } from '@joktec/core';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    LoggerModule,
    GatewayModule.forRoot({ metric: true }),
  ],
})
export class AppModule {}

Application.bootstrap(AppModule);
```

Runtime mode is selected from config:

- `gateway` config enables HTTP gateway bootstrap.
- `micro` config enables microservice bootstrap.
- Both can exist when a process needs both HTTP and transport listeners.

## Base Controller Usage

`BaseController` creates standard REST endpoints for a DTO:

- `GET /`
- `POST /search`
- `GET /:id`
- `POST /`
- `PUT /:id`
- `DELETE /:id`

```ts
import { BaseController, Controller, IControllerProps } from '@joktec/core';
import { Article } from './article.schema';
import { ArticleService } from './article.service';

const props: IControllerProps<Article> = {
  dto: Article,
  paginate: { mode: 'offset' },
  useBearer: true,
  create: { disable: true },
};

@Controller('articles')
export class ArticleController extends BaseController<Article, string>(props) {
  constructor(protected articleService: ArticleService) {
    super(articleService);
  }
}
```

Pagination response selection belongs to `paginate.mode`. `customDto.paginationDto` has priority over `paginate.mode` when a controller needs a custom Swagger response DTO.

## Sub-Resource Controller Usage

`SubController` creates nested REST CRUD endpoints such as `/articles/:articleId/comments`. It delegates to `IBaseSubService`; the service decides whether the child data is embedded, subdocument-backed, or relation-backed.

```ts
import { Controller, ISubControllerProps, SubController } from '@joktec/core';

const props: ISubControllerProps<Article, Comment> = {
  parentDto: Article,
  dto: Comment,
  parentParam: { name: 'articleId' },
  childParam: { name: 'commentId' },
  paginate: { mode: 'offset', search: true },
  customDto: { createDto: ArticleCommentCreateDto, updatedDto: ArticleCommentUpdateDto },
};

@Controller('articles/:articleId/comments')
export class ArticleCommentController extends SubController<Article, Comment, string, string>(props) {
  constructor(protected articleCommentService: ArticleCommentService) {
    super(articleCommentService);
  }
}
```

## Microservice CRUD Usage

`ClientController` and `ClientService` provide generated private transport CRUD for top-level resources. `SubClientController` and `SubClientService` do the same for nested resources with `Parent.Child.action` command names such as `Article.Comment.create`.

Create/update message handlers accept current `{ dto }` payloads and legacy `{ entity }` payloads. Validation is applied to the selected payload object before service delegation.

## Gateway Request Interceptor

`ExpressInterceptor` is the default HTTP request/response boundary for gateway apps. It enriches each request with locale, timezone, user agent, and GeoIP metadata, then normalizes query/search payloads before controllers receive them.

Query strings are cast into practical runtime values:

- `"true"` / `"false"` become booleans.
- `"null"` becomes `null`.
- `"undefined"` is removed from normalized objects.
- numeric strings become numbers.
- JSON object/array strings are parsed.
- date strings are cast only when the operator/path is date-like, such as `condition[createdAt][$lte]`.

`GET` and `POST` search endpoints ending in `/search` also normalize request bodies, but the default body policy only casts date-like strings because JSON bodies already preserve numbers, booleans, and nulls.

```ts
class AppExpressInterceptor extends ExpressInterceptor {
  protected resolverTimezone(req: ExpressRequest): string {
    return req.headers['x-timezone']?.toString() || super.resolverTimezone(req);
  }
}
```

For advanced projects, override `resolverRequestCastOptions()` to tune query or search-body casting. Prefer overriding `resolverLanguage`, `resolverTimezone`, `resolverQuery`, `resolverSearchBody`, or `transformResponse` before replacing the full interceptor flow.

## Pagination Contract

`IBaseRequest` supports three pagination styles:

```ts
type PaginationMode = 'page' | 'offset' | 'cursor';
```

Runtime priority is:

1. cursor when `cursor` or `cursorKey` exists
2. offset when `offset` exists
3. page as the default fallback

Page response:

```ts
{
  items: T[];
  total: number;
  prevPage: number | null;
  currPage: number;
  nextPage: number | null;
  lastPage: number | null;
}
```

Offset response:

```ts
{
  items: T[];
  total: number;
  prevOffset: number | null;
  currOffset: number;
  nextOffset: number | null;
  lastOffset: number | null;
}
```

Cursor response:

```ts
{
  items: T[];
  total: number;
  hasNextPage: boolean;
  nextCursor: string | null;
}
```

`BaseController` reads `paginate.mode` to select the representative Swagger response shape. It does not force runtime clients to use only that mode.

## Cursor Pagination Utility

`CursorPagination` creates opaque base64url cursor tokens from ordered item keys. Database packages use it to resolve cursor keys, sort directions, `limit + 1` slicing, and `nextCursor` generation.

```ts
import { CursorPagination } from '@joktec/core';

const limit = CursorPagination.getLimit(query.limit);
const cursor = CursorPagination.resolve({
  cursor: query.cursor,
  cursorKey: query.cursorKey,
  defaultKeys: ['createdAt', 'id'],
  tieBreakerKeys: ['id'],
  sort: query.sort,
});
```

## External Client Pattern

Reusable packages that manage external systems normally extend `AbstractClientService` and use `ClientConfig`. This preserves shared config validation, `conId` multi-connection support, lifecycle hooks, and retry/debug behavior.

## Repository Layout

- `src/abstractions`: base services, controllers, resolvers, and client factories.
- `src/infras`: application, gateway, and microservice runtime factories.
- `src/modules`: config, logger, metrics, JWT, Bull, and static assets modules.
- `src/models`: shared DTO, request, response, repository, and pagination contracts.
- `src/decorators`: HTTP, Swagger, metric, and transport decorators.
- `src/exceptions`, `src/interceptors`, `src/pipes`: cross-cutting runtime concerns.
- `src/index.ts`: public package export boundary.

## Development

```bash
yarn lint --scope @joktec/core
yarn build --scope @joktec/core
yarn test --scope @joktec/core
```

---
_Source: https://npm.io/package/@joktec/core · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
