@ima/core
Version:
IMA.js framework for isomorphic javascript application
124 lines (123 loc) • 3.96 kB
JavaScript
/**
* Namespace creation, manipulation and traversal utility. This utility is used
* to create semi-global shared namespaces for registering references to
* interfaces, classes and constants of the application to provide access to
* each other more easily than by using the ES6 import/export mechanism.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
Namespace: function() {
return Namespace;
},
getNamespace: function() {
return getNamespace;
},
ns: function() {
return ns;
}
});
class Namespace {
/**
* Initializes the namespace provider.
*
* This is a private constructor, you should use the exported `ns`
* instance to create and use namespaces (see the examples).
*
* @private
* @example
* import { ns } from '@ima/core';
* ns.namespace('ima.core');
* ns.has('ima.core');
*/ /**
* Verifies that the specified path in namespace exists, creates it if it
* does not, and returns the value at the specified path in the namespace.
*
* The method recursively creates all path parts in the namespaces as empty
* plain objects for all path parts that do not exist yet, including the
* last one. This means, that if called with a non-existing namespace path
* as an argument, the return value will be the last created namespace
* object.
*
* @param path The namespace path.
* @return The value at the specified path in the namespace.
*/ namespace(path) {
const levels = this.#resolvePathLevels(path);
// eslint-disable-next-line @typescript-eslint/no-this-alias
let self = this;
for (const levelName of levels){
if (!Object.prototype.hasOwnProperty.call(self, levelName)) {
self[levelName] = {};
}
self = self[levelName];
}
return self;
}
/**
* Verifies that the specified namespace path point to an existing
* namespace or terminal value.
*
* @param path The namespace path to test.
* @return `true` if the namespace or terminal value exists
* at the specified path.
*/ has(path) {
let hasPath;
try {
hasPath = this.get(path) !== undefined;
} catch (e) {
hasPath = false;
}
return hasPath;
}
/**
* Return value for the specified namespace path point or undefined if path is not type of string
*
* @param path The namespace path to get.
* @return The value at the specified path in the namespace or undefined for any non-string path
*/ get(path) {
const levels = this.#resolvePathLevels(path);
// eslint-disable-next-line @typescript-eslint/no-this-alias
let self = this;
for (const level of levels){
if (!self[level]) {
return undefined;
}
self = self[level];
}
return self;
}
/**
* Set value for the specified namespace path point.
*
* @param path The namespace path to set.
* @param value
*/ set(path, value) {
const levels = this.#resolvePathLevels(path);
const lastKey = levels.pop();
const namespace = this.namespace(levels.join('.'));
namespace[lastKey] = value;
}
/**
* Resolve path levels from string
*
* @param path The namespace path.
* @param array of levels or undefined for not valid path
*/ #resolvePathLevels(path) {
if (!path || typeof path !== 'string') {
throw Error('namespace.get: path is not type of string');
}
return path.split('.');
}
}
const ns = new Namespace();
function getNamespace() {
return ns;
}
//# sourceMappingURL=Namespace.js.map