zcb 0.0.7 → 0.0.8
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/README.md +60 -11
- package/package.json +1 -1
- package/src/__testUtils__/configReader.ts +7 -0
- package/src/cli.ts +3 -3
- package/src/createConfigBuilder.ts +6 -5
- package/src/createConfigParser.ts +16 -0
- package/src/createConfigReader.test.ts +9 -13
- package/src/createConfigReader.ts +4 -7
- package/src/index.ts +1 -0
- package/src/transformers/cloneNonEnumerableValues.ts +2 -2
- package/src/transformers/removeDisabledSlices.ts +7 -2
- package/src/transformers/runExperiments.ts +24 -0
- package/src/transformers/setupExperiments.ts +10 -6
- package/src/types.ts +30 -6
- package/src/utils/{importValidateWriteConfig.ts → importValidateTransformWriteConfig.ts} +7 -6
- package/src/utils/{writeConfig.ts → transformWriteConfig.ts} +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ npm install zcb
|
|
|
23
23
|
* [Create config builder](#create-config-builder)
|
|
24
24
|
* [Transform config builder](#transform-config-builder)
|
|
25
25
|
* [Create config reader](#create-config-reader)
|
|
26
|
+
* [Use config reader](#use-config-reader)
|
|
26
27
|
|
|
27
28
|
### Create schema
|
|
28
29
|
|
|
@@ -31,11 +32,13 @@ Create the schema for your configuration like in the example below.
|
|
|
31
32
|
```ts
|
|
32
33
|
// ./schema.ts
|
|
33
34
|
import { z } from 'zod';
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
import {
|
|
36
|
+
countryCodes,
|
|
37
|
+
countryNames,
|
|
38
|
+
distanceUnits,
|
|
39
|
+
languageCodes,
|
|
40
|
+
timezones,
|
|
41
|
+
} from 'zcb';
|
|
39
42
|
|
|
40
43
|
export const baseSectionSchema = z.object({
|
|
41
44
|
name: z.string(),
|
|
@@ -90,7 +93,7 @@ export type ConfigType = z.infer<typeof configSchema>;
|
|
|
90
93
|
|
|
91
94
|
### Create config builder
|
|
92
95
|
|
|
93
|
-
Then use the schema and its types to create a config builder and build out your configuration like in the example below. The config builder comes with method autocompletion and value type validation. It is important to default export the config builder.
|
|
96
|
+
Then use the schema and its types to create a config builder and build out your configuration like in the example below. The config builder comes with method autocompletion and value type validation. It is important to default export the config builder as this is what the cli build/watch scripts are expecting when they import the config builder.
|
|
94
97
|
|
|
95
98
|
```ts
|
|
96
99
|
// ./configBuilder.ts
|
|
@@ -280,17 +283,63 @@ export default {
|
|
|
280
283
|
} as const;
|
|
281
284
|
```
|
|
282
285
|
|
|
286
|
+
#### cli API
|
|
287
|
+
|
|
288
|
+
* `zcb build <input-file> <output-file>`
|
|
289
|
+
|
|
290
|
+
```sh
|
|
291
|
+
Write config from a config builder
|
|
292
|
+
|
|
293
|
+
Positionals:
|
|
294
|
+
input-file The relative path to the config builder root file
|
|
295
|
+
[string] [required]
|
|
296
|
+
output-file The relative path to the output config file [string] [required]
|
|
297
|
+
|
|
298
|
+
Options:
|
|
299
|
+
--version Show version number [boolean]
|
|
300
|
+
--help Show help [boolean]
|
|
301
|
+
--experiments-callback-file The relative path to the experiment callback file
|
|
302
|
+
[string]
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
* `zcb watch <input-file> <output-file>`
|
|
306
|
+
|
|
307
|
+
```sh
|
|
308
|
+
Watch a config builder and write config
|
|
309
|
+
|
|
310
|
+
Positionals:
|
|
311
|
+
input-file The relative path to the config builder root file
|
|
312
|
+
[string] [required]
|
|
313
|
+
output-file The relative path to the output config file [string] [required]
|
|
314
|
+
|
|
315
|
+
Options:
|
|
316
|
+
--version Show version number [boolean]
|
|
317
|
+
--help Show help [boolean]
|
|
318
|
+
--experiments-callback-file The relative path to the experiment callback file
|
|
319
|
+
[string]
|
|
320
|
+
```
|
|
321
|
+
|
|
283
322
|
### Create config reader
|
|
284
323
|
|
|
285
|
-
Then use the autogenerated config to create a config reader that you can access config values with. The
|
|
324
|
+
Then use the autogenerated config to create a config reader that you can access config values with. The autogenerated config will always be a default import.
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
// ./configReader.ts
|
|
328
|
+
import { createConfigParser, createConfigReader } from 'zcb';
|
|
329
|
+
import builtConfig from './builtConfig.ts';
|
|
330
|
+
|
|
331
|
+
export default () => createConfigReader(builtConfig);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Use config reader
|
|
335
|
+
|
|
336
|
+
Then import the config reader into the file in which you want access to config values. The config reader comes with config path autocomplete and return value preview.
|
|
286
337
|
|
|
287
338
|
```ts
|
|
288
|
-
import
|
|
289
|
-
import { createConfigReader } from 'zcb';
|
|
339
|
+
import configReader from './configReader.ts';
|
|
290
340
|
|
|
291
|
-
const reader = createConfigReader(builtConfig);
|
|
292
341
|
// scope config path autocompletion and validation
|
|
293
|
-
const scopedReader =
|
|
342
|
+
const scopedReader = configReader.scope('pages.contactDetails')
|
|
294
343
|
.scope('sections.1.sections')
|
|
295
344
|
.scope('0');
|
|
296
345
|
// reader config path autocompletion and validation
|
package/package.json
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createConfigParser } from '../createConfigParser.ts';
|
|
2
|
+
import { createConfigReader } from '../createConfigReader.ts';
|
|
3
|
+
import buildConfig from './builtConfig.ts';
|
|
4
|
+
|
|
5
|
+
const config = await createConfigParser(buildConfig);
|
|
6
|
+
|
|
7
|
+
export const createReader = () => createConfigReader(config);
|
package/src/cli.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { watchFile } from 'node:fs';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import shelljs from 'shelljs';
|
|
4
4
|
import yargs from 'yargs';
|
|
5
|
-
import {
|
|
5
|
+
import { importValidateTransformWriteConfig } from './utils/importValidateTransformWriteConfig.ts';
|
|
6
6
|
|
|
7
7
|
export enum Commands {
|
|
8
8
|
BUILD = 'build',
|
|
@@ -38,7 +38,7 @@ export const cli = () => {
|
|
|
38
38
|
watchFile(resolve(process.cwd(), argv['input-file']), () => {
|
|
39
39
|
shelljs.echo('zcd watch => file change detected');
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
importValidateTransformWriteConfig(
|
|
42
42
|
argv['input-file'],
|
|
43
43
|
argv['output-file'],
|
|
44
44
|
Commands.WATCH,
|
|
@@ -54,7 +54,7 @@ export const cli = () => {
|
|
|
54
54
|
argv => {
|
|
55
55
|
shelljs.echo(`zcd build => building file: ${argv['input-file']}`);
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
importValidateTransformWriteConfig(
|
|
58
58
|
argv['input-file'],
|
|
59
59
|
argv['output-file'],
|
|
60
60
|
Commands.BUILD,
|
|
@@ -2,6 +2,7 @@ import { type JSONSchema7 } from 'json-schema';
|
|
|
2
2
|
import { type ZodError, type z } from 'zod';
|
|
3
3
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
4
4
|
import { cloneNonEnumerableValues } from './transformers/cloneNonEnumerableValues.ts';
|
|
5
|
+
import { NonEmumeralProperties } from './types.ts';
|
|
5
6
|
import { arrayHasInvalidDefaults } from './utils/arrayHasInvalidDefaults.ts';
|
|
6
7
|
import { isDerivedValueCallback } from './utils/isDerivedValueCallback.ts';
|
|
7
8
|
import { isInvalidPropertyOverride } from './utils/isInvalidPropertyOverride.ts';
|
|
@@ -53,7 +54,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
53
54
|
|
|
54
55
|
let config = initialValues as Config;
|
|
55
56
|
|
|
56
|
-
Object.defineProperty(config,
|
|
57
|
+
Object.defineProperty(config, NonEmumeralProperties.ZCB, {
|
|
57
58
|
configurable: false,
|
|
58
59
|
enumerable: false,
|
|
59
60
|
value: true,
|
|
@@ -63,7 +64,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
63
64
|
|
|
64
65
|
const configBuilder = {
|
|
65
66
|
disable: () => {
|
|
66
|
-
Object.defineProperty(config,
|
|
67
|
+
Object.defineProperty(config, NonEmumeralProperties.DISABLED, {
|
|
67
68
|
configurable: false,
|
|
68
69
|
enumerable: false,
|
|
69
70
|
value: true,
|
|
@@ -80,7 +81,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
80
81
|
}
|
|
81
82
|
},
|
|
82
83
|
experiment: (key: string) => {
|
|
83
|
-
Object.defineProperty(config,
|
|
84
|
+
Object.defineProperty(config, NonEmumeralProperties.EXPERIMENT, {
|
|
84
85
|
configurable: false,
|
|
85
86
|
enumerable: false,
|
|
86
87
|
value: key,
|
|
@@ -97,7 +98,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
97
98
|
const values = configBuilder.values();
|
|
98
99
|
config = {} as Config;
|
|
99
100
|
|
|
100
|
-
Object.defineProperty(config,
|
|
101
|
+
Object.defineProperty(config, NonEmumeralProperties.ZCB, {
|
|
101
102
|
configurable: false,
|
|
102
103
|
enumerable: false,
|
|
103
104
|
value: true,
|
|
@@ -129,7 +130,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
129
130
|
},
|
|
130
131
|
} as unknown as ConfigBuilder;
|
|
131
132
|
|
|
132
|
-
Object.defineProperty(configBuilder,
|
|
133
|
+
Object.defineProperty(configBuilder, NonEmumeralProperties.CALLBACKS, {
|
|
133
134
|
configurable: false,
|
|
134
135
|
enumerable: false,
|
|
135
136
|
value: callbacks,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { runExperiments } from './transformers/runExperiments.ts';
|
|
2
|
+
import type { ConfigParserOptions, TransformConfigHandler } from './types.ts';
|
|
3
|
+
import { transformConfig } from './utils/transformConfig.ts';
|
|
4
|
+
|
|
5
|
+
export const createConfigParser = async <Config extends object>(
|
|
6
|
+
config: Config,
|
|
7
|
+
{ experimentsCallback }: ConfigParserOptions = {}
|
|
8
|
+
) => {
|
|
9
|
+
const handlers: TransformConfigHandler[] = [];
|
|
10
|
+
|
|
11
|
+
if (experimentsCallback) {
|
|
12
|
+
handlers.push(runExperiments(experimentsCallback));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return handlers.length > 0 ? await transformConfig(config, handlers) : config;
|
|
16
|
+
};
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createReader } from './__testUtils__/configReader.ts';
|
|
2
2
|
|
|
3
3
|
describe('createConfigReader', () => {
|
|
4
4
|
describe('when a user accesses a known property', () => {
|
|
5
|
-
it('should return the correct value',
|
|
6
|
-
const
|
|
7
|
-
const reader = createConfigReader(config);
|
|
5
|
+
it('should return the correct value', () => {
|
|
6
|
+
const reader = createReader();
|
|
8
7
|
const value = reader('countryCode');
|
|
9
8
|
expect(value).toBe('GB');
|
|
10
9
|
});
|
|
11
10
|
});
|
|
12
11
|
|
|
13
12
|
describe('when a user accesses a known nested property', () => {
|
|
14
|
-
it('should return the correct value',
|
|
15
|
-
const
|
|
16
|
-
const reader = createConfigReader(config);
|
|
13
|
+
it('should return the correct value', () => {
|
|
14
|
+
const reader = createReader();
|
|
17
15
|
const value = reader('pages.contactDetails.name');
|
|
18
16
|
expect(value).toBe('contactDetails');
|
|
19
17
|
});
|
|
@@ -21,9 +19,8 @@ describe('createConfigReader', () => {
|
|
|
21
19
|
|
|
22
20
|
describe('when the reader is scoped', () => {
|
|
23
21
|
describe('when a user accesses a known property', () => {
|
|
24
|
-
it('should return the correct value',
|
|
25
|
-
const
|
|
26
|
-
const reader = createConfigReader(config);
|
|
22
|
+
it('should return the correct value', () => {
|
|
23
|
+
const reader = createReader();
|
|
27
24
|
const scopedReader = reader.scope('pages.contactDetails');
|
|
28
25
|
const value = scopedReader('name');
|
|
29
26
|
expect(value).toBe('contactDetails');
|
|
@@ -33,9 +30,8 @@ describe('createConfigReader', () => {
|
|
|
33
30
|
|
|
34
31
|
describe('when the reader is scoped multiple times', () => {
|
|
35
32
|
describe('when a user accesses a known property', () => {
|
|
36
|
-
it('should return the correct value',
|
|
37
|
-
const
|
|
38
|
-
const reader = createConfigReader(config);
|
|
33
|
+
it('should return the correct value', () => {
|
|
34
|
+
const reader = createReader();
|
|
39
35
|
const scopedReader = reader.scope('pages.contactDetails').scope('sections.1.sections').scope('0');
|
|
40
36
|
const value = scopedReader('name');
|
|
41
37
|
expect(value).toBe('main');
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import get from 'lodash/get.js';
|
|
2
|
-
import type { Get
|
|
3
|
-
import type {
|
|
2
|
+
import type { Get } from 'type-fest';
|
|
3
|
+
import type { Path, Scope } from './types.ts';
|
|
4
4
|
|
|
5
5
|
export const createConfigReader = <Config extends object>(config: Config) => {
|
|
6
|
-
const configReader = <
|
|
7
|
-
|
|
8
|
-
configReader.scope = <Scope extends Join<Paths<Config>, '.'>>(scope: Scope) =>
|
|
9
|
-
createConfigReader(get(config, scope) as Get<Config, Scope>);
|
|
10
|
-
|
|
6
|
+
const configReader = <P extends Path<Config>>(path: P) => get(config, path);
|
|
7
|
+
configReader.scope = <S extends Scope<Config>>(scope: S) => createConfigReader(get(config, scope) as Get<Config, S>);
|
|
11
8
|
return configReader;
|
|
12
9
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AnyRecord, NonEmumeralProperties, type TransformConfigHandlerSync } from '../types.ts';
|
|
2
2
|
|
|
3
|
-
const NON_ENUMERABLE_KEYS = new Set(
|
|
3
|
+
const NON_ENUMERABLE_KEYS = new Set(Object.values(NonEmumeralProperties));
|
|
4
4
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
export const cloneNonEnumerableValues: TransformConfigHandlerSync = <Config extends AnyRecord>(
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AnyRecord,
|
|
3
|
+
NonEmumeralProperties,
|
|
4
|
+
TransformConfigHandlerAction,
|
|
5
|
+
type TransformConfigHandlerSync,
|
|
6
|
+
} from '../types.ts';
|
|
2
7
|
|
|
3
8
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
9
|
export const removeDisabledSlices: TransformConfigHandlerSync = <Config extends AnyRecord>(
|
|
5
10
|
clone: Config,
|
|
6
11
|
config: Config
|
|
7
12
|
) => {
|
|
8
|
-
if (
|
|
13
|
+
if (NonEmumeralProperties.DISABLED in config) {
|
|
9
14
|
return {
|
|
10
15
|
action: TransformConfigHandlerAction.DELETE_NODE,
|
|
11
16
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AnyRecord,
|
|
3
|
+
type Buckets,
|
|
4
|
+
NonEmumeralProperties,
|
|
5
|
+
type RunExperimentsCallback,
|
|
6
|
+
type TransformConfigHandler,
|
|
7
|
+
} from '../types.ts';
|
|
8
|
+
|
|
9
|
+
export const runExperiments =
|
|
10
|
+
(callback: RunExperimentsCallback): TransformConfigHandler =>
|
|
11
|
+
async <Config extends AnyRecord>(clone: Config, config: Config) => {
|
|
12
|
+
if (NonEmumeralProperties.EXPERIMENT in config && typeof config.__experiment === 'object') {
|
|
13
|
+
const { buckets, id } = config.__experiment as { buckets: Buckets<Config>; id: string };
|
|
14
|
+
const bucket = await callback(id);
|
|
15
|
+
|
|
16
|
+
if (bucket && bucket in buckets && buckets[bucket]) {
|
|
17
|
+
return buckets[bucket]!;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
value: clone,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
type AnyRecord,
|
|
3
|
+
NonEmumeralProperties,
|
|
4
|
+
type SetupExperimentsCallback,
|
|
5
|
+
type TransformConfigHandler,
|
|
6
|
+
} from '../types.ts';
|
|
2
7
|
|
|
3
8
|
export const setupExperiments =
|
|
4
|
-
(callback:
|
|
9
|
+
(callback: SetupExperimentsCallback): TransformConfigHandler =>
|
|
5
10
|
async <Config extends AnyRecord>(clone: Config, config: Config) => {
|
|
6
|
-
if (
|
|
7
|
-
const
|
|
11
|
+
if (NonEmumeralProperties.EXPERIMENT in config && typeof config.__experiment === 'string') {
|
|
12
|
+
const buckets = await callback(config.__experiment, clone, config);
|
|
8
13
|
|
|
9
14
|
// @ts-expect-error private property
|
|
10
15
|
clone.__experiment = {
|
|
11
|
-
|
|
16
|
+
buckets,
|
|
12
17
|
id: config.__experiment,
|
|
13
|
-
value,
|
|
14
18
|
};
|
|
15
19
|
|
|
16
20
|
return {
|
package/src/types.ts
CHANGED
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
import type { List } from 'ts-toolbelt';
|
|
2
|
-
import type { Includes } from 'type-fest';
|
|
2
|
+
import type { Includes, Join } from 'type-fest';
|
|
3
3
|
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
5
|
export type AnyRecord = Record<string, any>;
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export type Buckets<Config extends AnyRecord> = Record<string, Experiment<Config>>;
|
|
8
|
+
|
|
9
|
+
export interface ConfigParserOptions {
|
|
10
|
+
experimentsCallback?: RunExperimentsCallback;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Experiment<Config extends AnyRecord> {
|
|
14
|
+
action?: TransformConfigHandlerAction;
|
|
15
|
+
value?: Config;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export enum NonEmumeralProperties {
|
|
19
|
+
CALLBACKS = '__callbacks',
|
|
20
|
+
DISABLED = '__disabled',
|
|
21
|
+
EXPERIMENT = '__experiment',
|
|
22
|
+
ZCB = '__zcb',
|
|
10
23
|
}
|
|
11
24
|
|
|
12
|
-
export type
|
|
25
|
+
export type Path<Config extends object> = Join<Leaves<Config>, '.'>;
|
|
26
|
+
|
|
27
|
+
export type RunExperimentsCallback = (id: string) => Promise<string>;
|
|
28
|
+
|
|
29
|
+
export type Scope<Config extends object> = Join<Paths<Config>, '.'>;
|
|
30
|
+
|
|
31
|
+
export type SetupExperimentsCallback = <Config extends AnyRecord>(
|
|
13
32
|
id: string,
|
|
14
33
|
clone: Config,
|
|
15
34
|
config: Config
|
|
16
|
-
) => Promise<
|
|
35
|
+
) => Promise<Buckets<Config>>;
|
|
17
36
|
|
|
18
37
|
export type TransformConfigHandler = <Config extends AnyRecord>(
|
|
19
38
|
clone: Config,
|
|
@@ -35,6 +54,11 @@ export interface TransformConfigHandlerReturnType<Config extends AnyRecord> {
|
|
|
35
54
|
value?: Config;
|
|
36
55
|
}
|
|
37
56
|
|
|
57
|
+
export interface WriteConfigOptions {
|
|
58
|
+
experimentsCallback?: SetupExperimentsCallback;
|
|
59
|
+
outputFile: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
38
62
|
export type Leaves<T, Path extends string[] = []> = T extends string
|
|
39
63
|
? Path
|
|
40
64
|
: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import shelljs from 'shelljs';
|
|
3
3
|
import type { Commands } from '../cli.ts';
|
|
4
|
-
import type {
|
|
5
|
-
import {
|
|
4
|
+
import type { SetupExperimentsCallback } from '../types.ts';
|
|
5
|
+
import { transformWriteConfig } from './transformWriteConfig.ts';
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const importValidateTransformWriteConfig = (
|
|
8
8
|
inputFile: string,
|
|
9
9
|
outputFile: string,
|
|
10
10
|
command: Commands,
|
|
@@ -19,6 +19,7 @@ export const importValidateWriteConfig = (
|
|
|
19
19
|
}) => {
|
|
20
20
|
if (!configBuilder.validate()) {
|
|
21
21
|
shelljs.echo(`zcd ${command} => invalid config`);
|
|
22
|
+
shelljs.echo(`zcd ${command} => config values:\n${configBuilder.toJson()}\n`);
|
|
22
23
|
shelljs.echo(`zcd ${command} => errors:\n${JSON.stringify(configBuilder.errors(), undefined, 2)}\n`);
|
|
23
24
|
shelljs.exit(1);
|
|
24
25
|
}
|
|
@@ -28,8 +29,8 @@ export const importValidateWriteConfig = (
|
|
|
28
29
|
|
|
29
30
|
if (experimentCallbackFile) {
|
|
30
31
|
import(resolve(process.cwd(), experimentCallbackFile))
|
|
31
|
-
.then(({ default: experimentsCallback }: { default:
|
|
32
|
-
void
|
|
32
|
+
.then(({ default: experimentsCallback }: { default: SetupExperimentsCallback }) => {
|
|
33
|
+
void transformWriteConfig(configBuilder.values(), { experimentsCallback, outputFile });
|
|
33
34
|
})
|
|
34
35
|
.catch((error: unknown) => {
|
|
35
36
|
if (error instanceof Error) {
|
|
@@ -44,7 +45,7 @@ export const importValidateWriteConfig = (
|
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
void
|
|
48
|
+
void transformWriteConfig(configBuilder.values(), { outputFile });
|
|
48
49
|
}
|
|
49
50
|
)
|
|
50
51
|
.catch((error: unknown) => {
|
|
@@ -9,7 +9,7 @@ import { setupExperiments } from '../transformers/setupExperiments.ts';
|
|
|
9
9
|
import type { TransformConfigHandler, WriteConfigOptions } from '../types.ts';
|
|
10
10
|
import { transformConfig } from './transformConfig.ts';
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const transformWriteConfig = async <Config extends object>(
|
|
13
13
|
config: Config,
|
|
14
14
|
{ experimentsCallback, outputFile }: WriteConfigOptions
|
|
15
15
|
) => {
|