NestJS Enumerate loaded modules and invoke a method of the service if service extends specific class - module

I am building monitoring module for NestJS project that enumerates loaded modules and calls getStatus() method for modules that extends custom BaseService class (which has default implementation of getStatus()). I do not know what modules will be loaded, so I can not inject them in constructor() like we usually do it.
It makes no sense to create a new instance of the service, because I want to query status of running instance.
I have successfully managed to enumerate modules like so:
#Injectable()
export class StatusService extends BaseService {
constructor(readonly modulesContainer: ModulesContainer) {
super();
}
onModuleInit() {
const modules = [...this.modulesContainer.values()];
for (const module of modules) {
// get instance of service and call getStatus()
}
}
But I am struggling in finding instance of the service in module.
Please point me in the right direction.

I think this will do:
module.providers.forEach((value) => {
if (value.instance && typeof value.instance.getStatus === 'function') {
const status = value.instance.getStatus();
});

Related

What is the best way to handle Page Objects for different environments?

We have two sits to support, for an example US and Canada. Some pages are exactly the same and some have different options. How I can use page object pattern define pages for this situation and reduce the duplicates?
Let's take the Login page, For US as follows,
import { by, element, ElementFinder } from 'protractor';
export class Homepage {
public startNowButton: ElementFinder;
public signinLink: ElementFinder;
constructor() {
this.startNowButton = element(by.css('button[sso-modal="SignUp"]'));
this.signinLink = element(by.linkText('Sign in'));
}
}
For Canada, there is an additional checkbox,
export class Homepage {
public startNowButton: ElementFinder;
public signinLink: ElementFinder;
public loanPurposeRadio: string;
constructor() {
this.startNowButton = element(by.css('button[sso-modal="SignUp"]'));
this.signinLink = element(by.linkText('Sign in'));
this.loanPurposeRadio = '[ng-form="loanPurposeField"] label';
}
}
If I want to support both sites then what is the best way to model page objects this kind of situations rather creating two classes? Thanks
I am not JS expert. I did not verify the below code. I am explaining based on how i would achieve that in Java. you can modify accordingly.
I would be creating an abstract class HomePage which defines all the common functionalities for all locales. USHomePage, CAHomePage classes should extend the HomePage. Or, You can also use USHomePage as Base class HomePage and CAHomePage will extend this.
Now in the below example, you have all the functionalities of US home page & you have also added specific features of CA.
For ex:
export class CAHomepage extends HomePage {
public loanPurposeRadio: string;
constructor() {
super();
this.loanPurposeRadio = '[ng-form="loanPurposeField"] label';
}
}
Now you could maintain some of kind factory class to return specific instance of HomePage depends on the site you test.
var homePageFactory = {
"US": () => { return new HomePage() },
"CA": () => { return new CAHomePage() },
"UK": () => { return new UKHomePage() }
}
Based on the locale/country, you can access specific home page. Your tests are not tied to specific site & instead they are very generic. Depends on the site you test, they behave differently.
var lang = "US"
var homePage = homepageFactory[lang]();
homePage.login();
homePage.register();

singleton object in react native

I'm new in react native.I want store multiple small small strings to common singleton object class and want to access it from singleton object for all component. Can anyone help me singleton object implementation for react native.
Ex
Component 1 -- Login button -- >> success --> need to store userID into singleton object.
Component 2 --> get stored userID from singleton object. How can i implement it.
Here is a simple way of doing it...
export default class CommonDataManager {
static myInstance = null;
_userID = "";
/**
* #returns {CommonDataManager}
*/
static getInstance() {
if (CommonDataManager.myInstance == null) {
CommonDataManager.myInstance = new CommonDataManager();
}
return this.myInstance;
}
getUserID() {
return this._userID;
}
setUserID(id) {
this._userID = id;
}
}
And here is how to use it...
import CommonDataManager from './CommonDataManager';
// When storing data.
let commonData = CommonDataManager.getInstance();
commonData.setUserID("User1");
// When retrieving stored data.
let commonData = CommonDataManager.getInstance();
let userId = commonData.getUserID();
console.log(userId);
Hope this works out for you :)
I suggest making a static class that stores data using AsyncStorage.
You mentioned in a comment that you are already using AsyncStorage, but don't like spreading this functionality throughout your app. (i.e. try-catches all over the place, each component needing to check if a key is available, etc.) If this functionality were in a single class, it would clean up your code a lot.
Another bonus to this approach is that you could swap out the implementation pretty easily, for example, you could choose to use an in-memory object or AsyncStorage or whatever and you would only have to change this one file
NOTE: AsyncStorage is not a safe way to store sensitive information. See this question for more info on the security of AsyncStorage and alternatives.
That said, this is how I imagine a global data holder class might look:
export default class dataManager {
static storeKeyValue(key, value) {
// your choice of implementation:
// check if key is used
// wrap in try-catch
// etc.
}
static getValueForKey(key) {
// get the value out for the given key
}
// etc...
}
Then to use this class anywhere in your app, just import wherever it's needed like so:
import dataManager from 'path/to/dataManager.js';
// store value
dataManager.storeKeyValue('myKey', 'myValue');
// get value
const storedValue = dataManager.getValueForKey('myKey');
EDIT: Using Flux, Redux, or a similar technology is probably the preferred/suggested way to do this in most cases, but if you feel the Singleton pattern works best for your app then this is a good way to go. See You Might Not Need Redux
There is a workaround for this, react native packager require all the modules in the compilation phase for a generating a bundle , and after first require it generates an internal id for the module, which is from then on referenced in the whole run-time memory , so if we export an instance of a class from the file, that object will be referenced every-time whenever that file is imported .
TLDR;
Solution I :
class abc {
}
module.exports = new abc()
Solution II : I assume you want to get your strings which are static and wont change , so you can declare them as static and access them directly with class name
FYI :this works with webpack also.
I might be too late for this, but I might as well share my own implementation based on Yeshan Jay's answer.
export default class Data {
static instance = null;
_state = {};
static get inst() {
if (Data.instance == null) {
Data.instance = new Data();
}
return this.instance;
}
static get state() {
return Data.inst._state;
}
static set state(state) {
Data.inst._state = state;
}
static setState(state) {
Data.inst._state = {...Data.inst._state, ...state}
}
}
And here's how you use it. It's pretty much mimicking React Component's state behavior, so you should feel at home with little to no adjustment, without the need to frequently modify the Singleton to add new properties now and then.
import Data from './Data'
// change the whole singleton data
Data.state = { userId: "11231244", accessToken: "fa7sd87a8sdf7as" }
// change only a property
Data.setState ({ userId: "1231234" })
// get a single property directly
console.log("User Id: ", Data.state.userId)
// get a single property or more via object deconstruction
const { userId, property } = Data.state
console.log("User Id: ", userId)
TS Class Example:
export class SingletonClass
{
private static _instance: SingletonClass;
public anyMetod(_value:any):any
{
return _value;
}
public static getInstance(): SingletonClass
{
if (SingletonClass._instance == null)
{
SingletonClass._instance = new SingletonClass();
}
return this._instance;
}
constructor()
{
if(SingletonClass._instance)
{
throw new Error("Error: Instantiation failed: Use SingletonClass.getInstance() instead of new.");
}
}
}
Use:
SingletonClass.getInstance().anyMetod(1);

Is it possible to make a function or class available to all views in Aurelia?

The use case is as follows: We would like to have elements hidden or shown, based on the user's permissions.
The ideal way would be something like this:
<div if.bind="foo != bar && hasPermission('SOME_PERMISSION')"></div>
hasPermission() would in that case be a function that was automatically injected into all viewmodels.
Is that possible? I know we could use base classes for this, but we'd like to avoid that to stay as flexible as possible.
If you're willing to pay the price of a global function (global as in window), import it in your app-bootstrap file, like so:
has-permission.js
export function hasPermission(permission) {
return permission.id in user.permissions; // for example...
}
main.js
import 'has-permission';
export function configure(aurelia) {
// some bootstrapping code...
}
If the service you want to publish globally is a view, you can sidestep exposing it on the window and tell Aurelia's DI to make it available everywhere so you won't have to declare it in every dependent client.
To do so, pass its module ID in the FrameworkConfiguration#globalResources() configuration function:
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.globalResources('my-kick-ass-view', 'my-awesome-converter');
aurelia.start().then(a => a.setRoot());
}
If you have a service which deals with user permission, it can be injected in all your view-models.
export class UserPermissionService
{
hasPermission(user, permission)
{
return false;
}
}
#inject(UserPermissionService)
export class Users {
userPermissionService;
constructor(userPermissionService) {
this.userPermissionService = userPermissionService;
...
}
hasPermission(user, p)
{
return this.userPermissionService.hasPermission(user, p);
}
}
If you still don't like this, other options are:
a value converter http://aurelia.io/docs.html#/aurelia/binding/1.0.0-beta.1.2.1/doc/article/binding-value-converters
a custom attribute (similar to if it will hide the element)
http://www.foursails.co/blog/custom-attributes-part-1/
depending on what you need, both can use the UserPermissionService singleton from above
Add a .js file in your folder, with export function
ex: utility.js
export function hasPermission(permission) {
return true/false;
};
import the function in view-model
import {hasPermission} from 'utility';
export class MyClass{
constructor(){
this.hasPermission = hasPermission;
}
}
view.html
<div if.bind="foo != bar && hasPermission('SOME_PERMISSION')"></div>

