@bymax-one/nest-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ var common = require('@nestjs/common');
4
+
5
+ // src/pagination/internal.ts
6
+ var DEFAULT_LIMIT = 20;
7
+ var DEFAULT_MAX_LIMIT = 100;
8
+ var MINIMUM = 1;
9
+ function coercePositiveInt(value, fallback) {
10
+ if (typeof value !== "number" && typeof value !== "string") {
11
+ return fallback;
12
+ }
13
+ const coerced = Number(value);
14
+ if (!Number.isFinite(coerced) || coerced < MINIMUM) {
15
+ return fallback;
16
+ }
17
+ return Math.floor(coerced);
18
+ }
19
+ function clampLimit(rawLimit, options) {
20
+ const defaultLimit = coercePositiveInt(options?.defaultLimit, DEFAULT_LIMIT);
21
+ const maxLimit = coercePositiveInt(options?.maxLimit, DEFAULT_MAX_LIMIT);
22
+ return Math.min(coercePositiveInt(rawLimit, defaultLimit), maxLimit);
23
+ }
24
+
25
+ // src/pagination/offset.ts
26
+ function normalizePageQuery(raw, options) {
27
+ return {
28
+ page: coercePositiveInt(raw.page, MINIMUM),
29
+ limit: clampLimit(raw.limit, options)
30
+ };
31
+ }
32
+ function buildPageResult(items, totalItems, query) {
33
+ const safePage = coercePositiveInt(query.page, MINIMUM);
34
+ const safeTotal = Number.isFinite(totalItems) && totalItems > 0 ? Math.floor(totalItems) : 0;
35
+ const safeLimit = coercePositiveInt(query.limit, DEFAULT_LIMIT);
36
+ const totalPages = Math.ceil(safeTotal / safeLimit);
37
+ return {
38
+ items,
39
+ meta: { page: safePage, limit: safeLimit, totalItems: safeTotal, totalPages }
40
+ };
41
+ }
42
+
43
+ // src/envelope/error-codes.ts
44
+ var BYMAX_VALIDATION_FAILED = "BYMAX_VALIDATION_FAILED";
45
+
46
+ // src/pagination/cursor.ts
47
+ var BASE64URL_PATTERN = /^[A-Za-z0-9_-]+$/;
48
+ var CURSOR_REJECTION_MESSAGE = "Malformed pagination cursor.";
49
+ function cursorRejection() {
50
+ return new common.BadRequestException({
51
+ code: BYMAX_VALIDATION_FAILED,
52
+ message: CURSOR_REJECTION_MESSAGE
53
+ });
54
+ }
55
+ function isOrderingKeyRecord(value) {
56
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
57
+ return false;
58
+ }
59
+ return Object.values(value).every(
60
+ (entry) => typeof entry === "string" || typeof entry === "number" && Number.isFinite(entry)
61
+ );
62
+ }
63
+ function encodeCursor(payload) {
64
+ const encodable = Object.values(payload).every(
65
+ (value) => typeof value === "string" || Number.isFinite(value)
66
+ );
67
+ if (!encodable) {
68
+ throw new Error("encodeCursor payload values must each be a string or a finite number.");
69
+ }
70
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
71
+ }
72
+ function decodeCursor(cursor) {
73
+ if (!BASE64URL_PATTERN.test(cursor)) {
74
+ throw cursorRejection();
75
+ }
76
+ let parsed;
77
+ try {
78
+ parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
79
+ } catch {
80
+ throw cursorRejection();
81
+ }
82
+ if (!isOrderingKeyRecord(parsed)) {
83
+ throw cursorRejection();
84
+ }
85
+ return parsed;
86
+ }
87
+ function normalizeCursorQuery(raw, options) {
88
+ const limit = clampLimit(raw.limit, options);
89
+ if (typeof raw.cursor === "string") {
90
+ return { cursor: raw.cursor, limit };
91
+ }
92
+ return { limit };
93
+ }
94
+ function buildCursorResult(items, limit, toCursor) {
95
+ const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 0;
96
+ if (items.length <= safeLimit) {
97
+ return { items, nextCursor: null };
98
+ }
99
+ const page = items.slice(0, safeLimit);
100
+ const lastItem = page.at(-1);
101
+ if (lastItem === void 0) {
102
+ return { items: page, nextCursor: null };
103
+ }
104
+ return { items: page, nextCursor: encodeCursor(toCursor(lastItem)) };
105
+ }
106
+
107
+ exports.buildCursorResult = buildCursorResult;
108
+ exports.buildPageResult = buildPageResult;
109
+ exports.decodeCursor = decodeCursor;
110
+ exports.encodeCursor = encodeCursor;
111
+ exports.normalizeCursorQuery = normalizeCursorQuery;
112
+ exports.normalizePageQuery = normalizePageQuery;
@@ -0,0 +1,146 @@
1
+ /** Per-call overrides for the clamping bounds. Never module state. */
2
+ interface PaginationLimitOptions {
3
+ /** Page size used when the raw limit is absent or invalid. Default `20`. */
4
+ defaultLimit?: number;
5
+ /** Hard cap applied to the page size. Default `100`. */
6
+ maxLimit?: number;
7
+ }
8
+
9
+ /**
10
+ * @fileoverview Offset pagination primitives for the `./pagination` subpath.
11
+ * Pure, framework-neutral helpers that clamp untrusted page/limit input into a
12
+ * safe {@link PageQuery} and shape a {@link PageResult}. The package never runs
13
+ * a query: the consumer's repository translates the normalized query into its
14
+ * own persistence call and passes the rows and total back to the builder.
15
+ * @layer Utility
16
+ */
17
+
18
+ /** A safe, clamped offset query. `page` is 1-based. */
19
+ interface PageQuery {
20
+ /** 1-based page index, always `>= 1`. */
21
+ page: number;
22
+ /** Page size, always within `[1, maxLimit]`. */
23
+ limit: number;
24
+ }
25
+ /** Pagination metadata describing the position within the full result set. */
26
+ interface PageMeta {
27
+ /** The 1-based page this result represents. */
28
+ page: number;
29
+ /** The page size used to compute the slice. */
30
+ limit: number;
31
+ /** Total number of items across all pages. */
32
+ totalItems: number;
33
+ /** Total number of pages, `0` when there are no items. */
34
+ totalPages: number;
35
+ }
36
+ /** A page of items plus its computed {@link PageMeta}. */
37
+ interface PageResult<T> {
38
+ /** The items on this page. */
39
+ items: T[];
40
+ /** Metadata describing this page within the full set. */
41
+ meta: PageMeta;
42
+ }
43
+ /**
44
+ * Clamp raw request input into a safe {@link PageQuery}.
45
+ *
46
+ * `page` floors to `1`; `limit` floors to `1` and caps at `maxLimit`. Absent,
47
+ * non-numeric, negative, or zero fields fall back to defaults. Options are
48
+ * per-call and never retained between calls.
49
+ *
50
+ * @param raw - The untrusted page and limit values from the request.
51
+ * @param options - Per-call `defaultLimit` (default `20`) and `maxLimit`
52
+ * (default `100`) overrides.
53
+ * @returns A clamped, safe query ready to hand to a repository.
54
+ */
55
+ declare function normalizePageQuery(raw: {
56
+ page?: unknown;
57
+ limit?: unknown;
58
+ }, options?: PaginationLimitOptions): PageQuery;
59
+ /**
60
+ * Assemble a {@link PageResult} from a page of items and the total count.
61
+ *
62
+ * `totalPages` is the ceiling of `totalItems` over the query limit; a total of
63
+ * zero yields zero pages rather than one phantom page. Inputs are defensively
64
+ * normalized so a misused non-positive limit or a negative/non-finite total
65
+ * cannot produce an `Infinity`, `NaN`, or negative page count, and `page` is
66
+ * floored to `1` so the metadata always satisfies the `>= 1` contract.
67
+ *
68
+ * @param items - The items on the current page.
69
+ * @param totalItems - The total number of items across all pages.
70
+ * @param query - The clamped query that produced this page.
71
+ * @returns The page of items with its computed metadata.
72
+ */
73
+ declare function buildPageResult<T>(items: T[], totalItems: number, query: PageQuery): PageResult<T>;
74
+
75
+ /**
76
+ * Encode an ordering-key set into an opaque cursor.
77
+ *
78
+ * The payload must contain ordering keys only and never sensitive data: cursors
79
+ * are opaque but neither encrypted nor signed.
80
+ *
81
+ * @param payload - The ordering keys to encode.
82
+ * @returns A url-safe base64 cursor string.
83
+ * @throws Error when a payload value is not a string or a finite number. This
84
+ * covers non-finite numbers (which would encode as `null` and never decode)
85
+ * as well as any non-string, non-number value reaching the function through an
86
+ * `any`-typed payload.
87
+ */
88
+ declare function encodeCursor(payload: Record<string, string | number>): string;
89
+ /**
90
+ * Decode a cursor produced by {@link encodeCursor}.
91
+ *
92
+ * Input is untrusted: non-base64url text, non-JSON bytes, wrong JSON shapes, and
93
+ * disallowed value types all reject with a {@link BYMAX_VALIDATION_FAILED} HTTP
94
+ * 400 exception. The underlying parse error is never surfaced. The payload must
95
+ * carry ordering keys only and never sensitive data.
96
+ *
97
+ * @param cursor - The opaque cursor string from the request.
98
+ * @returns The decoded ordering-key payload.
99
+ * @throws BadRequestException when the cursor is malformed or of the wrong shape.
100
+ */
101
+ declare function decodeCursor<T extends Record<string, string | number>>(cursor: string): T;
102
+ /** A safe, clamped cursor query. The cursor is validated only at decode time. */
103
+ interface CursorQuery {
104
+ /** Opaque cursor from a prior page, or absent for the first page. */
105
+ cursor?: string;
106
+ /** Page size, always within `[1, maxLimit]`. */
107
+ limit: number;
108
+ }
109
+ /** A page of items plus the cursor for the next page, if any. */
110
+ interface CursorResult<T> {
111
+ /** The items on this page, trimmed to the requested limit. */
112
+ items: T[];
113
+ /** The cursor for the next page, or `null` when this is the last page. */
114
+ nextCursor: string | null;
115
+ }
116
+ /**
117
+ * Clamp raw request input into a safe {@link CursorQuery}.
118
+ *
119
+ * The limit is clamped exactly as the offset path clamps it. The cursor is
120
+ * passed through untouched when it is a string and omitted otherwise; its
121
+ * contents are validated later by {@link decodeCursor}, not here.
122
+ *
123
+ * @param raw - The untrusted cursor and limit values from the request.
124
+ * @param options - Per-call `defaultLimit` (default `20`) and `maxLimit`
125
+ * (default `100`) overrides.
126
+ * @returns A clamped, safe cursor query.
127
+ */
128
+ declare function normalizeCursorQuery(raw: {
129
+ cursor?: unknown;
130
+ limit?: unknown;
131
+ }, options?: PaginationLimitOptions): CursorQuery;
132
+ /**
133
+ * Assemble a {@link CursorResult} using the fetch-one-extra convention.
134
+ *
135
+ * The repository fetches `limit + 1` rows. A count beyond the limit signals a
136
+ * further page: the extra row is trimmed and `nextCursor` is derived from the
137
+ * last returned item. With `limit` rows or fewer, `nextCursor` is `null`.
138
+ *
139
+ * @param items - The fetched rows, expected to be up to `limit + 1` long.
140
+ * @param limit - The requested page size that bounds the returned items.
141
+ * @param toCursor - Maps the last returned item to its ordering keys.
142
+ * @returns The trimmed page and the next cursor, or `null` on the last page.
143
+ */
144
+ declare function buildCursorResult<T>(items: T[], limit: number, toCursor: (lastItem: T) => Record<string, string | number>): CursorResult<T>;
145
+
146
+ export { type CursorQuery, type CursorResult, type PageMeta, type PageQuery, type PageResult, buildCursorResult, buildPageResult, decodeCursor, encodeCursor, normalizeCursorQuery, normalizePageQuery };
@@ -0,0 +1,146 @@
1
+ /** Per-call overrides for the clamping bounds. Never module state. */
2
+ interface PaginationLimitOptions {
3
+ /** Page size used when the raw limit is absent or invalid. Default `20`. */
4
+ defaultLimit?: number;
5
+ /** Hard cap applied to the page size. Default `100`. */
6
+ maxLimit?: number;
7
+ }
8
+
9
+ /**
10
+ * @fileoverview Offset pagination primitives for the `./pagination` subpath.
11
+ * Pure, framework-neutral helpers that clamp untrusted page/limit input into a
12
+ * safe {@link PageQuery} and shape a {@link PageResult}. The package never runs
13
+ * a query: the consumer's repository translates the normalized query into its
14
+ * own persistence call and passes the rows and total back to the builder.
15
+ * @layer Utility
16
+ */
17
+
18
+ /** A safe, clamped offset query. `page` is 1-based. */
19
+ interface PageQuery {
20
+ /** 1-based page index, always `>= 1`. */
21
+ page: number;
22
+ /** Page size, always within `[1, maxLimit]`. */
23
+ limit: number;
24
+ }
25
+ /** Pagination metadata describing the position within the full result set. */
26
+ interface PageMeta {
27
+ /** The 1-based page this result represents. */
28
+ page: number;
29
+ /** The page size used to compute the slice. */
30
+ limit: number;
31
+ /** Total number of items across all pages. */
32
+ totalItems: number;
33
+ /** Total number of pages, `0` when there are no items. */
34
+ totalPages: number;
35
+ }
36
+ /** A page of items plus its computed {@link PageMeta}. */
37
+ interface PageResult<T> {
38
+ /** The items on this page. */
39
+ items: T[];
40
+ /** Metadata describing this page within the full set. */
41
+ meta: PageMeta;
42
+ }
43
+ /**
44
+ * Clamp raw request input into a safe {@link PageQuery}.
45
+ *
46
+ * `page` floors to `1`; `limit` floors to `1` and caps at `maxLimit`. Absent,
47
+ * non-numeric, negative, or zero fields fall back to defaults. Options are
48
+ * per-call and never retained between calls.
49
+ *
50
+ * @param raw - The untrusted page and limit values from the request.
51
+ * @param options - Per-call `defaultLimit` (default `20`) and `maxLimit`
52
+ * (default `100`) overrides.
53
+ * @returns A clamped, safe query ready to hand to a repository.
54
+ */
55
+ declare function normalizePageQuery(raw: {
56
+ page?: unknown;
57
+ limit?: unknown;
58
+ }, options?: PaginationLimitOptions): PageQuery;
59
+ /**
60
+ * Assemble a {@link PageResult} from a page of items and the total count.
61
+ *
62
+ * `totalPages` is the ceiling of `totalItems` over the query limit; a total of
63
+ * zero yields zero pages rather than one phantom page. Inputs are defensively
64
+ * normalized so a misused non-positive limit or a negative/non-finite total
65
+ * cannot produce an `Infinity`, `NaN`, or negative page count, and `page` is
66
+ * floored to `1` so the metadata always satisfies the `>= 1` contract.
67
+ *
68
+ * @param items - The items on the current page.
69
+ * @param totalItems - The total number of items across all pages.
70
+ * @param query - The clamped query that produced this page.
71
+ * @returns The page of items with its computed metadata.
72
+ */
73
+ declare function buildPageResult<T>(items: T[], totalItems: number, query: PageQuery): PageResult<T>;
74
+
75
+ /**
76
+ * Encode an ordering-key set into an opaque cursor.
77
+ *
78
+ * The payload must contain ordering keys only and never sensitive data: cursors
79
+ * are opaque but neither encrypted nor signed.
80
+ *
81
+ * @param payload - The ordering keys to encode.
82
+ * @returns A url-safe base64 cursor string.
83
+ * @throws Error when a payload value is not a string or a finite number. This
84
+ * covers non-finite numbers (which would encode as `null` and never decode)
85
+ * as well as any non-string, non-number value reaching the function through an
86
+ * `any`-typed payload.
87
+ */
88
+ declare function encodeCursor(payload: Record<string, string | number>): string;
89
+ /**
90
+ * Decode a cursor produced by {@link encodeCursor}.
91
+ *
92
+ * Input is untrusted: non-base64url text, non-JSON bytes, wrong JSON shapes, and
93
+ * disallowed value types all reject with a {@link BYMAX_VALIDATION_FAILED} HTTP
94
+ * 400 exception. The underlying parse error is never surfaced. The payload must
95
+ * carry ordering keys only and never sensitive data.
96
+ *
97
+ * @param cursor - The opaque cursor string from the request.
98
+ * @returns The decoded ordering-key payload.
99
+ * @throws BadRequestException when the cursor is malformed or of the wrong shape.
100
+ */
101
+ declare function decodeCursor<T extends Record<string, string | number>>(cursor: string): T;
102
+ /** A safe, clamped cursor query. The cursor is validated only at decode time. */
103
+ interface CursorQuery {
104
+ /** Opaque cursor from a prior page, or absent for the first page. */
105
+ cursor?: string;
106
+ /** Page size, always within `[1, maxLimit]`. */
107
+ limit: number;
108
+ }
109
+ /** A page of items plus the cursor for the next page, if any. */
110
+ interface CursorResult<T> {
111
+ /** The items on this page, trimmed to the requested limit. */
112
+ items: T[];
113
+ /** The cursor for the next page, or `null` when this is the last page. */
114
+ nextCursor: string | null;
115
+ }
116
+ /**
117
+ * Clamp raw request input into a safe {@link CursorQuery}.
118
+ *
119
+ * The limit is clamped exactly as the offset path clamps it. The cursor is
120
+ * passed through untouched when it is a string and omitted otherwise; its
121
+ * contents are validated later by {@link decodeCursor}, not here.
122
+ *
123
+ * @param raw - The untrusted cursor and limit values from the request.
124
+ * @param options - Per-call `defaultLimit` (default `20`) and `maxLimit`
125
+ * (default `100`) overrides.
126
+ * @returns A clamped, safe cursor query.
127
+ */
128
+ declare function normalizeCursorQuery(raw: {
129
+ cursor?: unknown;
130
+ limit?: unknown;
131
+ }, options?: PaginationLimitOptions): CursorQuery;
132
+ /**
133
+ * Assemble a {@link CursorResult} using the fetch-one-extra convention.
134
+ *
135
+ * The repository fetches `limit + 1` rows. A count beyond the limit signals a
136
+ * further page: the extra row is trimmed and `nextCursor` is derived from the
137
+ * last returned item. With `limit` rows or fewer, `nextCursor` is `null`.
138
+ *
139
+ * @param items - The fetched rows, expected to be up to `limit + 1` long.
140
+ * @param limit - The requested page size that bounds the returned items.
141
+ * @param toCursor - Maps the last returned item to its ordering keys.
142
+ * @returns The trimmed page and the next cursor, or `null` on the last page.
143
+ */
144
+ declare function buildCursorResult<T>(items: T[], limit: number, toCursor: (lastItem: T) => Record<string, string | number>): CursorResult<T>;
145
+
146
+ export { type CursorQuery, type CursorResult, type PageMeta, type PageQuery, type PageResult, buildCursorResult, buildPageResult, decodeCursor, encodeCursor, normalizeCursorQuery, normalizePageQuery };
@@ -0,0 +1,105 @@
1
+ import { BadRequestException } from '@nestjs/common';
2
+
3
+ // src/pagination/internal.ts
4
+ var DEFAULT_LIMIT = 20;
5
+ var DEFAULT_MAX_LIMIT = 100;
6
+ var MINIMUM = 1;
7
+ function coercePositiveInt(value, fallback) {
8
+ if (typeof value !== "number" && typeof value !== "string") {
9
+ return fallback;
10
+ }
11
+ const coerced = Number(value);
12
+ if (!Number.isFinite(coerced) || coerced < MINIMUM) {
13
+ return fallback;
14
+ }
15
+ return Math.floor(coerced);
16
+ }
17
+ function clampLimit(rawLimit, options) {
18
+ const defaultLimit = coercePositiveInt(options?.defaultLimit, DEFAULT_LIMIT);
19
+ const maxLimit = coercePositiveInt(options?.maxLimit, DEFAULT_MAX_LIMIT);
20
+ return Math.min(coercePositiveInt(rawLimit, defaultLimit), maxLimit);
21
+ }
22
+
23
+ // src/pagination/offset.ts
24
+ function normalizePageQuery(raw, options) {
25
+ return {
26
+ page: coercePositiveInt(raw.page, MINIMUM),
27
+ limit: clampLimit(raw.limit, options)
28
+ };
29
+ }
30
+ function buildPageResult(items, totalItems, query) {
31
+ const safePage = coercePositiveInt(query.page, MINIMUM);
32
+ const safeTotal = Number.isFinite(totalItems) && totalItems > 0 ? Math.floor(totalItems) : 0;
33
+ const safeLimit = coercePositiveInt(query.limit, DEFAULT_LIMIT);
34
+ const totalPages = Math.ceil(safeTotal / safeLimit);
35
+ return {
36
+ items,
37
+ meta: { page: safePage, limit: safeLimit, totalItems: safeTotal, totalPages }
38
+ };
39
+ }
40
+
41
+ // src/envelope/error-codes.ts
42
+ var BYMAX_VALIDATION_FAILED = "BYMAX_VALIDATION_FAILED";
43
+
44
+ // src/pagination/cursor.ts
45
+ var BASE64URL_PATTERN = /^[A-Za-z0-9_-]+$/;
46
+ var CURSOR_REJECTION_MESSAGE = "Malformed pagination cursor.";
47
+ function cursorRejection() {
48
+ return new BadRequestException({
49
+ code: BYMAX_VALIDATION_FAILED,
50
+ message: CURSOR_REJECTION_MESSAGE
51
+ });
52
+ }
53
+ function isOrderingKeyRecord(value) {
54
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
55
+ return false;
56
+ }
57
+ return Object.values(value).every(
58
+ (entry) => typeof entry === "string" || typeof entry === "number" && Number.isFinite(entry)
59
+ );
60
+ }
61
+ function encodeCursor(payload) {
62
+ const encodable = Object.values(payload).every(
63
+ (value) => typeof value === "string" || Number.isFinite(value)
64
+ );
65
+ if (!encodable) {
66
+ throw new Error("encodeCursor payload values must each be a string or a finite number.");
67
+ }
68
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
69
+ }
70
+ function decodeCursor(cursor) {
71
+ if (!BASE64URL_PATTERN.test(cursor)) {
72
+ throw cursorRejection();
73
+ }
74
+ let parsed;
75
+ try {
76
+ parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
77
+ } catch {
78
+ throw cursorRejection();
79
+ }
80
+ if (!isOrderingKeyRecord(parsed)) {
81
+ throw cursorRejection();
82
+ }
83
+ return parsed;
84
+ }
85
+ function normalizeCursorQuery(raw, options) {
86
+ const limit = clampLimit(raw.limit, options);
87
+ if (typeof raw.cursor === "string") {
88
+ return { cursor: raw.cursor, limit };
89
+ }
90
+ return { limit };
91
+ }
92
+ function buildCursorResult(items, limit, toCursor) {
93
+ const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 0;
94
+ if (items.length <= safeLimit) {
95
+ return { items, nextCursor: null };
96
+ }
97
+ const page = items.slice(0, safeLimit);
98
+ const lastItem = page.at(-1);
99
+ if (lastItem === void 0) {
100
+ return { items: page, nextCursor: null };
101
+ }
102
+ return { items: page, nextCursor: encodeCursor(toCursor(lastItem)) };
103
+ }
104
+
105
+ export { buildCursorResult, buildPageResult, decodeCursor, encodeCursor, normalizeCursorQuery, normalizePageQuery };
package/package.json ADDED
@@ -0,0 +1,169 @@
1
+ {
2
+ "name": "@bymax-one/nest-core",
3
+ "version": "1.0.0",
4
+ "description": "Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints, and an optional Prometheus metrics endpoint.",
5
+ "author": "Bymax One <support@bymax.one>",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/bymaxone/nest-core#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/bymaxone/nest-core.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/bymaxone/nest-core/issues"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "files": [
18
+ "dist",
19
+ "LICENSE",
20
+ "README.md",
21
+ "CHANGELOG.md"
22
+ ],
23
+ "main": "./dist/index.cjs",
24
+ "types": "./dist/index.d.cts",
25
+ "exports": {
26
+ ".": {
27
+ "import": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.mjs"
30
+ },
31
+ "require": {
32
+ "types": "./dist/index.d.cts",
33
+ "default": "./dist/index.cjs"
34
+ }
35
+ },
36
+ "./pagination": {
37
+ "import": {
38
+ "types": "./dist/pagination/index.d.ts",
39
+ "default": "./dist/pagination/index.mjs"
40
+ },
41
+ "require": {
42
+ "types": "./dist/pagination/index.d.cts",
43
+ "default": "./dist/pagination/index.cjs"
44
+ }
45
+ },
46
+ "./health": {
47
+ "import": {
48
+ "types": "./dist/health/index.d.ts",
49
+ "default": "./dist/health/index.mjs"
50
+ },
51
+ "require": {
52
+ "types": "./dist/health/index.d.cts",
53
+ "default": "./dist/health/index.cjs"
54
+ }
55
+ },
56
+ "./package.json": "./package.json"
57
+ },
58
+ "lint-staged": {
59
+ "*.{ts,tsx,js,mjs,cjs}": [
60
+ "eslint --fix",
61
+ "prettier --write"
62
+ ],
63
+ "*.{json,md,yml,yaml}": [
64
+ "prettier --write"
65
+ ]
66
+ },
67
+ "dependencies": {},
68
+ "peerDependencies": {
69
+ "@nestjs/common": "^11.0.16",
70
+ "@nestjs/core": "^11.1.18",
71
+ "reflect-metadata": "^0.2.0",
72
+ "rxjs": "^7.0.0",
73
+ "prom-client": "^15.0.0"
74
+ },
75
+ "peerDependenciesMeta": {
76
+ "prom-client": {
77
+ "optional": true
78
+ }
79
+ },
80
+ "devDependencies": {
81
+ "@arethetypeswrong/cli": "^0.18.2",
82
+ "@commitlint/cli": "^21.2.1",
83
+ "@commitlint/config-conventional": "^21.2.0",
84
+ "@eslint/js": "^9.39.4",
85
+ "@nestjs/common": "^11.1.20",
86
+ "@nestjs/core": "^11.1.20",
87
+ "@nestjs/platform-express": "^11.1.20",
88
+ "@nestjs/testing": "^11.1.20",
89
+ "@stryker-mutator/core": "^9",
90
+ "@stryker-mutator/jest-runner": "^9",
91
+ "@stryker-mutator/typescript-checker": "^9",
92
+ "@types/express": "^5.0.6",
93
+ "@types/jest": "^30.0.0",
94
+ "@types/node": "^24",
95
+ "@types/supertest": "^7.2.0",
96
+ "@typescript-eslint/eslint-plugin": "^8.59.3",
97
+ "@typescript-eslint/parser": "^8.59.3",
98
+ "eslint": "^9.39.4",
99
+ "eslint-config-prettier": "^10.1.8",
100
+ "eslint-import-resolver-typescript": "^4.4.4",
101
+ "eslint-plugin-import": "^2.32.0",
102
+ "eslint-plugin-prettier": "^5.5.5",
103
+ "eslint-plugin-security": "^4.0.0",
104
+ "globals": "^17.6.0",
105
+ "husky": "^9.1.7",
106
+ "jest": "^30.4.2",
107
+ "lint-staged": "^17.2.0",
108
+ "prettier": "^3.8.3",
109
+ "prom-client": "^15.1.3",
110
+ "reflect-metadata": "^0.2.2",
111
+ "rxjs": "^7.8.0",
112
+ "supertest": "^7.2.2",
113
+ "ts-jest": "^29.4.9",
114
+ "ts-node": "^10.9.2",
115
+ "tsup": "^8.5.1",
116
+ "typescript": "^5.9.3"
117
+ },
118
+ "keywords": [
119
+ "nestjs",
120
+ "error-envelope",
121
+ "exception-filter",
122
+ "request-timing",
123
+ "pagination",
124
+ "health-check",
125
+ "prometheus",
126
+ "metrics",
127
+ "typescript"
128
+ ],
129
+ "engines": {
130
+ "node": ">=24.0.0"
131
+ },
132
+ "publishConfig": {
133
+ "access": "public",
134
+ "provenance": true,
135
+ "registry": "https://registry.npmjs.org/"
136
+ },
137
+ "module": "./dist/index.mjs",
138
+ "typesVersions": {
139
+ "*": {
140
+ "pagination": [
141
+ "./dist/pagination/index.d.cts"
142
+ ],
143
+ "health": [
144
+ "./dist/health/index.d.cts"
145
+ ]
146
+ }
147
+ },
148
+ "scripts": {
149
+ "build": "pnpm clean && tsup",
150
+ "check:exports": "attw --pack . --profile strict",
151
+ "check:published": "node scripts/check-published-surface.mjs",
152
+ "check:runtime": "node scripts/check-consumer-runtime.mjs",
153
+ "clean": "node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"",
154
+ "dogfood": "node scripts/dogfood-smoke-test.mjs",
155
+ "lint": "eslint --no-error-on-unmatched-pattern src scripts test",
156
+ "lint:fix": "eslint --no-error-on-unmatched-pattern src scripts test --fix",
157
+ "mutation": "stryker run",
158
+ "mutation:dry-run": "stryker run --dryRunOnly",
159
+ "mutation:incremental": "stryker run --incremental",
160
+ "release": "npm publish --provenance --access public",
161
+ "size": "node scripts/check-size.mjs",
162
+ "test": "jest",
163
+ "test:cov": "jest --coverage",
164
+ "test:cov:all": "jest --config jest.coverage.config.ts --coverage",
165
+ "test:e2e": "jest --config jest.e2e.config.ts",
166
+ "test:watch": "jest --watch",
167
+ "typecheck": "tsc --noEmit"
168
+ }
169
+ }