diff --git a/README.md b/README.md index 3bf1072..5017d79 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ TypeConf supports different storage backends for configuration values: #### Browser only: -* **withDOMNode(id: string)** DOM element with encoded `value` attribute +* **withDOMNode(id: string, attribute?: string)** DOM element with encoded `content` attribute Backends are queried for existing values in the reverse order that they were added. For example: @@ -124,12 +124,12 @@ conf.getObject('object') === { a: 'a', b: { bb: 'bb' } }; **Node.js only.** Use a configuration file as a source. JSON and YAML (requires [js-yaml](https://www.npmjs.com/package/js-yaml)) are supported. -### withDOMNode(id: string): TypeConf +### withDOMNode(id: string, attribute?: string): TypeConf -**Browser only.** Use a DOM element with a `value` attribute as a source. The value must be a Base64-encoded JSON string. For example: +**Browser only.** Use a DOM element as a source. The configuration must be a Base64-encoded JSON string in an attribute of the element (default: `content`). For example: ```html - + ``` ### set(key: string, value: any): TypeConf diff --git a/package.json b/package.json index 7d40b79..50e1427 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typeconf", "version": "0.6.1", "description": "A typesafe hierarchical configuration manager for Node.js and the browser.", - "browser": "dist/TypeConf.js", + "browser": "dist/TypeConfBrowser.js", "main": "dist/TypeConfNode.js", "types": "./dist/TypeConfNode.d.ts", "repository": "https://github.com/mfellner/typeconf", diff --git a/src/TypeConf.ts b/src/TypeConf.ts index f1bfb80..888b16b 100644 --- a/src/TypeConf.ts +++ b/src/TypeConf.ts @@ -68,10 +68,11 @@ export interface TypeConf { * * Browser only. * - * @param id ID attribute of the DOM element. + * @param id ID attribute value of the DOM element. + * @param attribute Content attribute name of the DOM element (default: 'content'). * @return This TypeConf instance. */ - withDOMNode(id: string): TypeConf; + withDOMNode(id: string, attribute?: string): TypeConf; /** * Set an override value. diff --git a/src/TypeConfBrowser.ts b/src/TypeConfBrowser.ts index c28bfa7..466c883 100644 --- a/src/TypeConfBrowser.ts +++ b/src/TypeConfBrowser.ts @@ -4,12 +4,12 @@ import TypeConfBase from './TypeConfBase'; import { createStore, ObjectSupplier } from './util'; export default class TypeConfBrowser extends TypeConfBase { - public withDOMNode(id: string): TypeConf { + public withDOMNode(id: string, attribute: string = 'content'): TypeConf { const element = document.getElementById(id); - if (!element || !element.hasAttribute('value')) { + if (!element || !element.hasAttribute(attribute)) { return this; } - const encodedString = element.getAttribute('value'); + const encodedString = element.getAttribute(attribute); if (!encodedString) { return this; } @@ -17,7 +17,7 @@ export default class TypeConfBrowser extends TypeConfBase { try { storage = JSON.parse(atob(encodedString)); } catch (e) { - throw new StoreError(`cannot read value of DOM node ${id}`, e); + throw new StoreError(`cannot read attribute ${attribute} of DOM node ${id}`, e); } const store = createStore(new ObjectSupplier(storage)); this.addStore(store, `__DOM_${id}__`); diff --git a/src/TypeConfNode.ts b/src/TypeConfNode.ts index 89afc6e..a896416 100644 --- a/src/TypeConfNode.ts +++ b/src/TypeConfNode.ts @@ -61,8 +61,11 @@ export default class TypeConfNode extends TypeConfBase { get(name: string) { const envName = getEnvName(name); const result = process.env[envName]; - if (result !== undefined) return result; - return aggregateContainerValues(process.env, envName, separator, camelCase); + if (typeof result !== 'undefined') return result; + const aggregate = aggregateContainerValues(process.env, envName, separator, camelCase); + if (Object.keys(aggregate).length > 0) { + return aggregate; + } }, aggregate() { // We can only find relevant environment variables if a prefix is specified. diff --git a/test/TypeConfBrowser.test.ts b/test/TypeConfBrowser.test.ts index 50674a7..3f6fe93 100644 --- a/test/TypeConfBrowser.test.ts +++ b/test/TypeConfBrowser.test.ts @@ -13,7 +13,7 @@ describe('TypeConfBrowser', () => { const storage = { number: 42 }; const element = document.createElement('meta'); element.setAttribute('id', 'typeconf'); - element.setAttribute('value', btoa(JSON.stringify(storage))); + element.setAttribute('content', btoa(JSON.stringify(storage))); document.head.appendChild(element); const conf = new TypeConfBrowser().withDOMNode('typeconf'); @@ -31,7 +31,7 @@ describe('TypeConfBrowser', () => { test('TypeConfBrowser.getString with DOM node with empty value attribute', () => { const element = document.createElement('meta'); element.setAttribute('id', 'typeconf'); - element.setAttribute('value', ''); + element.setAttribute('content', ''); document.head.appendChild(element); expect(new TypeConfBrowser().withDOMNode('typeconf')).toBeInstanceOf(TypeConfBrowser); @@ -40,7 +40,7 @@ describe('TypeConfBrowser', () => { test('TypeConfBrowser.getString with DOM node should throw', () => { const element = document.createElement('meta'); element.setAttribute('id', 'typeconf'); - element.setAttribute('value', 'invalid'); + element.setAttribute('content', 'invalid'); document.head.appendChild(element); expect(() => new TypeConfBrowser().withDOMNode('typeconf')).toThrowError(StoreError); diff --git a/test/TypeConfNode.test.ts b/test/TypeConfNode.test.ts index 4be63e2..0e122dd 100644 --- a/test/TypeConfNode.test.ts +++ b/test/TypeConfNode.test.ts @@ -83,6 +83,11 @@ describe('TypeConfNode', () => { expect(conf.getBoolean('object')).toEqual(true); }); + test('conf.get with empty env', () => { + const conf = new TypeConfNode().withEnv(); + expect(conf.get('test')).toBeUndefined(); + }); + test('conf.getObject withFile and YAML file', () => { const conf = new TypeConfNode().withFile(path.resolve(__dirname, 'conf.yaml')); expect(conf.getObject('object')).toEqual({ string: 'string' });