Custom CustomerEndPoint Broadleaf

I am new to broadleaf. I want to create a custom customerEndPoint Class which will provide services like registering customer getting a customer details etc. I tried creating a CustomerEndpoint Class in com.mycompany.api.endpoint.customer package. Is there any other configurations to be done to access the customer urls??
Please help on this...
I solved this, Sharing it as it may be helpful for someone.
I Configured the CustomerEndPoint bean in applicationContent-rest-api.xml and annotated CustomerEndpoint as controller and just extented the BaseEndPoint.
CustomerEndpoint.java
#Controller
#Scope("singleton")
#Path("/customer/")
#Produces(value = { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
#Consumes(value = { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class CustomerEndpoint extends BaseEndpoint {
#Resource(name = "blCustomerService")
protected CustomerService customerService;
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
#GET
public CustomerWrapper getCustomer(#Context HttpServletRequest request,
#QueryParam("id") String emailId) {
CustomerWrapper customerWrapper = new CustomerWrapper();
if (emailId != null && emailId != "") {
customerWrapper.wrapDetails(
customerService.readCustomerByEmail(emailId), request);
}
return customerWrapper;
}
}
applicationContext-rest-api.xml
<bean id="customerEndpoint" class="com.mycompany.api.endpoint.customer.CustomerEndpoint"/>
It depends of whatever version are you using. If you using for example : broadleaf-3.1.X see
http://mvnrepository.com/artifact/org.broadleafcommerce/broadleaf-framework/3.1.5-GA
You could take as an example com.mycompany.api.endpoint.checkout.CheckoutEndpoint.
Into default platform there is org.broadleafcommerce.core.web.api.endpoint.customer.CustomerEndpoint but this implementation is empty.
You could extend that class and add annotation similar to com.mycompany.api.endpoint.checkout.CheckoutEndpoint also add business logic according to your needs.
There isn't some platform default implementation into platform as far as I can see int broadleaf-3.1.6-GA

