@bymax-one/nest-logger 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,27 @@
1
+ 'use strict';
2
+
3
+ // src/shared/constants/log-keys-convention.constants.ts
4
+ var LOG_KEYS_CONVENTION_REGEX = /^[A-Z][A-Z0-9_]+_[A-Z][A-Z0-9_]+(_[A-Z][A-Z0-9_]+)?$/;
5
+
6
+ // src/shared/constants/reserved-log-keys.constants.ts
7
+ var RESERVED_LOG_KEYS = Object.freeze({
8
+ LOGGER_BOOTSTRAP_OK: "LOGGER_BOOTSTRAP_OK",
9
+ LOGGER_BOOTSTRAP_WARNING: "LOGGER_BOOTSTRAP_WARNING",
10
+ LOGGER_SHUTDOWN_OK: "LOGGER_SHUTDOWN_OK",
11
+ HTTP_REQUEST_START: "HTTP_REQUEST_START",
12
+ HTTP_REQUEST_SUCCESS: "HTTP_REQUEST_SUCCESS",
13
+ HTTP_REQUEST_REDIRECT: "HTTP_REQUEST_REDIRECT",
14
+ HTTP_REQUEST_CLIENT_ERROR: "HTTP_REQUEST_CLIENT_ERROR",
15
+ HTTP_REQUEST_SERVER_ERROR: "HTTP_REQUEST_SERVER_ERROR",
16
+ HTTP_REQUEST_COMPLETED: "HTTP_REQUEST_COMPLETED",
17
+ HTTP_EXCEPTION_HANDLED: "HTTP_EXCEPTION_HANDLED",
18
+ HTTP_EXCEPTION_UNHANDLED: "HTTP_EXCEPTION_UNHANDLED",
19
+ METHOD_EXECUTION: "METHOD_EXECUTION",
20
+ METHOD_SLOW_EXECUTION: "METHOD_SLOW_EXECUTION",
21
+ LOGGER_DESTINATION_INIT_FAILED: "LOGGER_DESTINATION_INIT_FAILED",
22
+ LOGGER_DESTINATION_WRITE_FAILED: "LOGGER_DESTINATION_WRITE_FAILED",
23
+ LOGGER_ENTRY_TRUNCATED: "LOGGER_ENTRY_TRUNCATED"
24
+ });
25
+
26
+ exports.LOG_KEYS_CONVENTION_REGEX = LOG_KEYS_CONVENTION_REGEX;
27
+ exports.RESERVED_LOG_KEYS = RESERVED_LOG_KEYS;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Pino log levels (mirrored to NestJS-compatible names).
3
+ *
4
+ * Numeric mapping (Pino):
5
+ * - `fatal` 60
6
+ * - `error` 50
7
+ * - `warn` 40
8
+ * - `info` 30
9
+ * - `debug` 20
10
+ * - `trace` 10
11
+ *
12
+ * @example
13
+ * const level: LogLevel = 'info'
14
+ */
15
+ type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
16
+
17
+ /**
18
+ * Service metadata propagated to every log entry.
19
+ *
20
+ * Aligned with OpenTelemetry semantic conventions for service identity:
21
+ * {@link https://opentelemetry.io/docs/specs/semconv/resource/#service}
22
+ */
23
+ interface ServiceMetadata {
24
+ /** OTel attribute `service.name` — stable identifier of the running service. */
25
+ readonly name: string;
26
+ /** OTel attribute `service.version` — semver, commit SHA, or build tag. */
27
+ readonly version: string;
28
+ }
29
+
30
+ /**
31
+ * Shape of a single log entry as serialized to JSON output.
32
+ *
33
+ * Used by destinations and downstream parsers (Datadog, Loki, Elastic).
34
+ * The trailing index signature `[key: string]: unknown` covers arbitrary
35
+ * structured fields injected by application logs.
36
+ */
37
+ interface LogEntry {
38
+ /** Pino numeric level (30 = info, 50 = error, etc.). */
39
+ level: number;
40
+ /** ISO 8601 UTC timestamp string OR epoch milliseconds (numeric). */
41
+ time: string | number;
42
+ /** Human-readable message. */
43
+ msg: string;
44
+ /** Convention key — `MODULE_ACTION_RESULT` format. */
45
+ logKey?: string;
46
+ /** Service metadata snapshot — see {@link ServiceMetadata}. */
47
+ service?: ServiceMetadata;
48
+ /** Optional NestJS context (typically the emitting class name). */
49
+ context?: string;
50
+ /** Optional correlation IDs propagated via AsyncLocalStorage. */
51
+ requestId?: string;
52
+ tenantId?: string;
53
+ userId?: string;
54
+ /** Optional trace context injected when OpenTelemetry SDK is active. */
55
+ traceId?: string;
56
+ spanId?: string;
57
+ /** Arbitrary additional fields produced by application logs. */
58
+ [key: string]: unknown;
59
+ }
60
+
61
+ /**
62
+ * Regex enforcing the canonical Bymax log-key convention.
63
+ *
64
+ * The convention is `MODULE_ACTION_RESULT` (e.g., `USER_CREATED`,
65
+ * `AUTH_LOGIN_SUCCESS`), but the regex accepts **two or more** uppercase words —
66
+ * keys in {@link RESERVED_LOG_KEYS} legitimately use four words
67
+ * (e.g. `HTTP_REQUEST_CLIENT_ERROR`, `LOGGER_DESTINATION_WRITE_FAILED`).
68
+ *
69
+ * Pattern: two mandatory uppercase-prefixed groups separated by `_`, plus one
70
+ * optional third group. Within each group, `[A-Z0-9_]+` allows digits and
71
+ * underscores after the leading uppercase letter, which enables additional
72
+ * semantic words inside a group (e.g., `HTTP_REQUEST_CLIENT` is the first group
73
+ * in `HTTP_REQUEST_CLIENT_ERROR`). As a side-effect, strings with a double
74
+ * underscore (`HELLO__WORLD`) also pass; this is an accepted edge case.
75
+ *
76
+ * Enforcement rules:
77
+ * - At least 2 uppercase-prefixed words (`[A-Z][A-Z0-9_]+`)
78
+ * - Each pattern group starts with `A-Z`; no lowercase letters permitted
79
+ * - No leading or trailing underscores at the top level
80
+ *
81
+ * @example
82
+ * LOG_KEYS_CONVENTION_REGEX.test('USER_CREATED') // true
83
+ * LOG_KEYS_CONVENTION_REGEX.test('AUTH_LOGIN_SUCCESS') // true
84
+ * LOG_KEYS_CONVENTION_REGEX.test('HTTP_REQUEST_CLIENT_ERROR') // true (4 words)
85
+ * LOG_KEYS_CONVENTION_REGEX.test('login_success') // false (lowercase)
86
+ * LOG_KEYS_CONVENTION_REGEX.test('LOGIN') // false (single word)
87
+ */
88
+ declare const LOG_KEYS_CONVENTION_REGEX: RegExp;
89
+
90
+ /**
91
+ * Log keys reserved by `@bymax-one/nest-logger` for its own structured events.
92
+ *
93
+ * Consumer apps SHOULD NOT use these names for application-level events
94
+ * to avoid collision in log aggregation queries (Datadog, Loki, Elastic).
95
+ */
96
+ declare const RESERVED_LOG_KEYS: Readonly<{
97
+ readonly LOGGER_BOOTSTRAP_OK: "LOGGER_BOOTSTRAP_OK";
98
+ readonly LOGGER_BOOTSTRAP_WARNING: "LOGGER_BOOTSTRAP_WARNING";
99
+ readonly LOGGER_SHUTDOWN_OK: "LOGGER_SHUTDOWN_OK";
100
+ readonly HTTP_REQUEST_START: "HTTP_REQUEST_START";
101
+ readonly HTTP_REQUEST_SUCCESS: "HTTP_REQUEST_SUCCESS";
102
+ readonly HTTP_REQUEST_REDIRECT: "HTTP_REQUEST_REDIRECT";
103
+ readonly HTTP_REQUEST_CLIENT_ERROR: "HTTP_REQUEST_CLIENT_ERROR";
104
+ readonly HTTP_REQUEST_SERVER_ERROR: "HTTP_REQUEST_SERVER_ERROR";
105
+ readonly HTTP_REQUEST_COMPLETED: "HTTP_REQUEST_COMPLETED";
106
+ readonly HTTP_EXCEPTION_HANDLED: "HTTP_EXCEPTION_HANDLED";
107
+ readonly HTTP_EXCEPTION_UNHANDLED: "HTTP_EXCEPTION_UNHANDLED";
108
+ readonly METHOD_EXECUTION: "METHOD_EXECUTION";
109
+ readonly METHOD_SLOW_EXECUTION: "METHOD_SLOW_EXECUTION";
110
+ readonly LOGGER_DESTINATION_INIT_FAILED: "LOGGER_DESTINATION_INIT_FAILED";
111
+ readonly LOGGER_DESTINATION_WRITE_FAILED: "LOGGER_DESTINATION_WRITE_FAILED";
112
+ readonly LOGGER_ENTRY_TRUNCATED: "LOGGER_ENTRY_TRUNCATED";
113
+ }>;
114
+ /**
115
+ * Strongly-typed union of every reserved log key value, derived from
116
+ * {@link RESERVED_LOG_KEYS}. Use this type to constrain log-key arguments.
117
+ */
118
+ type ReservedLogKey = (typeof RESERVED_LOG_KEYS)[keyof typeof RESERVED_LOG_KEYS];
119
+
120
+ export { LOG_KEYS_CONVENTION_REGEX, type LogEntry, type LogLevel, RESERVED_LOG_KEYS, type ReservedLogKey, type ServiceMetadata };
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Pino log levels (mirrored to NestJS-compatible names).
3
+ *
4
+ * Numeric mapping (Pino):
5
+ * - `fatal` 60
6
+ * - `error` 50
7
+ * - `warn` 40
8
+ * - `info` 30
9
+ * - `debug` 20
10
+ * - `trace` 10
11
+ *
12
+ * @example
13
+ * const level: LogLevel = 'info'
14
+ */
15
+ type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
16
+
17
+ /**
18
+ * Service metadata propagated to every log entry.
19
+ *
20
+ * Aligned with OpenTelemetry semantic conventions for service identity:
21
+ * {@link https://opentelemetry.io/docs/specs/semconv/resource/#service}
22
+ */
23
+ interface ServiceMetadata {
24
+ /** OTel attribute `service.name` — stable identifier of the running service. */
25
+ readonly name: string;
26
+ /** OTel attribute `service.version` — semver, commit SHA, or build tag. */
27
+ readonly version: string;
28
+ }
29
+
30
+ /**
31
+ * Shape of a single log entry as serialized to JSON output.
32
+ *
33
+ * Used by destinations and downstream parsers (Datadog, Loki, Elastic).
34
+ * The trailing index signature `[key: string]: unknown` covers arbitrary
35
+ * structured fields injected by application logs.
36
+ */
37
+ interface LogEntry {
38
+ /** Pino numeric level (30 = info, 50 = error, etc.). */
39
+ level: number;
40
+ /** ISO 8601 UTC timestamp string OR epoch milliseconds (numeric). */
41
+ time: string | number;
42
+ /** Human-readable message. */
43
+ msg: string;
44
+ /** Convention key — `MODULE_ACTION_RESULT` format. */
45
+ logKey?: string;
46
+ /** Service metadata snapshot — see {@link ServiceMetadata}. */
47
+ service?: ServiceMetadata;
48
+ /** Optional NestJS context (typically the emitting class name). */
49
+ context?: string;
50
+ /** Optional correlation IDs propagated via AsyncLocalStorage. */
51
+ requestId?: string;
52
+ tenantId?: string;
53
+ userId?: string;
54
+ /** Optional trace context injected when OpenTelemetry SDK is active. */
55
+ traceId?: string;
56
+ spanId?: string;
57
+ /** Arbitrary additional fields produced by application logs. */
58
+ [key: string]: unknown;
59
+ }
60
+
61
+ /**
62
+ * Regex enforcing the canonical Bymax log-key convention.
63
+ *
64
+ * The convention is `MODULE_ACTION_RESULT` (e.g., `USER_CREATED`,
65
+ * `AUTH_LOGIN_SUCCESS`), but the regex accepts **two or more** uppercase words —
66
+ * keys in {@link RESERVED_LOG_KEYS} legitimately use four words
67
+ * (e.g. `HTTP_REQUEST_CLIENT_ERROR`, `LOGGER_DESTINATION_WRITE_FAILED`).
68
+ *
69
+ * Pattern: two mandatory uppercase-prefixed groups separated by `_`, plus one
70
+ * optional third group. Within each group, `[A-Z0-9_]+` allows digits and
71
+ * underscores after the leading uppercase letter, which enables additional
72
+ * semantic words inside a group (e.g., `HTTP_REQUEST_CLIENT` is the first group
73
+ * in `HTTP_REQUEST_CLIENT_ERROR`). As a side-effect, strings with a double
74
+ * underscore (`HELLO__WORLD`) also pass; this is an accepted edge case.
75
+ *
76
+ * Enforcement rules:
77
+ * - At least 2 uppercase-prefixed words (`[A-Z][A-Z0-9_]+`)
78
+ * - Each pattern group starts with `A-Z`; no lowercase letters permitted
79
+ * - No leading or trailing underscores at the top level
80
+ *
81
+ * @example
82
+ * LOG_KEYS_CONVENTION_REGEX.test('USER_CREATED') // true
83
+ * LOG_KEYS_CONVENTION_REGEX.test('AUTH_LOGIN_SUCCESS') // true
84
+ * LOG_KEYS_CONVENTION_REGEX.test('HTTP_REQUEST_CLIENT_ERROR') // true (4 words)
85
+ * LOG_KEYS_CONVENTION_REGEX.test('login_success') // false (lowercase)
86
+ * LOG_KEYS_CONVENTION_REGEX.test('LOGIN') // false (single word)
87
+ */
88
+ declare const LOG_KEYS_CONVENTION_REGEX: RegExp;
89
+
90
+ /**
91
+ * Log keys reserved by `@bymax-one/nest-logger` for its own structured events.
92
+ *
93
+ * Consumer apps SHOULD NOT use these names for application-level events
94
+ * to avoid collision in log aggregation queries (Datadog, Loki, Elastic).
95
+ */
96
+ declare const RESERVED_LOG_KEYS: Readonly<{
97
+ readonly LOGGER_BOOTSTRAP_OK: "LOGGER_BOOTSTRAP_OK";
98
+ readonly LOGGER_BOOTSTRAP_WARNING: "LOGGER_BOOTSTRAP_WARNING";
99
+ readonly LOGGER_SHUTDOWN_OK: "LOGGER_SHUTDOWN_OK";
100
+ readonly HTTP_REQUEST_START: "HTTP_REQUEST_START";
101
+ readonly HTTP_REQUEST_SUCCESS: "HTTP_REQUEST_SUCCESS";
102
+ readonly HTTP_REQUEST_REDIRECT: "HTTP_REQUEST_REDIRECT";
103
+ readonly HTTP_REQUEST_CLIENT_ERROR: "HTTP_REQUEST_CLIENT_ERROR";
104
+ readonly HTTP_REQUEST_SERVER_ERROR: "HTTP_REQUEST_SERVER_ERROR";
105
+ readonly HTTP_REQUEST_COMPLETED: "HTTP_REQUEST_COMPLETED";
106
+ readonly HTTP_EXCEPTION_HANDLED: "HTTP_EXCEPTION_HANDLED";
107
+ readonly HTTP_EXCEPTION_UNHANDLED: "HTTP_EXCEPTION_UNHANDLED";
108
+ readonly METHOD_EXECUTION: "METHOD_EXECUTION";
109
+ readonly METHOD_SLOW_EXECUTION: "METHOD_SLOW_EXECUTION";
110
+ readonly LOGGER_DESTINATION_INIT_FAILED: "LOGGER_DESTINATION_INIT_FAILED";
111
+ readonly LOGGER_DESTINATION_WRITE_FAILED: "LOGGER_DESTINATION_WRITE_FAILED";
112
+ readonly LOGGER_ENTRY_TRUNCATED: "LOGGER_ENTRY_TRUNCATED";
113
+ }>;
114
+ /**
115
+ * Strongly-typed union of every reserved log key value, derived from
116
+ * {@link RESERVED_LOG_KEYS}. Use this type to constrain log-key arguments.
117
+ */
118
+ type ReservedLogKey = (typeof RESERVED_LOG_KEYS)[keyof typeof RESERVED_LOG_KEYS];
119
+
120
+ export { LOG_KEYS_CONVENTION_REGEX, type LogEntry, type LogLevel, RESERVED_LOG_KEYS, type ReservedLogKey, type ServiceMetadata };
@@ -0,0 +1,24 @@
1
+ // src/shared/constants/log-keys-convention.constants.ts
2
+ var LOG_KEYS_CONVENTION_REGEX = /^[A-Z][A-Z0-9_]+_[A-Z][A-Z0-9_]+(_[A-Z][A-Z0-9_]+)?$/;
3
+
4
+ // src/shared/constants/reserved-log-keys.constants.ts
5
+ var RESERVED_LOG_KEYS = Object.freeze({
6
+ LOGGER_BOOTSTRAP_OK: "LOGGER_BOOTSTRAP_OK",
7
+ LOGGER_BOOTSTRAP_WARNING: "LOGGER_BOOTSTRAP_WARNING",
8
+ LOGGER_SHUTDOWN_OK: "LOGGER_SHUTDOWN_OK",
9
+ HTTP_REQUEST_START: "HTTP_REQUEST_START",
10
+ HTTP_REQUEST_SUCCESS: "HTTP_REQUEST_SUCCESS",
11
+ HTTP_REQUEST_REDIRECT: "HTTP_REQUEST_REDIRECT",
12
+ HTTP_REQUEST_CLIENT_ERROR: "HTTP_REQUEST_CLIENT_ERROR",
13
+ HTTP_REQUEST_SERVER_ERROR: "HTTP_REQUEST_SERVER_ERROR",
14
+ HTTP_REQUEST_COMPLETED: "HTTP_REQUEST_COMPLETED",
15
+ HTTP_EXCEPTION_HANDLED: "HTTP_EXCEPTION_HANDLED",
16
+ HTTP_EXCEPTION_UNHANDLED: "HTTP_EXCEPTION_UNHANDLED",
17
+ METHOD_EXECUTION: "METHOD_EXECUTION",
18
+ METHOD_SLOW_EXECUTION: "METHOD_SLOW_EXECUTION",
19
+ LOGGER_DESTINATION_INIT_FAILED: "LOGGER_DESTINATION_INIT_FAILED",
20
+ LOGGER_DESTINATION_WRITE_FAILED: "LOGGER_DESTINATION_WRITE_FAILED",
21
+ LOGGER_ENTRY_TRUNCATED: "LOGGER_ENTRY_TRUNCATED"
22
+ });
23
+
24
+ export { LOG_KEYS_CONVENTION_REGEX, RESERVED_LOG_KEYS };
package/package.json ADDED
@@ -0,0 +1,141 @@
1
+ {
2
+ "name": "@bymax-one/nest-logger",
3
+ "version": "1.0.0",
4
+ "description": "Structured JSON logging for NestJS based on Pino 10, with optional OpenTelemetry correlation.",
5
+ "author": "Bymax One <support@bymax.one>",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/bymaxone/nest-logger#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/bymaxone/nest-logger.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/bymaxone/nest-logger/issues"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "files": [
18
+ "dist",
19
+ "LICENSE",
20
+ "README.md",
21
+ "CHANGELOG.md"
22
+ ],
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/server/index.d.ts",
26
+ "import": "./dist/server/index.mjs",
27
+ "require": "./dist/server/index.cjs"
28
+ },
29
+ "./shared": {
30
+ "types": "./dist/shared/index.d.ts",
31
+ "import": "./dist/shared/index.mjs",
32
+ "require": "./dist/shared/index.cjs"
33
+ }
34
+ },
35
+ "lint-staged": {
36
+ "*.{ts,tsx,js,mjs,cjs}": [
37
+ "eslint --fix",
38
+ "prettier --write"
39
+ ],
40
+ "*.{json,md,yml,yaml}": [
41
+ "prettier --write"
42
+ ]
43
+ },
44
+ "dependencies": {},
45
+ "peerDependencies": {
46
+ "@nestjs/common": "^11.0.0",
47
+ "@nestjs/core": "^11.0.0",
48
+ "pino": "^10.0.0",
49
+ "reflect-metadata": "^0.2.0",
50
+ "rxjs": "^7.8.0",
51
+ "pino-pretty": "^13.0.0",
52
+ "@opentelemetry/api": "^1.9.0"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "pino-pretty": {
56
+ "optional": true
57
+ },
58
+ "@opentelemetry/api": {
59
+ "optional": true
60
+ }
61
+ },
62
+ "devDependencies": {
63
+ "@commitlint/cli": "^21.0.2",
64
+ "@commitlint/config-conventional": "^21.0.2",
65
+ "@eslint/js": "^9.39.4",
66
+ "@nestjs/common": "^11.1.20",
67
+ "@nestjs/core": "^11.1.20",
68
+ "@nestjs/platform-express": "^11.1.20",
69
+ "@nestjs/testing": "^11.1.20",
70
+ "@opentelemetry/api": "^1.9.0",
71
+ "@stryker-mutator/core": "^9",
72
+ "@stryker-mutator/jest-runner": "^9",
73
+ "@stryker-mutator/typescript-checker": "^9",
74
+ "@types/express": "^5.0.6",
75
+ "@types/jest": "^30.0.0",
76
+ "@types/node": "^25",
77
+ "@types/supertest": "^7.2.0",
78
+ "@typescript-eslint/eslint-plugin": "^8.59.3",
79
+ "@typescript-eslint/parser": "^8.59.3",
80
+ "eslint": "^9.39.4",
81
+ "eslint-config-prettier": "^10.1.8",
82
+ "eslint-import-resolver-typescript": "^4.4.4",
83
+ "eslint-plugin-import": "^2.32.0",
84
+ "eslint-plugin-prettier": "^5.5.5",
85
+ "eslint-plugin-security": "^4.0.0",
86
+ "globals": "^17.6.0",
87
+ "husky": "^9.1.7",
88
+ "jest": "^30.4.2",
89
+ "lint-staged": "^17.0.7",
90
+ "pino": "^10.0.0",
91
+ "pino-pretty": "^13.0.0",
92
+ "prettier": "^3.8.3",
93
+ "reflect-metadata": "^0.2.2",
94
+ "rxjs": "^7.8.0",
95
+ "supertest": "^7.2.2",
96
+ "tinybench": "^6.0.2",
97
+ "ts-jest": "^29.4.9",
98
+ "ts-node": "^10.9.2",
99
+ "tsup": "^8.5.1",
100
+ "tsx": "^4.19.2",
101
+ "typescript": "^5.9.3"
102
+ },
103
+ "keywords": [
104
+ "nestjs",
105
+ "logger",
106
+ "pino",
107
+ "json-logging",
108
+ "structured-logging",
109
+ "opentelemetry",
110
+ "observability",
111
+ "tracing",
112
+ "request-id",
113
+ "pii-redaction"
114
+ ],
115
+ "engines": {
116
+ "node": ">=24.0.0"
117
+ },
118
+ "publishConfig": {
119
+ "access": "public",
120
+ "registry": "https://registry.npmjs.org/"
121
+ },
122
+ "scripts": {
123
+ "build": "pnpm clean && tsup",
124
+ "lint": "eslint src",
125
+ "lint:fix": "eslint src --fix",
126
+ "test": "jest",
127
+ "test:cov": "jest --coverage",
128
+ "test:watch": "jest --watch",
129
+ "test:e2e": "jest --config jest.e2e.config.ts",
130
+ "test:all": "pnpm test && pnpm test:e2e",
131
+ "test:cov:all": "jest --config jest.coverage.config.ts --coverage",
132
+ "mutation": "stryker run",
133
+ "mutation:incremental": "stryker run --incremental",
134
+ "mutation:dry-run": "stryker run --dryRunOnly",
135
+ "bench": "node --expose-gc --import tsx bench/throughput.bench.ts",
136
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.server.json",
137
+ "size": "node scripts/check-size.mjs",
138
+ "clean": "rm -rf dist coverage",
139
+ "release": "pnpm publish --provenance"
140
+ }
141
+ }