@jayalfredprufrock/confetti 0.1.2 → 0.2.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/dist/index.d.cts CHANGED
@@ -1,68 +1,128 @@
1
1
  //#region src/symbols.d.ts
2
2
  declare const CONFETTI: unique symbol;
3
3
  declare const DEFAULT: unique symbol;
4
- declare const ENV_VAR: unique symbol;
4
+ declare const ENV: unique symbol;
5
5
  declare const DATA: unique symbol;
6
+ declare const TYPE: unique symbol;
6
7
  //#endregion
7
8
  //#region src/types.d.ts
8
9
  type Obj<T = unknown> = Record<string, T>;
9
10
  type Primitive = string | number | boolean | null;
10
11
  type MaybeArray<T> = T | T[];
11
- type ConfigVal = MaybeArray<Primitive> | ((context: ConfigFlatMapContext) => any) | (() => Promise<any>);
12
+ type ConfigValFn<T = unknown> = (env: string) => T;
13
+ type ConfigVal = MaybeArray<Primitive> | ConfigValFn<any>;
14
+ type TypeTag = "string" | "number" | "boolean" | "string[]" | "number[]" | "boolean[]";
15
+ type TypeMap = {
16
+ string: string;
17
+ number: number;
18
+ boolean: boolean;
19
+ "string[]": string[];
20
+ "number[]": number[];
21
+ "boolean[]": boolean[];
22
+ };
12
23
  type IsConfigValPerEnv<T> = T extends {
13
24
  [DEFAULT]: any;
14
25
  } | {
15
- [ENV_VAR]: any;
26
+ [ENV]: any;
16
27
  } | {
17
28
  [DATA]: any;
29
+ } | {
30
+ [TYPE]: any;
18
31
  } ? true : false;
19
- type ConfigValPerEnv<D extends ConfigVal = ConfigVal> = {
20
- [DEFAULT]?: D;
21
- [ENV_VAR]?: string;
22
- [DATA]?: any;
23
- } & Record<string, D>;
32
+ type ConfigValPerEnvTyped<T extends TypeTag> = {
33
+ readonly [TYPE]: T;
34
+ readonly [DEFAULT]?: TypeMap[T] | ConfigValFn<TypeMap[T]>;
35
+ readonly [ENV]?: string;
36
+ readonly [DATA]?: any;
37
+ readonly [key: string]: TypeMap[T] | ConfigValFn<TypeMap[T]>;
38
+ };
39
+ type ConfigValPerEnvFetcher = {
40
+ readonly [TYPE]?: never;
41
+ readonly [DEFAULT]?: string | ConfigValFn<string>;
42
+ readonly [ENV]?: string;
43
+ readonly [DATA]?: any;
44
+ readonly [key: string]: string | ConfigValFn<string> | undefined;
45
+ };
46
+ type ConfigValPerEnvPlain<D extends ConfigVal = ConfigVal> = {
47
+ readonly [TYPE]?: never;
48
+ readonly [DEFAULT]?: D;
49
+ readonly [ENV]?: never;
50
+ readonly [DATA]?: never;
51
+ readonly [key: string]: D;
52
+ };
53
+ type ConfigValPerEnv = ConfigValPerEnvTyped<TypeTag> | ConfigValPerEnvFetcher | ConfigValPerEnvPlain;
24
54
  type Config = {
25
55
  [key: string]: Config | ConfigVal | ConfigValPerEnv;
26
56
  };
