nope/lib/helpers/singletonMethod.ts

86 lines
2.3 KiB
TypeScript
Raw Normal View History

2020-08-25 22:11:26 +00:00
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @desc [description]
*/
const NOPE_SYMBOL = Symbol.for("nope");
const SINGLETONS_SYMBOL = Symbol.for("singletons");
2020-08-25 22:11:26 +00:00
/**
2022-01-18 07:01:50 +00:00
* Function to get a singleton. To create the singleton, the parameter *create* is used. This will be called once.
* The singleton will be stored as *global* variable and can be accessed by the identifier
2022-01-18 20:51:19 +00:00
*
2022-01-18 07:01:50 +00:00
* @author M.Karkowski
* @export
* @template T The Type of the singleton
* @param {string} identifier Identifier to access the singleton
* @param {() => T} create The Callback which is used to create the instance.
* @return An object, containing the key **instances**, where you'll find the instance and an helper function **setInstance** to redefine the instance
2020-08-25 22:11:26 +00:00
*/
2022-01-18 20:51:19 +00:00
export function getSingleton<T>(
identifier: string,
create: () => T
): {
2022-01-18 07:01:50 +00:00
instance: T;
setInstance: (value: T) => void;
} {
if (!global[NOPE_SYMBOL]) {
global[NOPE_SYMBOL] = {
singletons: {},
};
}
if (!global[NOPE_SYMBOL][SINGLETONS_SYMBOL]) {
global[NOPE_SYMBOL][SINGLETONS_SYMBOL] = {};
}
2021-12-04 07:25:26 +00:00
// Extract all
const globalSingletons = Object.getOwnPropertyNames(
global[NOPE_SYMBOL][SINGLETONS_SYMBOL]
);
2020-08-25 22:11:26 +00:00
// create a unique, global symbol name
// -----------------------------------
const IDENTIFIER_DISPATCHER_CONTAINER = identifier;
2020-08-25 22:11:26 +00:00
// check if the global object has this symbol
// add it if it does not have the symbol, yet
// ------------------------------------------
2021-12-04 07:25:26 +00:00
const hasContainer =
globalSingletons.indexOf(IDENTIFIER_DISPATCHER_CONTAINER) > -1;
2020-08-25 22:11:26 +00:00
if (!hasContainer) {
global[NOPE_SYMBOL][SINGLETONS_SYMBOL][IDENTIFIER_DISPATCHER_CONTAINER] =
create();
2020-08-25 22:11:26 +00:00
}
const ret: {
2021-12-04 07:25:26 +00:00
instance: T;
setInstance: (value: T) => void;
2020-08-25 22:11:26 +00:00
} = {
instance:
global[NOPE_SYMBOL][SINGLETONS_SYMBOL][IDENTIFIER_DISPATCHER_CONTAINER],
2020-08-25 22:11:26 +00:00
setInstance: (value: T) => {
global[NOPE_SYMBOL][SINGLETONS_SYMBOL][IDENTIFIER_DISPATCHER_CONTAINER] =
value;
2021-12-04 07:25:26 +00:00
},
};
2020-08-25 22:11:26 +00:00
// define the singleton API
// ------------------------
2021-12-04 07:25:26 +00:00
Object.defineProperty(ret, "instance", {
2020-08-25 22:11:26 +00:00
get: function () {
return global[NOPE_SYMBOL][SINGLETONS_SYMBOL][
IDENTIFIER_DISPATCHER_CONTAINER
];
2021-12-04 07:25:26 +00:00
},
2020-08-25 22:11:26 +00:00
});
// ensure the API is never changed
// -------------------------------
Object.freeze(ret);
return ret;
2021-12-04 07:25:26 +00:00
}