Can not find model class in module application

I'm new in Zend, i had defined in my application.ini some lines to use multiple db.
resources.multidb.sitgm.adapter = "pdo_pgsql"
resources.multidb.sitgm.host = "localhost"
resources.multidb.sitgm.username = "postgres"
resources.multidb.sitgm.password = "pass"
resources.multidb.sitgm.dbname = "mydb"
resources.multidb.sitgm.isDefaultTableAdapter = true
In my APPLICATION Bootstrap i have a function:
public function _initDbRegistry()
{
$this->_application->bootstrap('multidb');
$multidb = $this->_application->getPluginResource('multidb');
Zend_Registry::set('db_sitgm', $multidb->getDb('sitgm'));
}
But when i had migrated to module squema, i have a default module, i added another DEFAULT Bootstrap.
class Default_Bootstrap extends Zend_Application_Module_Bootstrap
{
public function _initDbRegistry()
{
//Do i must add something here to access application DB conf like app bootstrap????
}
}
In this point How i can call the application config beacuse i am getting an error in my default model class which can not find it.
class Default_Model_Base {
protected $db;
public $sql="";
function __construct() {
$this->db = Zend_Registry::get("db_sitgm"); //HERE I GOT THE ERROR
$this->db->setFetchMode(Zend_Db::FETCH_OBJ);
}
}
Thanks in advance
You don't have to define the _initDbRegistry in your module bootstrap as well. You can leave it in your application Bootstrap.php