Skip to content

Commit

Permalink
Merge branch 'release/0.8.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
allohamora committed Sep 6, 2023
2 parents 59cdc1a + c337949 commit 45d992a
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 41 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [0.8.0](https://github.com/allohamora/config-manager/compare/0.6.0...0.8.0) (2023-09-06)

### Features

- add rest to envRecord ([2d57b5d](https://github.com/allohamora/config-manager/commit/2d57b5d4e9ce2555cafd5b302ce0b4195c1b4a83))
- add return types and remove unnecessary as casting ([642ccde](https://github.com/allohamora/config-manager/commit/642ccde036efe3cdad46edf114588c8c2f323378))
- improve defaultFor response types ([7726b0f](https://github.com/allohamora/config-manager/commit/7726b0f2bf3bebd616042cbd557a32da1f88a135))
- improve defaultFor with rest return value ([304530d](https://github.com/allohamora/config-manager/commit/304530d2106ac0575fe06cc8a532be48e441d924))
- improve EnvPicker types ([4893b92](https://github.com/allohamora/config-manager/commit/4893b925313bbe50a6b4d7bdc4c616fbe5dd4e16))
- improve orThrow methods typing ([d7f7590](https://github.com/allohamora/config-manager/commit/d7f7590e3ee04eef31edeb028752105056982346))
- remove env.manager cache ([def7154](https://github.com/allohamora/config-manager/commit/def7154dad588b12c7c44f35e2c823e87ed36211))

## [0.7.0](https://github.com/allohamora/config-manager/compare/0.6.0...0.7.0) (2023-07-27)

### Features
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@allohamora/config-manager",
"version": "0.7.0",
"version": "0.8.0",
"description": "config manager",
"main": "./dist/index.cjs",
"exports": {
Expand Down
46 changes: 21 additions & 25 deletions src/env/env.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ interface Options<NodeEnv, Env> {
}

export class EnvManager<NodeEnv extends string, Config extends BaseConfig = BaseConfig> extends Manager<Config> {
private nodeEnv: string;
private cache = new Map<keyof Config, EnvPicker<NodeEnv, string | undefined>>();
private nodeEnv: NodeEnv;

constructor({
getEnv = () => process.env as Config,
Expand All @@ -19,7 +18,7 @@ export class EnvManager<NodeEnv extends string, Config extends BaseConfig = Base
this.nodeEnv = getNodeEnv();
}

private getEnvValue<Key extends keyof Config>(key: Key) {
private getEnvValue<Key extends keyof Config>(key: Key): Config[Key] | undefined {
const value = this.source[key];

if (value === null || value === undefined || value.trim() === '') {
Expand All @@ -29,8 +28,8 @@ export class EnvManager<NodeEnv extends string, Config extends BaseConfig = Base
return value;
}

private getKeyOrThrow<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>) {
const key: Key | undefined = envRecord[this.nodeEnv as NodeEnv] ?? envRecord.rest;
private getKeyOrThrow<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>): Key {
const key = envRecord[this.nodeEnv] ?? envRecord.rest;

if (!key) {
throw new Error(`key is not found empty in nodeEnv: ${this.nodeEnv}`);
Expand All @@ -39,45 +38,42 @@ export class EnvManager<NodeEnv extends string, Config extends BaseConfig = Base
return key;
}

public pick<Key extends keyof Config>(key: Key) {
if (!this.cache.has(key)) {
this.cache.set(
key,
new EnvPicker(this.getEnvValue(key), this.nodeEnv) as EnvPicker<NodeEnv, Config[Key] | undefined>,
);
}

return this.cache.get(key) as EnvPicker<NodeEnv, Config[Key] | undefined>;
public pick<Key extends keyof Config>(key: Key): EnvPicker<NodeEnv, Config[Key] | undefined> {
return new EnvPicker(this.getEnvValue(key), this.nodeEnv);
}

public pickOrThrow<Key extends keyof Config>(key: Key) {
public pickOrThrow<Key extends keyof Config>(key: Key): EnvPicker<NodeEnv, NonNullable<Config[Key]>> {
const value = this.source[key];

if (value === null || value === undefined || value.trim() === '') {
throw new Error(`key: ${key.toString()} is empty`);
}

return this.pick(key) as EnvPicker<NodeEnv, NonNullable<Config[Key]>>;
return new EnvPicker(value, this.nodeEnv);
}

public pickFor<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>) {
const key: Key | undefined = envRecord[this.nodeEnv as NodeEnv] ?? envRecord.rest;
public pickFor<Key extends keyof Config>(
envRecord: EnvRecord<NodeEnv, Key>,
): EnvPicker<NodeEnv, Config[Key] | undefined> {
const key = envRecord[this.nodeEnv] ?? envRecord.rest;

if (!key) {
return new EnvPicker(undefined, this.nodeEnv) as EnvPicker<NodeEnv, undefined>;
return new EnvPicker(undefined, this.nodeEnv);
}

return this.pick(key) as EnvPicker<NodeEnv, Config[Key] | undefined>;
return this.pick(key);
}

public pickForOrThrow<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>) {
public pickForOrThrow<Key extends keyof Config>(
envRecord: EnvRecord<NodeEnv, Key>,
): EnvPicker<NodeEnv, NonNullable<Config[Key]>> {
const key = this.getKeyOrThrow(envRecord);

return this.pickOrThrow(key);
}

public getFor<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>) {
const key: Key | undefined = envRecord[this.nodeEnv as NodeEnv] ?? envRecord.rest;
public getFor<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>): Config[Key] | undefined {
const key = envRecord[this.nodeEnv] ?? envRecord.rest;

if (!key) {
return;
Expand All @@ -86,8 +82,8 @@ export class EnvManager<NodeEnv extends string, Config extends BaseConfig = Base
return this.get(key);
}

public getForOrThrow<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>) {
const key: Key | undefined = this.getKeyOrThrow(envRecord);
public getForOrThrow<Key extends keyof Config>(envRecord: EnvRecord<NodeEnv, Key>): Config[Key] {
const key = this.getKeyOrThrow(envRecord);

return this.getOrThrow(key);
}
Expand Down
30 changes: 19 additions & 11 deletions src/env/env.picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ type MoveOptional<Type, Value> = Type extends null
export type BaseConfig = Record<string, string | undefined>;
export type EnvRecord<NodeEnv extends string, Value> = Partial<Record<NodeEnv | 'rest', Value>>;

export type DefaultForResponse<NodeEnv extends string, State, NewState, EnvOptions> = EnvOptions extends {
rest: NewState;
}
? EnvPicker<NodeEnv, NonNullable<State> | EnvOptions[keyof EnvOptions] | EnvOptions['rest']>
: EnvPicker<NodeEnv, State | NewState>;

export const wrapInEnvPickers = <NodeEnv extends string, Config extends BaseConfig>(
config: Config,
nodeEnv: NodeEnv,
Expand All @@ -25,35 +31,37 @@ export const wrapInEnvPickers = <NodeEnv extends string, Config extends BaseConf
export class EnvPicker<NodeEnv extends string, State> {
constructor(private state: State, private nodeEnv: NodeEnv) {}

public default(newState: State) {
public default<NewState extends State>(newState: NewState): EnvPicker<NodeEnv, NewState | NonNullable<State>> {
this.state ??= newState;

return this as unknown as EnvPicker<NodeEnv, NonNullable<State>>;
return this as EnvPicker<NodeEnv, NewState | NonNullable<State>>;
}

public defaultFor<E extends EnvRecord<NodeEnv, State>>(envRecord: E) {
public defaultFor<NewState extends State, EnvOptions extends EnvRecord<NodeEnv, NewState>>(
envRecord: EnvOptions,
): DefaultForResponse<NodeEnv, State, NewState, EnvOptions> {
this.state ??= (envRecord[this.nodeEnv] ?? envRecord.rest) as State;

return this as unknown as E extends { rest: State }
? EnvPicker<NodeEnv, NonNullable<State>>
: EnvPicker<NodeEnv, State>;
return this as unknown as DefaultForResponse<NodeEnv, State, NewState, EnvOptions>;
}

public map<Result>(mapper: (state: State) => Result) {
public map<NewState>(mapper: (state: State) => NewState): EnvPicker<NodeEnv, NewState> {
this.state = mapper(this.state) as unknown as State;

return this as unknown as EnvPicker<NodeEnv, Result>;
return this as unknown as EnvPicker<NodeEnv, NewState>;
}

public mapIfExists<Result>(mapper: (state: NonNullable<State>) => Result) {
public mapIfExists<NewState>(
mapper: (state: NonNullable<State>) => NewState,
): EnvPicker<NodeEnv, MoveOptional<State, NewState>> {
if (this.state !== null && this.state !== undefined) {
this.state = mapper(this.state as NonNullable<State>) as unknown as State;
}

return this as unknown as EnvPicker<NodeEnv, MoveOptional<State, Result>>;
return this as unknown as EnvPicker<NodeEnv, MoveOptional<State, NewState>>;
}

public value() {
public value(): State {
return this.state;
}
}
4 changes: 2 additions & 2 deletions src/utils/manager.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ export class Manager<Source extends Record<string, unknown>> {
this.source = getSource();
}

public get<Key extends keyof Source>(key: Key) {
public get<Key extends keyof Source>(key: Key): Source[Key] | undefined {
return this.source[key];
}

public getOrThrow<Key extends keyof Source>(key: Key) {
public getOrThrow<Key extends keyof Source>(key: Key): Source[Key] {
const value = this.source[key];

if (value === null || value === undefined) {
Expand Down

0 comments on commit 45d992a

Please sign in to comment.