Skip to content

Commit

Permalink
Version 1.0.5 (#22) (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
siyul-park authored Sep 16, 2020
1 parent 7f9fb68 commit e5aa4aa
Show file tree
Hide file tree
Showing 11 changed files with 238 additions and 33 deletions.
138 changes: 137 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,137 @@
# conev sync
# conev-sync
Conev-sync is a synchronous version of [conev](#reference). You can save, manage and use configuration through it.

## Contents

- [Install](#install)
- [Usage](#usage)
- [ConfigBuilder](#configbuilder)
- [Config](#config)
- [Source](#source)
- [Sources](#sources)
- [JsonSource](#jsonsource)
- [Example](#example)
- [Reference](#reference)
## Install
```shell
npm install conev-sync
```

## Usage

Get ConfigBuilder from conev-sync and one or more Sources to use. In this example, the built-in JsonSource is used.

```typescript
import { ConfigBuilder, JsonSource } from 'conev-sync';
```


Then, create Sources and set up.

```typescript
const jsonSource = new JsonSource();

jsonSource
.set('basic', basic) //basic is JSON
.set('dev', dev) //dev is JSON
.set('prd', prd); //prd is JSON
```


Create ConfigBuilder and add Environment, Source.

```typescript
const builder = new ConfigBuilder();

builder
.addEnv('dev', 'basic')
.addSource(jsonSource);
```


Build configuration.

```typescript
const config = builder.build(); // This is the result of combining dev and basic.
```


Use configuration.

```typescript
config.get(); // The whole configuration created comes out
config.get('a.b.c'); // Is same as config.get().a.b.c
```



*Each of Environments and Sources are merged by [deepmerge](#reference).(What is added first has high priority)*
You can set deepmerge options as follow :

```typescript
builder.setOptions(options);
```

### ConfigBuilder

```typescript
class ConfigBuilder {
addSource(...sources: Source[]): ConfigBuilder;
addEnv(...envs: string[]): ConfigBuilder;
setOptions(options?: Options): ConfigBuilder;
build(): Config;
}
```
`ConfigBuilder` takes a configuration from the source and creates a new configuration according to the environment. `Env` and `Source` have priority. If priority is not defined, highest priority is added first.

### Config

```typescript
class Config {
constructor(sources: Source[], envs: string[], options?: Options);
sync(): Config;
get(key = ''): unknown | undefined;
}
```
`config` is a container for configuration. `config` is provided by creating a new configuration from the configuration and environment obtained from `source`.

### Source

```typescript
interface Source {
export(): Map<string, Record<string, unknown>>;
}
```
`Source` defines the source from which to get the configuration. Map is returned as the result value of `export`. The key of this map is environment and the value is the configuration when environment.

You can make custom `Source` and use that.

### Sources

```typescript
class Sources implements Source {
constructor(sources: Source[], options?: Options);
add(source: Source, priority = -1): Sources;
export(): Map<string, Record<string, unknown>>;
}
```
`Sources` defines the source by merging several sources. Use `add` to add source for new source. Map is returned as the result value of `export`. The key of this map is environment and the value is the configuration when environment.


### JsonSource

```typescript
export default class JsonSource {
constructor();
set(env: string, json: Record<string, unknown>): JsonSource;
export(): Map<string, Record<string, unknown>>;
}
```
`JsonSource` defines the source from JSON. Use `set` to add a configuration for a new environment. Map is returned as the result value of `export`. The key of this map is environment and the value is the configuration when environment.

## Example

## Reference

- [conev](https://github.com/CourseDesign/conev)
- [deepmerge](https://github.com/TehShrike/deepmerge)
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "conev-sync",
"version": "1.0.2",
"version": "1.0.5",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -24,14 +24,14 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/CourseDesign/design-system.git"
"url": "git+https://github.com/CourseDesign/conev-sync.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/CourseDesign/design-system/issues"
"url": "https://github.com/CourseDesign/conev-sync/issues"
},
"homepage": "https://github.com/CourseDesign/design-system#readme",
"homepage": "https://github.com/CourseDesign/conev-sync#readme",
"husky": {
"hooks": {
"pre-push": "npm run test",
Expand Down Expand Up @@ -83,7 +83,7 @@
"typescript": "^4.0.2"
},
"dependencies": {
"conev-sync-core": "^1.0.4",
"conev-sync-core": "^1.0.5",
"conev-sync-json-source": "^1.0.4"
}
}
2 changes: 1 addition & 1 deletion package/conev-sync-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "conev-sync-core",
"version": "1.0.4",
"version": "1.0.5",
"description": "",
"main": "dist/index.js",
"types" : "dist/index.d.ts",
Expand Down
25 changes: 25 additions & 0 deletions package/conev-sync-core/src/cache/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default class Cache<K, V> {
private readonly provider: (key: K) => V | undefined;

private readonly values: Map<K, V>;

constructor(provider: (key: K) => V | undefined) {
this.provider = provider;
this.values = new Map<K, V>();
}

refresh(): Cache<K, V> {
this.values.clear();
return this;
}

get(key: K): V | undefined {
if (!this.values.has(key)) {
const value = this.provider(key);
if (value !== undefined) {
this.values.set(key, value);
}
}
return this.values.get(key);
}
}
66 changes: 46 additions & 20 deletions package/conev-sync-core/src/config/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,24 @@ import Config from './config';
import SourceMock from '../source/source.mock';

describe('config', () => {
const source1 = new SourceMock(
new Map<string, Record<string, unknown>>([
['default', { source: '1', port: 3000, db: { type: 'postgres' } }],
['develop', { env: 'develop', port: 3001 }],
])
);

const source2 = new SourceMock(
new Map<string, Record<string, unknown>>([
[
'default',
{
source: '2',
port: 3000,
db: { port: 7070, username: 'test', type: 'mysql' },
},
],
['production', { env: 'production', port: 3002 }],
])
);
const values1 = new Map<string, Record<string, unknown>>([
['default', { source: '1', port: 3000, db: { type: 'postgres' } }],
['develop', { env: 'develop', port: 3001 }],
]);
const source1 = new SourceMock(values1);

const values2 = new Map<string, Record<string, unknown>>([
[
'default',
{
source: '2',
port: 3000,
db: { port: 7070, username: 'test', type: 'mysql' },
},
],
['production', { env: 'production', port: 3002 }],
]);
const source2 = new SourceMock(values2);

test('get', () => {
const config = new Config([source1, source2], ['default', 'develop']);
Expand All @@ -33,6 +31,34 @@ describe('config', () => {
db: { port: 7070, username: 'test', type: 'mysql' },
});
expect(config.get('source')).toEqual('2');
expect(config.get('port')).toEqual(3001);
expect(config.get('db.port')).toEqual(7070);
});

test('sync', () => {
const config = new Config([source1, source2], ['default', 'develop']);

expect(config.get()).toEqual({
source: '2',
env: 'develop',
port: 3001,
db: { port: 7070, username: 'test', type: 'mysql' },
});
expect(config.get('source')).toEqual('2');
expect(config.get('port')).toEqual(3001);
expect(config.get('db.port')).toEqual(7070);

values2.set('develop', { port: 3002 });
config.sync();

expect(config.get()).toEqual({
source: '2',
env: 'develop',
port: 3002,
db: { port: 7070, username: 'test', type: 'mysql' },
});
expect(config.get('source')).toEqual('2');
expect(config.get('port')).toEqual(3002);
expect(config.get('db.port')).toEqual(7070);
});
});
12 changes: 11 additions & 1 deletion package/conev-sync-core/src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import merge, { Options } from 'deepmerge';
import Sources from '../source/sources';
import Source from '../source/source';
import Cache from '../cache/cache';

export default class Config {
private readonly sources: Sources;
Expand All @@ -11,16 +12,21 @@ export default class Config {

private values: Record<string, unknown> | null;

private cache: Cache<string, unknown>;

constructor(sources: Source[], envs: string[], options?: Options) {
this.sources = new Sources(sources, options);
this.envs = envs;
this.options = options;
this.values = null;
this.cache = new Cache((key: string) => this.getValue(key));

this.sync();
}

sync(): Config {
this.cache.refresh();

const source = this.sources.export();
const configs = this.envs
.map((env) => source.get(env))
Expand All @@ -31,7 +37,11 @@ export default class Config {
return this;
}

get(key = ''): unknown | null {
get(key = ''): unknown | undefined {
return this.cache.get(key);
}

private getValue(key = ''): unknown | undefined {
const tokens: string[] = key.split('.').reverse();

let current: any = this.values;
Expand Down
3 changes: 2 additions & 1 deletion package/conev-sync-core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": [
"es2017",
"es2015",
"dom"
],
/* Specify library files to be included in the compilation. */
Expand Down Expand Up @@ -48,7 +49,7 @@
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a proxy. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */

/* Module Resolution Options */
Expand Down
2 changes: 1 addition & 1 deletion package/conev-sync-json-source/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a proxy. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */

/* Module Resolution Options */
Expand Down
2 changes: 1 addition & 1 deletion script/change-package.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if (key == null) {

const value = process.argv[4];
if (value == null) {
console.error('Value is undefined!');
console.error('Proxy is undefined!');
process.exit(1);
}

Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
export * from 'conev-sync-core';
export {
default,
ConfigBuilder,
Config,
Source,
Sources,
} from 'conev-sync-core';
export { default as JsonSource } from 'conev-sync-json-source';
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": [
"es2017",
"es2015",
"dom"
],
/* Specify library files to be included in the compilation. */
Expand Down Expand Up @@ -48,7 +49,7 @@
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a proxy. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */

/* Module Resolution Options */
Expand Down

0 comments on commit e5aa4aa

Please sign in to comment.