27
- type ResolvedValue<V> = V extends ((...args: any[]) => any) ? Awaited<ReturnType<V>> : V;
28
- type ResolvedConfig<C> = { [K in keyof C]: C[K] extends Obj ? IsConfigValPerEnv<C[K]> extends true ? C[K] extends ConfigValPerEnv<infer D> ? ResolvedValue<D> : ResolvedConfig<C[K]> : ResolvedConfig<C[K]> : ResolvedValue<C[K]> };
29
- type MakeConfig<R extends Config> = (env: string) => Promise<R>;
30
- type ResolvedEnvVars<C> = { [K in keyof C]: C[K] extends ConfigValPerEnv<infer V> ? C[K][typeof ENV_VAR] extends string ? V : undefined : C[K] extends Obj ? ResolvedEnvVars<C[K]> : Awaited<C[K]> };
31
- interface ResolvedSecret {
32
- secret: string;
33
- path: string;
34
- value: unknown;
57
+ type ValidateConfig<C> = { [K in keyof C]: C[K] extends {
58
+ [TYPE]: infer T extends TypeTag;
59
+ } ? ConfigValPerEnvTyped<T> : C[K] extends {
60
+ [ENV]: any;
61
+ } | {
62
+ [DATA]: any;
63
+ } ? ConfigValPerEnvFetcher : C[K] extends {
64
+ [DEFAULT]: any;
65
+ } ? C[K] : C[K] extends Obj ? ValidateConfig<C[K]> : C[K] };
66
+ type WidenLiteral<T> = T extends boolean ? boolean : T extends number ? number : T extends string ? string : T extends readonly (infer E)[] ? WidenLiteral<E>[] : T;
67
+ type ResolvedValue<V> = V extends ((...args: any[]) => any) ? Awaited<ReturnType<V>> : WidenLiteral<V>;
68
+ type ResolvedConfig<C> = { [K in keyof C]: C[K] extends Obj ? IsConfigValPerEnv<C[K]> extends true ? ResolveNode<C[K]> : ResolvedConfig<C[K]> : ResolvedValue<C[K]> };
69
+ type IsNestedConfig<T> = T extends Obj ? (IsConfigValPerEnv<T> extends true ? false : true) : false;
70
+ type Paths<C> = C extends Obj ? { [K in keyof C & string]: IsNestedConfig<C[K]> extends true ? K | `${K}.${Paths<C[K]> & string}` : K }[keyof C & string] : never;
71
+ type SubtreePaths<C> = C extends Obj ? { [K in keyof C & string]: IsNestedConfig<C[K]> extends true ? K | `${K}.${SubtreePaths<C[K]> & string}` : never }[keyof C & string] : never;
72
+ type ResolveNode<T> = T extends Obj ? IsConfigValPerEnv<T> extends true ? T extends {
73
+ [TYPE]: infer Tag extends TypeTag;
74
+ } ? TypeMap[Tag] : T extends {
75
+ [ENV]: any;
76
+ } | {
77
+ [DATA]: any;
78
+ } ? string : T extends ConfigValPerEnvPlain<infer D> ? ResolvedValue<D> : never : ResolvedConfig<T> : ResolvedValue<T>;
79
+ type ValueAtPath<C, P extends string> = P extends `${infer Head}.${infer Rest}` ? Head extends keyof C ? ValueAtPath<C[Head], Rest> : never : P extends keyof C ? ResolveNode<C[P]> : never;
80
+ interface FetcherContext<D = unknown> {
81
+ env: string;
82
+ default?: D;
35
83
  envVar?: string;
84
+ data?: unknown;
85
+ type?: TypeTag;
36
86
  }
37
- interface ConfigFlatMapContext {
87
+ type Fetcher<D = unknown, T = unknown> = (context: FetcherContext<D>) => Promise<T | undefined>;
88
+ interface ConfigEntry {
38
89
  path: string;
39
- unresolvedValue: ConfigVal;
90
+ value?: unknown;
91
+ default?: unknown;
40
92
  envVar?: string;
41
93
  data?: unknown;
94
+ type?: TypeTag;
42
95
  }
43
96
  type Confetti<C> = {
44
97
  [CONFETTI]: "CONFETTI";
45
98
  (env: string): {
46
99
  config: C;
47
- flatMap: <T>(transform: (context: ConfigFlatMapContext) => T | T[]) => T[];
48
- resolve: () => Promise<ResolvedConfig<C>>;
49
- resolveSync: () => ResolvedConfig<C>;
50
- resolveValue: (path: string) => Promise<string>;
51
- resolveValueSync: (path: string) => string;
52
- resolveEnv: () => Promise<Obj<string>>;
100
+ get<P extends Paths<C> & string>(path: P): ValueAtPath<C, P>;
101
+ resolve<P extends Paths<C> & string>(path: P, fetcher: Fetcher): Promise<ValueAtPath<C, P>>;
102
+ entries(startPath?: SubtreePaths<C> & string): IterableIterator<[string, ConfigEntry]>;
53
103
  };
54
104
  };
55
105
  type GetConfig<T> = T extends Confetti<infer C> ? ResolvedConfig<C> : never;
56
106
  //#endregion
57
107
  //#region src/make-config.d.ts
58
- declare const makeConfig: <C extends Config>(makeConfig: (env: string) => C) => Confetti<C>;
108
+ declare const makeConfig: <const C extends Config>(input: (C & ValidateConfig<C>) | ((env: string) => C & ValidateConfig<C>)) => Confetti<C>;
59
109
  //#endregion
60
110
  //#region src/util.d.ts
61
111
  declare const isObj: (val: unknown) => val is Obj;
62
112
  declare const isConfigValPerEnv: (val: unknown) => val is ConfigValPerEnv;
113
+ declare const isNestedConfig: (val: unknown) => val is Obj;
63
114
  declare const isConfetti: (val: unknown) => val is Confetti<any>;
64
- declare const configFlatMap: <T>(env: string, obj: Obj, map: (context: ConfigFlatMapContext) => T | T[], _currentPath?: string) => T[];
65
- declare const setAtPath: (obj: Obj, path: string, value: unknown) => void;
115
+ declare const isThenable: (v: unknown) => v is PromiseLike<unknown>;
116
+ declare const getAtPath: (config: Obj, path: string) => unknown;
117
+ declare const coerceFromString: (raw: string, type: TypeTag, path: string) => unknown;
118
+ declare const buildEntry: (node: unknown, path: string, env: string) => ConfigEntry;
119
+ declare function entriesIter(config: Obj, env: string, pathPrefix?: string): IterableIterator<[string, ConfigEntry]>;
120
+ declare const invokeSync: (source: unknown, path: string, env: string) => unknown;
121
+ declare const invokeAsync: (source: unknown, env: string) => Promise<unknown>;
122
+ declare const resolveEntrySync: (entry: ConfigEntry, env: string) => unknown;
123
+ declare const resolveEntryAsync: (entry: ConfigEntry, env: string, fetcher: Fetcher) => Promise<unknown>;
124
+ declare const resolveSubtreeSync: (node: Obj, prefix: string, env: string) => Obj;
125
+ declare const resolveSubtreeAsync: (node: Obj, prefix: string, env: string, fetcher: Fetcher) => Promise<Obj>;
66
126
  //#endregion
67
- export { CONFETTI, Confetti, Config, ConfigFlatMapContext, ConfigVal, ConfigValPerEnv, DATA, DEFAULT, ENV_VAR, GetConfig, IsConfigValPerEnv, MakeConfig, MaybeArray, Obj, Primitive, ResolvedConfig, ResolvedEnvVars, ResolvedSecret, ResolvedValue, configFlatMap, isConfetti, isConfigValPerEnv, isObj, makeConfig, setAtPath };
127
+ export { CONFETTI, Confetti, Config, ConfigEntry, ConfigVal, ConfigValFn, ConfigValPerEnv, ConfigValPerEnvFetcher, ConfigValPerEnvPlain, ConfigValPerEnvTyped, DATA, DEFAULT, ENV, Fetcher, FetcherContext, GetConfig, IsConfigValPerEnv, MaybeArray, Obj, Paths, Primitive, ResolvedConfig, ResolvedValue, SubtreePaths, TYPE, TypeMap, TypeTag, ValidateConfig, ValueAtPath, buildEntry, coerceFromString, entriesIter, getAtPath, invokeAsync, invokeSync, isConfetti, isConfigValPerEnv, isNestedConfig, isObj, isThenable, makeConfig, resolveEntryAsync, resolveEntrySync, resolveSubtreeAsync, resolveSubtreeSync };
68
128
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/symbols.ts","../src/types.ts","../src/make-config.ts","../src/util.ts"],"mappings":";cAAa,QAAA;AAAA,cACA,OAAA;AAAA,cACA,OAAA;AAAA,cACA,IAAA;;;KCDD,GAAA,gBAAmB,MAAA,SAAe,CAAA;AAAA,KAElC,SAAA;AAAA,KACA,UAAA,MAAgB,CAAA,GAAI,CAAA;AAAA,KAEpB,SAAA,GACR,UAAA,CAAW,SAAA,MACT,OAAA,EAAS,oBAAA,mBACJ,OAAA;AAAA,KAEC,iBAAA,MAAuB,CAAA;EAAA,CAC5B,OAAA;AAAA;EAAA,CACA,OAAA;AAAA;EAAA,CACA,IAAA;AAAA;AAAA,KAKK,eAAA,WAA0B,SAAA,GAAY,SAAA;EAAA,CAC/C,OAAA,IAAW,CAAA;EAAA,CACX,OAAA;EAAA,CACA,IAAA;AAAA,IACC,MAAA,SAAe,CAAA;AAAA,KAEP,MAAA;EAAA,CACT,GAAA,WAAc,MAAA,GAAS,SAAA,GAAY,eAAA;AAAA;AAAA,KAG1B,aAAA,MAAmB,CAAA,cAAc,IAAA,mBAAsB,OAAA,CAAQ,UAAA,CAAW,CAAA,KAAM,CAAA;AAAA,KAEhF,cAAA,oBACE,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,GAAA,GACzB,iBAAA,CAAkB,CAAA,CAAE,CAAA,kBAClB,CAAA,CAAE,CAAA,UAAW,eAAA,YACX,aAAA,CAAc,CAAA,IACd,cAAA,CAAe,CAAA,CAAE,CAAA,KACnB,cAAA,CAAe,CAAA,CAAE,CAAA,KACnB,aAAA,CAAc,CAAA,CAAE,CAAA;AAAA,KAGV,UAAA,WAAqB,MAAA,KAAW,GAAA,aAAgB,OAAA,CAAQ,CAAA;AAAA,KAExD,eAAA,oBACE,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,eAAA,YACzB,CAAA,CAAE,CAAA,SAAU,OAAA,mBACV,CAAA,eAEF,CAAA,CAAE,CAAA,UAAW,GAAA,GACX,eAAA,CAAgB,CAAA,CAAE,CAAA,KAClB,OAAA,CAAQ,CAAA,CAAE,CAAA;AAAA,UAGD,cAAA;EACf,MAAA;EACA,IAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,UAGe,oBAAA;EACf,IAAA;EACA,eAAA,EAAiB,SAAA;EACjB,MAAA;EACA,IAAA;AAAA;AAAA,KAGU,QAAA;EAAA,CACT,QAAA;EAAA,CACA,GAAA;IACC,MAAA,EAAQ,CAAA;IACR,OAAA,MAAa,SAAA,GAAY,OAAA,EAAS,oBAAA,KAAyB,CAAA,GAAI,CAAA,OAAQ,CAAA;IACvE,OAAA,QAAe,OAAA,CAAQ,cAAA,CAAe,CAAA;IACtC,WAAA,QAAmB,cAAA,CAAe,CAAA;IAClC,YAAA,GAAe,IAAA,aAAiB,OAAA;IAChC,gBAAA,GAAmB,IAAA;IACnB,UAAA,QAAkB,OAAA,CAAQ,GAAA;EAAA;AAAA;AAAA,KAIlB,SAAA,MAAe,CAAA,SAAU,QAAA,YAAoB,cAAA,CAAe,CAAA;;;cC7E3D,UAAA,aAAwB,MAAA,EAAQ,UAAA,GAAa,GAAA,aAAgB,CAAA,KAAI,QAAA,CAAS,CAAA;;;cCD1E,KAAA,GAAS,GAAA,cAAe,GAAA,IAAO,GAAA;AAAA,cAI/B,iBAAA,GAAqB,GAAA,cAAe,GAAA,IAAO,eAAA;AAAA,cAI3C,UAAA,GAAc,GAAA,cAAe,GAAA,IAAO,QAAA;AAAA,cAIpC,aAAA,MACX,GAAA,UACA,GAAA,EAAK,GAAA,EACL,GAAA,GAAM,OAAA,EAAS,oBAAA,KAAyB,CAAA,GAAI,CAAA,IAC5C,YAAA,cACC,CAAA;AAAA,cAuCU,SAAA,GAAa,GAAA,EAAK,GAAA,EAAK,IAAA,UAAc,KAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/symbols.ts","../src/types.ts","../src/make-config.ts","../src/util.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,68 +1,128 @@
1
1
  //#region src/symbols.d.ts
2
2
  declare const CONFETTI: unique symbol;
3
3
  declare const DEFAULT: unique symbol;
4
- declare const ENV_VAR: unique symbol;
4
+ declare const ENV: unique symbol;
5
5
  declare const DATA: unique symbol;
6
+ declare const TYPE: unique symbol;
6
7
  //#endregion
7
8
  //#region src/types.d.ts
8
9
  type Obj<T = unknown> = Record<string, T>;
9
10
  type Primitive = string | number | boolean | null;
10
11
  type MaybeArray<T> = T | T[];
11
- type ConfigVal = MaybeArray<Primitive> | ((context: ConfigFlatMapContext) => any) | (() => Promise<any>);
12
+ type ConfigValFn<T = unknown> = (env: string) => T;
13
+ type ConfigVal = MaybeArray<Primitive> | ConfigValFn<any>;
14
+ type TypeTag = "string" | "number" | "boolean" | "string[]" | "number[]" | "boolean[]";
15
+ type TypeMap = {
16
+ string: string;
17
+ number: number;
18
+ boolean: boolean;
19
+ "string[]": string[];
20
+ "number[]": number[];
21
+ "boolean[]": boolean[];
22
+ };
12
23
  type IsConfigValPerEnv<T> = T extends {
13
24
  [DEFAULT]: any;
14
25
  } | {
15
- [ENV_VAR]: any;
26
+ [ENV]: any;
16
27
  } | {
17
28
  [DATA]: any;
29
+ } | {
30
+ [TYPE]: any;
18
31
  } ? true : false;
19
- type ConfigValPerEnv<D extends ConfigVal = ConfigVal> = {
20
- [DEFAULT]?: D;
21
- [ENV_VAR]?: string;
22
- [DATA]?: any;
23
- } & Record<string, D>;
32
+ type ConfigValPerEnvTyped<T extends TypeTag> = {
33
+ readonly [TYPE]: T;
34
+ readonly [DEFAULT]?: TypeMap[T] | ConfigValFn<TypeMap[T]>;
35
+ readonly [ENV]?: string;
36
+ readonly [DATA]?: any;
37
+ readonly [key: string]: TypeMap[T] | ConfigValFn<TypeMap[T]>;
38
+ };
39
+ type ConfigValPerEnvFetcher = {
40
+ readonly [TYPE]?: never;
41
+ readonly [DEFAULT]?: string | ConfigValFn<string>;
42
+ readonly [ENV]?: string;
43
+ readonly [DATA]?: any;
44
+ readonly [key: string]: string | ConfigValFn<string> | undefined;
45
+ };
46
+ type ConfigValPerEnvPlain<D extends ConfigVal = ConfigVal> = {
47
+ readonly [TYPE]?: never;
48
+ readonly [DEFAULT]?: D;
49
+ readonly [ENV]?: never;
50
+ readonly [DATA]?: never;
51
+ readonly [key: string]: D;
52
+ };
53
+ type ConfigValPerEnv = ConfigValPerEnvTyped<TypeTag> | ConfigValPerEnvFetcher | ConfigValPerEnvPlain;
24
54
  type Config = {
25
55
  [key: string]: Config | ConfigVal | ConfigValPerEnv;
26
56
  };
27
- type ResolvedValue<V> = V extends ((...args: any[]) => any) ? Awaited<ReturnType<V>> : V;
28
- type ResolvedConfig<C> = { [K in keyof C]: C[K] extends Obj ? IsConfigValPerEnv<C[K]> extends true ? C[K] extends ConfigValPerEnv<infer D> ? ResolvedValue<D> : ResolvedConfig<C[K]> : ResolvedConfig<C[K]> : ResolvedValue<C[K]> };
29
- type MakeConfig<R extends Config> = (env: string) => Promise<R>;
30
- type ResolvedEnvVars<C> = { [K in keyof C]: C[K] extends ConfigValPerEnv<infer V> ? C[K][typeof ENV_VAR] extends string ? V : undefined : C[K] extends Obj ? ResolvedEnvVars<C[K]> : Awaited<C[K]> };
31
- interface ResolvedSecret {
32
- secret: string;
33
- path: string;
34
- value: unknown;
57
+ type ValidateConfig<C> = { [K in keyof C]: C[K] extends {
58
+ [TYPE]: infer T extends TypeTag;
59
+ } ? ConfigValPerEnvTyped<T> : C[K] extends {
60
+ [ENV]: any;
61
+ } | {
62
+ [DATA]: any;
63
+ } ? ConfigValPerEnvFetcher : C[K] extends {
64
+ [DEFAULT]: any;
65
+ } ? C[K] : C[K] extends Obj ? ValidateConfig<C[K]> : C[K] };
66
+ type WidenLiteral<T> = T extends boolean ? boolean : T extends number ? number : T extends string ? string : T extends readonly (infer E)[] ? WidenLiteral<E>[] : T;
67
+ type ResolvedValue<V> = V extends ((...args: any[]) => any) ? Awaited<ReturnType<V>> : WidenLiteral<V>;
68
+ type ResolvedConfig<C> = { [K in keyof C]: C[K] extends Obj ? IsConfigValPerEnv<C[K]> extends true ? ResolveNode<C[K]> : ResolvedConfig<C[K]> : ResolvedValue<C[K]> };
69
+ type IsNestedConfig<T> = T extends Obj ? (IsConfigValPerEnv<T> extends true ? false : true) : false;
70
+ type Paths<C> = C extends Obj ? { [K in keyof C & string]: IsNestedConfig<C[K]> extends true ? K | `${K}.${Paths<C[K]> & string}` : K }[keyof C & string] : never;
71
+ type SubtreePaths<C> = C extends Obj ? { [K in keyof C & string]: IsNestedConfig<C[K]> extends true ? K | `${K}.${SubtreePaths<C[K]> & string}` : never }[keyof C & string] : never;
72
+ type ResolveNode<T> = T extends Obj ? IsConfigValPerEnv<T> extends true ? T extends {
73
+ [TYPE]: infer Tag extends TypeTag;
74
+ } ? TypeMap[Tag] : T extends {
75
+ [ENV]: any;
76
+ } | {
77
+ [DATA]: any;
78
+ } ? string : T extends ConfigValPerEnvPlain<infer D> ? ResolvedValue<D> : never : ResolvedConfig<T> : ResolvedValue<T>;
79
+ type ValueAtPath<C, P extends string> = P extends `${infer Head}.${infer Rest}` ? Head extends keyof C ? ValueAtPath<C[Head], Rest> : never : P extends keyof C ? ResolveNode<C[P]> : never;
80
+ interface FetcherContext<D = unknown> {
81
+ env: string;
82
+ default?: D;
35
83
  envVar?: string;
84
+ data?: unknown;
85
+ type?: TypeTag;
36
86
  }
37
- interface ConfigFlatMapContext {
87
+ type Fetcher<D = unknown, T = unknown> = (context: FetcherContext<D>) => Promise<T | undefined>;
88
+ interface ConfigEntry {
38
89
  path: string;
39
- unresolvedValue: ConfigVal;
90
+ value?: unknown;
91
+ default?: unknown;
40
92
  envVar?: string;
41
93
  data?: unknown;
94
+ type?: TypeTag;
42
95
  }
43
96
  type Confetti<C> = {
44
97
  [CONFETTI]: "CONFETTI";
45
98
  (env: string): {
46
99
  config: C;
47
- flatMap: <T>(transform: (context: ConfigFlatMapContext) => T | T[]) => T[];
48
- resolve: () => Promise<ResolvedConfig<C>>;
49
- resolveSync: () => ResolvedConfig<C>;
50
- resolveValue: (path: string) => Promise<string>;
51
- resolveValueSync: (path: string) => string;
52
- resolveEnv: () => Promise<Obj<string>>;
100
+ get<P extends Paths<C> & string>(path: P): ValueAtPath<C, P>;
101
+ resolve<P extends Paths<C> & string>(path: P, fetcher: Fetcher): Promise<ValueAtPath<C, P>>;
102
+ entries(startPath?: SubtreePaths<C> & string): IterableIterator<[string, ConfigEntry]>;
53
103
  };
54
104
  };
55
105
  type GetConfig<T> = T extends Confetti<infer C> ? ResolvedConfig<C> : never;
56
106
  //#endregion
57
107
  //#region src/make-config.d.ts
58
- declare const makeConfig: <C extends Config>(makeConfig: (env: string) => C) => Confetti<C>;
108
+ declare const makeConfig: <const C extends Config>(input: (C & ValidateConfig<C>) | ((env: string) => C & ValidateConfig<C>)) => Confetti<C>;
59
109
  //#endregion
60
110
  //#region src/util.d.ts
61
111
  declare const isObj: (val: unknown) => val is Obj;
62
112
  declare const isConfigValPerEnv: (val: unknown) => val is ConfigValPerEnv;
113
+ declare const isNestedConfig: (val: unknown) => val is Obj;
63
114
  declare const isConfetti: (val: unknown) => val is Confetti<any>;
64
- declare const configFlatMap: <T>(env: string, obj: Obj, map: (context: ConfigFlatMapContext) => T | T[], _currentPath?: string) => T[];
65
- declare const setAtPath: (obj: Obj, path: string, value: unknown) => void;
115
+ declare const isThenable: (v: unknown) => v is PromiseLike<unknown>;
116
+ declare const getAtPath: (config: Obj, path: string) => unknown;
117
+ declare const coerceFromString: (raw: string, type: TypeTag, path: string) => unknown;
118
+ declare const buildEntry: (node: unknown, path: string, env: string) => ConfigEntry;
119
+ declare function entriesIter(config: Obj, env: string, pathPrefix?: string): IterableIterator<[string, ConfigEntry]>;
120
+ declare const invokeSync: (source: unknown, path: string, env: string) => unknown;
121
+ declare const invokeAsync: (source: unknown, env: string) => Promise<unknown>;
122
+ declare const resolveEntrySync: (entry: ConfigEntry, env: string) => unknown;
123
+ declare const resolveEntryAsync: (entry: ConfigEntry, env: string, fetcher: Fetcher) => Promise<unknown>;
124
+ declare const resolveSubtreeSync: (node: Obj, prefix: string, env: string) => Obj;
125
+ declare const resolveSubtreeAsync: (node: Obj, prefix: string, env: string, fetcher: Fetcher) => Promise<Obj>;
66
126
  //#endregion
67
- export { CONFETTI, Confetti, Config, ConfigFlatMapContext, ConfigVal, ConfigValPerEnv, DATA, DEFAULT, ENV_VAR, GetConfig, IsConfigValPerEnv, MakeConfig, MaybeArray, Obj, Primitive, ResolvedConfig, ResolvedEnvVars, ResolvedSecret, ResolvedValue, configFlatMap, isConfetti, isConfigValPerEnv, isObj, makeConfig, setAtPath };
127
+ export { CONFETTI, Confetti, Config, ConfigEntry, ConfigVal, ConfigValFn, ConfigValPerEnv, ConfigValPerEnvFetcher, ConfigValPerEnvPlain, ConfigValPerEnvTyped, DATA, DEFAULT, ENV, Fetcher, FetcherContext, GetConfig, IsConfigValPerEnv, MaybeArray, Obj, Paths, Primitive, ResolvedConfig, ResolvedValue, SubtreePaths, TYPE, TypeMap, TypeTag, ValidateConfig, ValueAtPath, buildEntry, coerceFromString, entriesIter, getAtPath, invokeAsync, invokeSync, isConfetti, isConfigValPerEnv, isNestedConfig, isObj, isThenable, makeConfig, resolveEntryAsync, resolveEntrySync, resolveSubtreeAsync, resolveSubtreeSync };
68
128
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/symbols.ts","../src/types.ts","../src/make-config.ts","../src/util.ts"],"mappings":";cAAa,QAAA;AAAA,cACA,OAAA;AAAA,cACA,OAAA;AAAA,cACA,IAAA;;;KCDD,GAAA,gBAAmB,MAAA,SAAe,CAAA;AAAA,KAElC,SAAA;AAAA,KACA,UAAA,MAAgB,CAAA,GAAI,CAAA;AAAA,KAEpB,SAAA,GACR,UAAA,CAAW,SAAA,MACT,OAAA,EAAS,oBAAA,mBACJ,OAAA;AAAA,KAEC,iBAAA,MAAuB,CAAA;EAAA,CAC5B,OAAA;AAAA;EAAA,CACA,OAAA;AAAA;EAAA,CACA,IAAA;AAAA;AAAA,KAKK,eAAA,WAA0B,SAAA,GAAY,SAAA;EAAA,CAC/C,OAAA,IAAW,CAAA;EAAA,CACX,OAAA;EAAA,CACA,IAAA;AAAA,IACC,MAAA,SAAe,CAAA;AAAA,KAEP,MAAA;EAAA,CACT,GAAA,WAAc,MAAA,GAAS,SAAA,GAAY,eAAA;AAAA;AAAA,KAG1B,aAAA,MAAmB,CAAA,cAAc,IAAA,mBAAsB,OAAA,CAAQ,UAAA,CAAW,CAAA,KAAM,CAAA;AAAA,KAEhF,cAAA,oBACE,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,GAAA,GACzB,iBAAA,CAAkB,CAAA,CAAE,CAAA,kBAClB,CAAA,CAAE,CAAA,UAAW,eAAA,YACX,aAAA,CAAc,CAAA,IACd,cAAA,CAAe,CAAA,CAAE,CAAA,KACnB,cAAA,CAAe,CAAA,CAAE,CAAA,KACnB,aAAA,CAAc,CAAA,CAAE,CAAA;AAAA,KAGV,UAAA,WAAqB,MAAA,KAAW,GAAA,aAAgB,OAAA,CAAQ,CAAA;AAAA,KAExD,eAAA,oBACE,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,eAAA,YACzB,CAAA,CAAE,CAAA,SAAU,OAAA,mBACV,CAAA,eAEF,CAAA,CAAE,CAAA,UAAW,GAAA,GACX,eAAA,CAAgB,CAAA,CAAE,CAAA,KAClB,OAAA,CAAQ,CAAA,CAAE,CAAA;AAAA,UAGD,cAAA;EACf,MAAA;EACA,IAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,UAGe,oBAAA;EACf,IAAA;EACA,eAAA,EAAiB,SAAA;EACjB,MAAA;EACA,IAAA;AAAA;AAAA,KAGU,QAAA;EAAA,CACT,QAAA;EAAA,CACA,GAAA;IACC,MAAA,EAAQ,CAAA;IACR,OAAA,MAAa,SAAA,GAAY,OAAA,EAAS,oBAAA,KAAyB,CAAA,GAAI,CAAA,OAAQ,CAAA;IACvE,OAAA,QAAe,OAAA,CAAQ,cAAA,CAAe,CAAA;IACtC,WAAA,QAAmB,cAAA,CAAe,CAAA;IAClC,YAAA,GAAe,IAAA,aAAiB,OAAA;IAChC,gBAAA,GAAmB,IAAA;IACnB,UAAA,QAAkB,OAAA,CAAQ,GAAA;EAAA;AAAA;AAAA,KAIlB,SAAA,MAAe,CAAA,SAAU,QAAA,YAAoB,cAAA,CAAe,CAAA;;;cC7E3D,UAAA,aAAwB,MAAA,EAAQ,UAAA,GAAa,GAAA,aAAgB,CAAA,KAAI,QAAA,CAAS,CAAA;;;cCD1E,KAAA,GAAS,GAAA,cAAe,GAAA,IAAO,GAAA;AAAA,cAI/B,iBAAA,GAAqB,GAAA,cAAe,GAAA,IAAO,eAAA;AAAA,cAI3C,UAAA,GAAc,GAAA,cAAe,GAAA,IAAO,QAAA;AAAA,cAIpC,aAAA,MACX,GAAA,UACA,GAAA,EAAK,GAAA,EACL,GAAA,GAAM,OAAA,EAAS,oBAAA,KAAyB,CAAA,GAAI,CAAA,IAC5C,YAAA,cACC,CAAA;AAAA,cAuCU,SAAA,GAAa,GAAA,EAAK,GAAA,EAAK,IAAA,UAAc,KAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/symbols.ts","../src/types.ts","../src/make-config.ts","../src/util.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,121 +1,185 @@
1
1
  //#region src/symbols.ts
2
2
  const CONFETTI = Symbol.for("CONFETTI");
3
3
  const DEFAULT = Symbol.for("CONFETTI_DEFAULT");
4
- const ENV_VAR = Symbol.for("CONFETTI_ENV_VAR");
4
+ const ENV = Symbol.for("CONFETTI_ENV");
5
5
  const DATA = Symbol.for("CONFETTI_DATA");
6
+ const TYPE = Symbol.for("CONFETTI_TYPE");
6
7
  //#endregion
7
8
  //#region src/util.ts
8
9
  const isObj = (val) => {
9
10
  return val !== null && typeof val === "object" && !Array.isArray(val);
10
11
  };
11
12
  const isConfigValPerEnv = (val) => {
12
- return isObj(val) && (DEFAULT in val || DATA in val || ENV_VAR in val);
13
+ return isObj(val) && (DEFAULT in val || DATA in val || ENV in val || TYPE in val);
14
+ };
15
+ const isNestedConfig = (val) => {
16
+ return isObj(val) && !isConfigValPerEnv(val);
13
17
  };
14
18
  const isConfetti = (val) => {
15
19
  return typeof val === "function" && Object.hasOwn(val, CONFETTI);
16
20
  };
17
- const configFlatMap = (env, obj, map, _currentPath = "") => {
18
- return Object.entries(obj).flatMap(([key, value]) => {
19
- const path = `${_currentPath}${key}`;
20
- if (isObj(value)) {
21
- if (isConfigValPerEnv(value)) {
22
- let unresolvedValue;
23
- if (value[ENV_VAR] && process.env[value[ENV_VAR]] !== void 0) try {
24
- unresolvedValue = JSON.parse(process.env[value[ENV_VAR]]);
25
- } catch {
26
- unresolvedValue = process.env[value[ENV_VAR]];
27
- }
28
- else if (value[env] !== void 0) unresolvedValue = value[env];
29
- else if (value[DEFAULT] !== void 0) unresolvedValue = value[DEFAULT];
30
- if (unresolvedValue === void 0) throw new Error(`Unable to find '${env}' config value at '${path}`);
31
- return map({
32
- path,
33
- unresolvedValue,
34
- envVar: value[ENV_VAR],
35
- data: value[DATA]
36
- });
37
- }
38
- return configFlatMap(env, value, map, `${path}.`);
39
- }
40
- return map({
41
- path,
42
- unresolvedValue: value
43
- });
44
- });
21
+ const isThenable = (v) => {
22
+ return v !== null && typeof v === "object" && "then" in v && typeof v.then === "function";
45
23
  };
46
- const setAtPath = (obj, path, value) => {
24
+ const getAtPath = (config, path) => {
25
+ if (!path) return config;
47
26
  const segments = path.split(".");
48
- let objAtSeg = obj;
49
- for (let i = 0; i < segments.length; i++) {
50
- const segment = segments[i] ?? "";
51
- if (segments.length === i + 1) objAtSeg[segment] = value;
52
- else {
53
- if (!isObj(objAtSeg[segment])) objAtSeg[segment] = {};
54
- objAtSeg = objAtSeg[segment];
55
- }
27
+ let node = config;
28
+ for (const segment of segments) {
29
+ if (!isNestedConfig(node)) throw new Error(`Invalid config path '${path}'.`);
30
+ node = node[segment];
31
+ if (node === void 0) throw new Error(`Invalid config path '${path}'.`);
56
32
  }
33
+ return node;
34
+ };
35
+ const matchesType = (val, type) => {
36
+ if (type === "string") return typeof val === "string";
37
+ if (type === "number") return typeof val === "number" && !Number.isNaN(val);
38
+ if (type === "boolean") return typeof val === "boolean";
39
+ if (!Array.isArray(val)) return false;
40
+ const elem = type.slice(0, -2);
41
+ return val.every((x) => typeof x === elem);
42
+ };
43
+ const coerceFromString = (raw, type, path) => {
44
+ if (type === "string") return raw;
45
+ if (type === "number") {
46
+ if (raw === "") throw new Error(`Cannot coerce empty string to number at '${path}'.`);
47
+ const n = Number(raw);
48
+ if (Number.isNaN(n)) throw new Error(`Cannot coerce '${raw}' to number at '${path}'.`);
49
+ return n;
50
+ }
51
+ if (type === "boolean") {
52
+ if (raw === "true") return true;
53
+ if (raw === "false") return false;
54
+ throw new Error(`Cannot coerce '${raw}' to boolean at '${path}' (expected 'true' or 'false').`);
55
+ }
56
+ let parsed;
57
+ try {
58
+ parsed = JSON.parse(raw);
59
+ } catch {
60
+ throw new Error(`Cannot coerce '${raw}' to ${type} at '${path}' (invalid JSON).`);
61
+ }
62
+ if (!Array.isArray(parsed)) throw new Error(`Cannot coerce '${raw}' to ${type} at '${path}' (not an array).`);
63
+ const elem = type.slice(0, -2);
64
+ if (!parsed.every((x) => typeof x === elem)) throw new Error(`Cannot coerce '${raw}' to ${type} at '${path}' (element type mismatch).`);
65
+ return parsed;
66
+ };
67
+ const coerceFetched = (fetched, type, path) => {
68
+ if (type === void 0) {
69
+ if (typeof fetched !== "string") throw new Error(`Fetcher for '${path}' must return a string (add [TYPE] to use non-string values).`);
70
+ return fetched;
71
+ }
72
+ if (typeof fetched === "string") return coerceFromString(fetched, type, path);
73
+ if (matchesType(fetched, type)) return fetched;
74
+ throw new Error(`Fetcher for '${path}' returned value that doesn't match [TYPE] '${type}'.`);
75
+ };
76
+ const buildEntry = (node, path, env) => {
77
+ if (!isConfigValPerEnv(node)) return {
78
+ path,
79
+ value: node
80
+ };
81
+ const envVar = node[ENV];
82
+ const data = node[DATA];
83
+ const defaultVal = node[DEFAULT];
84
+ const typeTag = node[TYPE];
85
+ const entry = { path };
86
+ if (envVar && process.env[envVar] !== void 0) {
87
+ const raw = process.env[envVar];
88
+ entry.value = typeTag ? coerceFromString(raw, typeTag, path) : raw;
89
+ } else if (node[env] !== void 0) entry.value = node[env];
90
+ if (defaultVal !== void 0) entry.default = defaultVal;
91
+ if (envVar) entry.envVar = envVar;
92
+ if (data !== void 0) entry.data = data;
93
+ if (typeTag !== void 0) entry.type = typeTag;
94
+ return entry;
95
+ };
96
+ function* entriesIter(config, env, pathPrefix = "") {
97
+ for (const [key, value] of Object.entries(config)) {
98
+ const path = pathPrefix + key;
99
+ if (isNestedConfig(value)) yield* entriesIter(value, env, `${path}.`);
100
+ else yield [path, buildEntry(value, path, env)];
101
+ }
102
+ }
103
+ const invokeSync = (source, path, env) => {
104
+ if (typeof source !== "function") return source;
105
+ const result = source(env);
106
+ if (isThenable(result)) throw new Error(`Config at '${path}' requires async resolution (use resolve).`);
107
+ return result;
108
+ };
109
+ const invokeAsync = async (source, env) => {
110
+ return typeof source === "function" ? await source(env) : source;
111
+ };
112
+ const resolveEntrySync = (entry, env) => {
113
+ if ("value" in entry) return invokeSync(entry.value, entry.path, env);
114
+ if ("default" in entry) return invokeSync(entry.default, entry.path, env);
115
+ throw new Error(`Config at '${entry.path}' requires async resolution (use resolve).`);
116
+ };
117
+ const resolveEntryAsync = async (entry, env, fetcher) => {
118
+ if ("value" in entry) return invokeAsync(entry.value, env);
119
+ if (entry.envVar !== void 0 || entry.data !== void 0) {
120
+ const fetched = await fetcher({
121
+ env,
122
+ default: entry.default,
123
+ envVar: entry.envVar,
124
+ data: entry.data,
125
+ type: entry.type
126
+ });
127
+ if (fetched !== void 0) return coerceFetched(fetched, entry.type, entry.path);
128
+ }
129
+ if ("default" in entry) return invokeAsync(entry.default, env);
130
+ throw new Error(`Unable to resolve config value at '${entry.path}'.`);
131
+ };
132
+ const resolveSubtreeSync = (node, prefix, env) => {
133
+ const result = {};
134
+ for (const [key, child] of Object.entries(node)) {
135
+ const path = prefix ? `${prefix}.${key}` : key;
136
+ result[key] = isNestedConfig(child) ? resolveSubtreeSync(child, path, env) : resolveEntrySync(buildEntry(child, path, env), env);
137
+ }
138
+ return result;
139
+ };
140
+ const resolveSubtreeAsync = async (node, prefix, env, fetcher) => {
141
+ const keys = Object.keys(node);
142
+ const values = await Promise.all(keys.map((key) => {
143
+ const child = node[key];
144
+ const path = prefix ? `${prefix}.${key}` : key;
145
+ return isNestedConfig(child) ? resolveSubtreeAsync(child, path, env, fetcher) : resolveEntryAsync(buildEntry(child, path, env), env, fetcher);
146
+ }));
147
+ const result = {};
148
+ keys.forEach((key, i) => {
149
+ result[key] = values[i];
150
+ });
151
+ return result;
57
152
  };
58
153
  //#endregion
59
154
  //#region src/make-config.ts
60
- const makeConfig = (makeConfig) => {
155
+ const makeConfig = (input) => {
156
+ const factory = typeof input === "function" ? input : () => input;
61
157
  const confetti = (env) => {
62
- const config = makeConfig(env);
63
- const flatMap = (transform) => configFlatMap(env, config, transform);
64
- const contextByPath = Object.fromEntries(flatMap((context) => [[context.path, context]]));
65
- const resolveValue = async (path) => {
66
- const context = contextByPath[path];
67
- if (!context) throw new Error(`Invalid config path '${path}'.`);
68
- const { unresolvedValue } = context;
69
- const value = typeof unresolvedValue === "function" ? await unresolvedValue(context) : unresolvedValue;
70
- if (value === void 0) throw new Error(`Config value at '${path}' resolved to undefined.`);
71
- return value;
72
- };
73
- const resolveValueSync = (path) => {
74
- const context = contextByPath[path];
75
- if (!context) throw new Error(`Invalid config path '${path}'.`);
76
- const { unresolvedValue } = context;
77
- if (typeof unresolvedValue === "function") throw new Error(`Cannot resolve config value at "${path}" synchronously.`);
78
- return unresolvedValue;
79
- };
80
- const resolve = async () => {
81
- const resolvedConfig = {};
82
- const promises = Object.keys(contextByPath).map(async (path) => {
83
- return resolveValue(path).then((resolvedValue) => setAtPath(resolvedConfig, path, resolvedValue));
84
- });
85
- await Promise.all(promises);
86
- return resolvedConfig;
158
+ const config = factory(env);
159
+ const get = (path) => {
160
+ const node = getAtPath(config, path);
161
+ return isNestedConfig(node) ? resolveSubtreeSync(node, path, env) : resolveEntrySync(buildEntry(node, path, env), env);
87
162
  };
88
- const resolveSync = () => {
89
- const resolvedConfig = {};
90
- for (const path of Object.keys(contextByPath)) setAtPath(resolvedConfig, path, resolveValueSync(path));
91
- return resolvedConfig;
163
+ const resolve = async (path, fetcher) => {
164
+ const node = getAtPath(config, path);
165
+ return isNestedConfig(node) ? await resolveSubtreeAsync(node, path, env, fetcher) : await resolveEntryAsync(buildEntry(node, path, env), env, fetcher);
92
166
  };
93
- const resolveEnv = async () => {
94
- const envVars = {};
95
- const promises = Object.values(contextByPath).flatMap(async (context) => {
96
- const { envVar } = context;
97
- if (!envVar) return [];
98
- return resolveValue(context.path).then((resolvedValue) => {
99
- envVars[envVar] = JSON.stringify(resolvedValue);
100
- });
101
- });
102
- await Promise.all(promises);
103
- return envVars;
167
+ const entries = (startPath) => {
168
+ const root = startPath ? getAtPath(config, startPath) : config;
169
+ if (!isNestedConfig(root)) throw new Error(`'${startPath}' is not a config subtree.`);
170
+ return entriesIter(root, env, startPath ? `${startPath}.` : "");
104
171
  };
105
172
  return {
106
173
  config,
107
- flatMap,
108
- resolveValue,
109
- resolveValueSync,
174
+ get,
110
175
  resolve,
111
- resolveSync,
112
- resolveEnv
176
+ entries
113
177
  };
114
178
  };
115
179
  confetti[CONFETTI] = "CONFETTI";
116
180
  return confetti;
117
181
  };
118
182
  //#endregion
119
- export { CONFETTI, DATA, DEFAULT, ENV_VAR, configFlatMap, isConfetti, isConfigValPerEnv, isObj, makeConfig, setAtPath };
183
+ export { CONFETTI, DATA, DEFAULT, ENV, TYPE, buildEntry, coerceFromString, entriesIter, getAtPath, invokeAsync, invokeSync, isConfetti, isConfigValPerEnv, isNestedConfig, isObj, isThenable, makeConfig, resolveEntryAsync, resolveEntrySync, resolveSubtreeAsync, resolveSubtreeSync };
120
184
 
121
185
  //# sourceMappingURL=index.mjs.map