@bymax-one/nest-config 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.
- package/CHANGELOG.md +106 -0
- package/LICENSE +21 -0
- package/README.md +572 -0
- package/dist/index.cjs +34 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/internal/index.cjs +423 -0
- package/dist/internal/index.d.cts +571 -0
- package/dist/internal/index.d.ts +571 -0
- package/dist/internal/index.mjs +415 -0
- package/dist/testing/index.cjs +171 -0
- package/dist/testing/index.d.cts +88 -0
- package/dist/testing/index.d.ts +88 -0
- package/dist/testing/index.mjs +168 -0
- package/package.json +161 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { EnvShape, EnvOutput, EnvSchema } from '@bymax-one/nest-config/internal';
|
|
2
|
+
import { DynamicModule } from '@nestjs/common';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview createTestConfig: the public test-config builder of the testing
|
|
6
|
+
* subpath. It synthesizes a complete valid source from a `defineEnv` schema,
|
|
7
|
+
* overlays selective nested partial overrides onto the targeted leaves through
|
|
8
|
+
* the shared source mapping, then runs the exact production pipeline (validate,
|
|
9
|
+
* deep-freeze) so a test exercises the same code path a running app does. An
|
|
10
|
+
* override that violates a declared constraint fails through the production
|
|
11
|
+
* validation error, and the returned configuration is deeply immutable. No
|
|
12
|
+
* `process.env` is ever read.
|
|
13
|
+
* @layer Utility
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Selective nested partial overrides for a synthesized test configuration.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors the two-level `namespace.leaf` shape of the inferred configuration,
|
|
20
|
+
* with every namespace and leaf optional, so a test pins only the values it
|
|
21
|
+
* cares about and lets synthesis and schema defaults resolve the rest.
|
|
22
|
+
*
|
|
23
|
+
* @typeParam TShape - The two-level schema shape.
|
|
24
|
+
*/
|
|
25
|
+
type ConfigOverrides<TShape extends EnvShape> = {
|
|
26
|
+
readonly [Namespace in keyof EnvOutput<TShape>]?: {
|
|
27
|
+
readonly [Leaf in keyof EnvOutput<TShape>[Namespace]]?: EnvOutput<TShape>[Namespace][Leaf];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Build a validated, frozen test configuration from a schema and overrides.
|
|
32
|
+
*
|
|
33
|
+
* Synthesizes a complete constraint-compliant source, applies the selective
|
|
34
|
+
* overrides, and runs the production validation and deep-freeze pipeline, so the
|
|
35
|
+
* returned object is exactly what a running application would receive. A test
|
|
36
|
+
* never touches `process.env`, yet an override that breaks a declared constraint
|
|
37
|
+
* still throws the production {@link BymaxConfigValidationError}.
|
|
38
|
+
*
|
|
39
|
+
* @typeParam TShape - The two-level schema shape.
|
|
40
|
+
* @param schema - A schema produced by `defineEnv`.
|
|
41
|
+
* @param overrides - Optional selective nested partial overrides.
|
|
42
|
+
* @returns The validated, deep-frozen configuration typed by the schema.
|
|
43
|
+
* @throws {BymaxConfigValidationError} When an override violates a constraint.
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const config = createTestConfig(envSchema, {
|
|
47
|
+
* database: { url: 'postgres://localhost:5432/test' },
|
|
48
|
+
* });
|
|
49
|
+
* config.database.url; // typed, validated, frozen
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
declare function createTestConfig<TShape extends EnvShape>(schema: EnvSchema<TShape>, overrides?: ConfigOverrides<TShape>): Readonly<EnvOutput<TShape>>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @fileoverview configTestingModule: a thin testing wrapper that registers the
|
|
56
|
+
* production BymaxConfigModule with a fully synthesized (and optionally
|
|
57
|
+
* overridden) source. It delegates to `BymaxConfigModule.forRoot`, so a Nest
|
|
58
|
+
* `TestingModule` graph exercises the exact production registration path, the
|
|
59
|
+
* same validation, freezing, and provider wiring an application boots with,
|
|
60
|
+
* without touching `process.env`. This is the module-shaped counterpart to
|
|
61
|
+
* `createTestConfig`.
|
|
62
|
+
* @layer Module
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Build an importable testing module preconfigured with a synthesized source.
|
|
67
|
+
*
|
|
68
|
+
* Synthesizes a complete valid source for the schema, applies the selective
|
|
69
|
+
* overrides, and registers the production {@link BymaxConfigModule} with it, so
|
|
70
|
+
* the returned module provides and exports the frozen `BYMAX_CONFIG` and the
|
|
71
|
+
* typed `ConfigService` exactly as in production. Import it into a Nest
|
|
72
|
+
* `TestingModule` to inject configuration without a process environment.
|
|
73
|
+
*
|
|
74
|
+
* @typeParam TShape - The two-level schema shape.
|
|
75
|
+
* @param schema - A schema produced by `defineEnv`.
|
|
76
|
+
* @param overrides - Optional selective nested partial overrides.
|
|
77
|
+
* @returns A dynamic module registered through the production `forRoot` path.
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const moduleRef = await Test.createTestingModule({
|
|
81
|
+
* imports: [configTestingModule(envSchema, { server: { port: 0 } })],
|
|
82
|
+
* providers: [InvoiceService],
|
|
83
|
+
* }).compile();
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare function configTestingModule<TShape extends EnvShape>(schema: EnvSchema<TShape>, overrides?: ConfigOverrides<TShape>): DynamicModule;
|
|
87
|
+
|
|
88
|
+
export { configTestingModule, createTestConfig };
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createValidatedConfig, BymaxConfigModule, resolveSourceNames } from '@bymax-one/nest-config/internal';
|
|
2
|
+
|
|
3
|
+
// src/testing/create-test-config.ts
|
|
4
|
+
var FILLER_CHARACTER = "a";
|
|
5
|
+
var PLACEHOLDER_URL = "https://placeholder.local";
|
|
6
|
+
var PLACEHOLDER_EMAIL_DOMAIN = "@placeholder.local";
|
|
7
|
+
var DEFAULT_NUMBER = 1;
|
|
8
|
+
var DEFAULT_STRING_LENGTH = 1;
|
|
9
|
+
var PLACEHOLDER_BOOLEAN = "true";
|
|
10
|
+
function readDef(leaf) {
|
|
11
|
+
return leaf._zod.def;
|
|
12
|
+
}
|
|
13
|
+
function checksOf(def) {
|
|
14
|
+
return def.checks ?? [];
|
|
15
|
+
}
|
|
16
|
+
function readStringLengths(def) {
|
|
17
|
+
let min = 0;
|
|
18
|
+
let max = Number.POSITIVE_INFINITY;
|
|
19
|
+
let exact;
|
|
20
|
+
for (const wrapper of checksOf(def)) {
|
|
21
|
+
const check = wrapper._zod.def;
|
|
22
|
+
if (check.check === "min_length") min = check.minimum;
|
|
23
|
+
if (check.check === "max_length") max = check.maximum;
|
|
24
|
+
if (check.check === "length_equals") exact = check.length;
|
|
25
|
+
}
|
|
26
|
+
return exact === void 0 ? { min, max } : { min, max, exact };
|
|
27
|
+
}
|
|
28
|
+
var URL_PREFIX = "http://";
|
|
29
|
+
var EMAIL_SUFFIX = "@a.lo";
|
|
30
|
+
function clampLength(preferred, min, max) {
|
|
31
|
+
return Math.min(Math.max(preferred, min), max);
|
|
32
|
+
}
|
|
33
|
+
function urlOfLength(target) {
|
|
34
|
+
const hostFill = Math.max(target - URL_PREFIX.length, 1);
|
|
35
|
+
return `${URL_PREFIX}${FILLER_CHARACTER.repeat(hostFill)}`;
|
|
36
|
+
}
|
|
37
|
+
function emailOfLength(target) {
|
|
38
|
+
const localFill = Math.max(target - EMAIL_SUFFIX.length, 1);
|
|
39
|
+
return `${FILLER_CHARACTER.repeat(localFill)}${EMAIL_SUFFIX}`;
|
|
40
|
+
}
|
|
41
|
+
function synthesizeUrl(lengths) {
|
|
42
|
+
if (lengths.exact === void 0 && PLACEHOLDER_URL.length >= lengths.min && PLACEHOLDER_URL.length <= lengths.max) {
|
|
43
|
+
return PLACEHOLDER_URL;
|
|
44
|
+
}
|
|
45
|
+
return urlOfLength(lengths.exact ?? clampLength(PLACEHOLDER_URL.length, lengths.min, lengths.max));
|
|
46
|
+
}
|
|
47
|
+
function synthesizeEmail(lengths) {
|
|
48
|
+
const canonical = `${FILLER_CHARACTER}${PLACEHOLDER_EMAIL_DOMAIN}`;
|
|
49
|
+
if (lengths.exact === void 0 && canonical.length >= lengths.min && canonical.length <= lengths.max) {
|
|
50
|
+
return canonical;
|
|
51
|
+
}
|
|
52
|
+
return emailOfLength(lengths.exact ?? clampLength(canonical.length, lengths.min, lengths.max));
|
|
53
|
+
}
|
|
54
|
+
function synthesizePlainString(lengths) {
|
|
55
|
+
if (lengths.exact !== void 0) return FILLER_CHARACTER.repeat(lengths.exact);
|
|
56
|
+
const target = Math.max(lengths.min, DEFAULT_STRING_LENGTH);
|
|
57
|
+
const bounded = target > lengths.max ? lengths.max : target;
|
|
58
|
+
return FILLER_CHARACTER.repeat(bounded);
|
|
59
|
+
}
|
|
60
|
+
function synthesizeString(def) {
|
|
61
|
+
const lengths = readStringLengths(def);
|
|
62
|
+
if (def.format === "url") return synthesizeUrl(lengths);
|
|
63
|
+
if (def.format === "email") return synthesizeEmail(lengths);
|
|
64
|
+
return synthesizePlainString(lengths);
|
|
65
|
+
}
|
|
66
|
+
function selectNumber(bounds) {
|
|
67
|
+
const { lower, upper, integer } = bounds;
|
|
68
|
+
if (lower !== void 0 && upper !== void 0) {
|
|
69
|
+
if (integer) {
|
|
70
|
+
const lo = bounds.lowerExclusive ? Math.floor(lower) + 1 : Math.ceil(lower);
|
|
71
|
+
const hi = bounds.upperExclusive ? Math.ceil(upper) - 1 : Math.floor(upper);
|
|
72
|
+
return Math.floor((lo + hi) / 2);
|
|
73
|
+
}
|
|
74
|
+
return (lower + upper) / 2;
|
|
75
|
+
}
|
|
76
|
+
if (lower !== void 0) return bounds.lowerExclusive ? lower + (integer ? 1 : 0.5) : lower;
|
|
77
|
+
if (upper !== void 0) return bounds.upperExclusive ? upper - (integer ? 1 : 0.5) : upper;
|
|
78
|
+
return DEFAULT_NUMBER;
|
|
79
|
+
}
|
|
80
|
+
function synthesizeNumber(def) {
|
|
81
|
+
const bounds = { lowerExclusive: false, upperExclusive: false, integer: false };
|
|
82
|
+
for (const wrapper of checksOf(def)) {
|
|
83
|
+
const check = wrapper._zod.def;
|
|
84
|
+
if (check.check === "greater_than") {
|
|
85
|
+
bounds.lower = check.value;
|
|
86
|
+
bounds.lowerExclusive = check.inclusive !== true;
|
|
87
|
+
}
|
|
88
|
+
if (check.check === "less_than") {
|
|
89
|
+
bounds.upper = check.value;
|
|
90
|
+
bounds.upperExclusive = check.inclusive !== true;
|
|
91
|
+
}
|
|
92
|
+
if (check.check === "number_format") bounds.integer = true;
|
|
93
|
+
}
|
|
94
|
+
return String(selectNumber(bounds));
|
|
95
|
+
}
|
|
96
|
+
function synthesizeEnum(def) {
|
|
97
|
+
const [first] = Object.values(def.entries);
|
|
98
|
+
return String(first);
|
|
99
|
+
}
|
|
100
|
+
function synthesizeLeaf(leaf) {
|
|
101
|
+
const def = readDef(leaf);
|
|
102
|
+
switch (def.type) {
|
|
103
|
+
case "default":
|
|
104
|
+
case "optional":
|
|
105
|
+
return void 0;
|
|
106
|
+
case "nullable":
|
|
107
|
+
return synthesizeLeaf(def.innerType);
|
|
108
|
+
case "string":
|
|
109
|
+
return synthesizeString(def);
|
|
110
|
+
case "number":
|
|
111
|
+
return synthesizeNumber(def);
|
|
112
|
+
case "boolean":
|
|
113
|
+
return PLACEHOLDER_BOOLEAN;
|
|
114
|
+
case "enum":
|
|
115
|
+
return synthesizeEnum(def);
|
|
116
|
+
default:
|
|
117
|
+
return FILLER_CHARACTER;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function synthesizePlaceholderSource(schema) {
|
|
121
|
+
const valueByPath = /* @__PURE__ */ new Map();
|
|
122
|
+
for (const [namespace, namespaceSchema] of Object.entries(schema.shape)) {
|
|
123
|
+
for (const [leafKey, leafSchema] of Object.entries(namespaceSchema.shape)) {
|
|
124
|
+
const value = synthesizeLeaf(leafSchema);
|
|
125
|
+
if (value !== void 0) valueByPath.set(`${namespace}.${leafKey}`, value);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const source = /* @__PURE__ */ Object.create(null);
|
|
129
|
+
for (const binding of resolveSourceNames(schema)) {
|
|
130
|
+
const value = valueByPath.get(binding.path);
|
|
131
|
+
if (value !== void 0) source[binding.variable] = value;
|
|
132
|
+
}
|
|
133
|
+
return source;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/testing/create-test-config.ts
|
|
137
|
+
function flattenOverrides(overrides) {
|
|
138
|
+
const flat = /* @__PURE__ */ new Map();
|
|
139
|
+
for (const [namespace, leaves] of Object.entries(overrides)) {
|
|
140
|
+
for (const [leaf, value] of Object.entries(leaves)) {
|
|
141
|
+
flat.set(`${namespace}.${leaf}`, value);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return flat;
|
|
145
|
+
}
|
|
146
|
+
function applyOverrides(schema, base, overrides) {
|
|
147
|
+
const flat = flattenOverrides(overrides ?? {});
|
|
148
|
+
const entries = new Map(Object.entries(base));
|
|
149
|
+
for (const binding of resolveSourceNames(schema)) {
|
|
150
|
+
const value = flat.get(binding.path);
|
|
151
|
+
if (value !== void 0) entries.set(binding.variable, String(value));
|
|
152
|
+
}
|
|
153
|
+
const source = /* @__PURE__ */ Object.create(null);
|
|
154
|
+
for (const [variable, value] of entries) source[variable] = value;
|
|
155
|
+
return source;
|
|
156
|
+
}
|
|
157
|
+
function buildTestSource(schema, overrides) {
|
|
158
|
+
return applyOverrides(schema, synthesizePlaceholderSource(schema), overrides);
|
|
159
|
+
}
|
|
160
|
+
function createTestConfig(schema, overrides) {
|
|
161
|
+
return createValidatedConfig({ schema, source: buildTestSource(schema, overrides) });
|
|
162
|
+
}
|
|
163
|
+
function configTestingModule(schema, overrides) {
|
|
164
|
+
const source = buildTestSource(schema, overrides);
|
|
165
|
+
return BymaxConfigModule.forRoot({ schema, source });
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { configTestingModule, createTestConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bymax-one/nest-config",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Typed and validated environment configuration entry point for NestJS 11 applications, built on Zod v4.",
|
|
5
|
+
"author": "Bymax One <support@bymax.one>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/bymaxone/nest-config#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/bymaxone/nest-config.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/bymaxone/nest-config/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
|
+
"import": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.mjs"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./dist/index.d.cts",
|
|
31
|
+
"default": "./dist/index.cjs"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"./testing": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/testing/index.d.ts",
|
|
37
|
+
"default": "./dist/testing/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/testing/index.d.cts",
|
|
41
|
+
"default": "./dist/testing/index.cjs"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"./internal": {
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./dist/internal/index.d.ts",
|
|
47
|
+
"default": "./dist/internal/index.mjs"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./dist/internal/index.d.cts",
|
|
51
|
+
"default": "./dist/internal/index.cjs"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"./package.json": "./package.json"
|
|
55
|
+
},
|
|
56
|
+
"lint-staged": {
|
|
57
|
+
"*.{ts,tsx,js,mjs,cjs}": [
|
|
58
|
+
"eslint --fix",
|
|
59
|
+
"prettier --write"
|
|
60
|
+
],
|
|
61
|
+
"*.{json,md,yml,yaml}": [
|
|
62
|
+
"prettier --write"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {},
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"@nestjs/common": "^11.0.16",
|
|
68
|
+
"@nestjs/core": "^11.1.18",
|
|
69
|
+
"reflect-metadata": "^0.2.0",
|
|
70
|
+
"zod": "^4.0.0"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
74
|
+
"@commitlint/cli": "^21.0.2",
|
|
75
|
+
"@commitlint/config-conventional": "^21.0.2",
|
|
76
|
+
"@eslint/js": "^9.39.4",
|
|
77
|
+
"@nestjs/common": "^11.1.20",
|
|
78
|
+
"@nestjs/core": "^11.1.20",
|
|
79
|
+
"@nestjs/platform-express": "^11.1.20",
|
|
80
|
+
"@nestjs/testing": "^11.1.20",
|
|
81
|
+
"@stryker-mutator/core": "^9",
|
|
82
|
+
"@stryker-mutator/jest-runner": "^9",
|
|
83
|
+
"@stryker-mutator/typescript-checker": "^9",
|
|
84
|
+
"@types/express": "^5.0.6",
|
|
85
|
+
"@types/jest": "^30.0.0",
|
|
86
|
+
"@types/node": "^25",
|
|
87
|
+
"@typescript-eslint/eslint-plugin": "^8.59.3",
|
|
88
|
+
"@typescript-eslint/parser": "^8.59.3",
|
|
89
|
+
"eslint": "^9.39.4",
|
|
90
|
+
"eslint-config-prettier": "^10.1.8",
|
|
91
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
92
|
+
"eslint-plugin-import": "^2.32.0",
|
|
93
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
94
|
+
"eslint-plugin-security": "^4.0.0",
|
|
95
|
+
"globals": "^17.6.0",
|
|
96
|
+
"husky": "^9.1.7",
|
|
97
|
+
"jest": "^30.4.2",
|
|
98
|
+
"lint-staged": "^17.0.7",
|
|
99
|
+
"prettier": "^3.8.3",
|
|
100
|
+
"reflect-metadata": "^0.2.2",
|
|
101
|
+
"ts-jest": "^29.4.9",
|
|
102
|
+
"ts-node": "^10.9.2",
|
|
103
|
+
"tsup": "^8.5.1",
|
|
104
|
+
"typescript": "^5.9.3",
|
|
105
|
+
"zod": "^4.0.0"
|
|
106
|
+
},
|
|
107
|
+
"keywords": [
|
|
108
|
+
"nestjs",
|
|
109
|
+
"config",
|
|
110
|
+
"environment",
|
|
111
|
+
"env",
|
|
112
|
+
"zod",
|
|
113
|
+
"validation",
|
|
114
|
+
"typed-config",
|
|
115
|
+
"dependency-injection",
|
|
116
|
+
"fail-fast",
|
|
117
|
+
"configuration"
|
|
118
|
+
],
|
|
119
|
+
"engines": {
|
|
120
|
+
"node": ">=24.0.0"
|
|
121
|
+
},
|
|
122
|
+
"publishConfig": {
|
|
123
|
+
"access": "public",
|
|
124
|
+
"provenance": true,
|
|
125
|
+
"registry": "https://registry.npmjs.org/"
|
|
126
|
+
},
|
|
127
|
+
"main": "./dist/index.cjs",
|
|
128
|
+
"module": "./dist/index.mjs",
|
|
129
|
+
"types": "./dist/index.d.cts",
|
|
130
|
+
"typesVersions": {
|
|
131
|
+
"*": {
|
|
132
|
+
"testing": [
|
|
133
|
+
"./dist/testing/index.d.cts"
|
|
134
|
+
],
|
|
135
|
+
"internal": [
|
|
136
|
+
"./dist/internal/index.d.cts"
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"scripts": {
|
|
141
|
+
"build": "pnpm clean && tsup",
|
|
142
|
+
"check:exports": "attw --pack . --profile strict",
|
|
143
|
+
"check:published": "node scripts/check-published-surface.mjs",
|
|
144
|
+
"check:runtime": "node scripts/check-consumer-runtime.mjs",
|
|
145
|
+
"clean": "node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"",
|
|
146
|
+
"dogfood": "node scripts/dogfood-smoke-test.mjs",
|
|
147
|
+
"lint": "eslint src",
|
|
148
|
+
"lint:fix": "eslint src --fix",
|
|
149
|
+
"mutation": "stryker run",
|
|
150
|
+
"mutation:dry-run": "stryker run --dryRunOnly",
|
|
151
|
+
"mutation:incremental": "stryker run --incremental",
|
|
152
|
+
"release": "npm publish --provenance --access public",
|
|
153
|
+
"size": "node scripts/check-size.mjs",
|
|
154
|
+
"test": "jest",
|
|
155
|
+
"test:cov": "jest --coverage",
|
|
156
|
+
"test:cov:all": "jest --config jest.coverage.config.ts --coverage",
|
|
157
|
+
"test:e2e": "jest --config jest.e2e.config.ts",
|
|
158
|
+
"test:watch": "jest --watch",
|
|
159
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.build.json"
|
|
160
|
+
}
|
|
161
|
+
}
|