How to override the needle API when creating a blueprint? - jhipster

I'm actually working on a .Net Core blueprint for JHipster. The file tree is not the same as for the Java version and the needles don't work anymore. I need to override the needles in order to modify the paths in it.
How to make the generator using the blueprint's needles and not the original ones ?
I tried to extends the needles and to modify the paths in it but they are not taken into consideration. The JHipster's needles are always used. I also tried to see how the others blueprints as ViewJS and Kotlin manage the problem but no one override the needles. I also tried to find a documentation on the needle API but there is none.
For example, the client's entities are no longer generated at the same path. So I tried to override the needle-client-angular.js.
const chalk = require('chalk');
const _ = require('lodash');
const needleClientAngular = require('generator-jhipster/generators/client/needle-api/needle-client-angular');
const constants = require('generator-jhipster/generators/generator-constants');
const dotnetConstants = require('../../generator-dotnetcore-constants');
const jhipsterUtils = require('generator-jhipster/generators/utils');
const toPascalCase = require('to-pascal-case');
const CLIENT_MAIN_SRC_DIR = `${dotnetConstants.SERVER_SRC_DIR}${toPascalCase(this.baseName)}/ClientApp`;
module.exports = class extends needleClientAngular {
...
addEntityToMenu(routerName, enableTranslation, entityTranslationKeyMenu) {
const errorMessage = `${chalk.yellow('Reference to ') + routerName} ${chalk.yellow('not added to menu.\n')}`;
const entityMenuPath = `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.component.html`;
const entityEntry =
// prettier-ignore
this.generator.stripMargin(`|<li>
| <a class="dropdown-item" routerLink="${routerName}" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }" (click)="collapseNavbar()">
| <fa-icon icon="asterisk" fixedWidth="true"></fa-icon>
| <span${enableTranslation ? ` jhiTranslate="global.menu.entities.${entityTranslationKeyMenu}"` : ''}>${_.startCase(routerName)}</span>
| </a>
| </li>`);
const rewriteFileModel = this.generateFileModel(entityMenuPath, 'jhipster-needle-add-entity-to-menu', entityEntry);
this.addBlockContentToFile(rewriteFileModel, errorMessage);
}
...
}
Currently, I get this error, proof that the needle override is not used :
Unable to find
src/main/webapp/app/layouts/navbar/navbar.component.html or missing
required jhipster-needle. Reference to bank-account not added to the
menu

Currently, the only way I found to do it is to replace needles paths from the blueprint client subgenerator directly into the generator-jhipster node module. I know it's not clean but it's not a priority and we will certainly make something better in the future.
The related issue :
https://github.com/jhipster/jhipster-dotnetcore/issues/11

Related

What is the difference between require with curly braces and require normal?

What is the difference between this
const authController = require("../controller/authController");
and this
const { authController } = require("../controller/authController");
my code doesnt work when i call a function like authController.createUser in second one and i wondered thats why?
Thanks for helps.
The difference between example one and example two is that you are using the Destructuring Assignment method in example two. That means, you can destruct an Object, or Array to have the keys of the object as variables.
So, for example if we take this simple object and we start destructuring:
const someObject = {
something1: "1",
something2: "2",
something3: "3",
something4: "4",
};
const { something1 } = someObject;
console.log(something1) // Returns 1
You see that we can use something1 as a "new variable" instead of accessing it by using someObject.something1.
In your case you are including a module / class with the name authController, but if your module doesn't have a method or key called authController, using the following method:
const { AuthController } = ...
won't work, because it's unable to access this method or key.
So, the first one: authController.createUser() will work because you are loading up the entire module without destructuring the module. If you do something like this const { createUser } = require("authController"), you can use it like createUser(...)
Difference between
const authController = require("../controller/authController");
and
const { authController } = require("../controller/authController");
is, when your module exported by default from your .js file we use first syntax, while if there are several modules getting exported from a single .js file we use the second syntax. Also you cannot have more than one default export from a file. Hope that helps.

gnome-shell 3.34 missing ExtensionUtils.extension property

I've written a GNOME shell extension for gnome3.30-3.32 using:
const ExtensionUtils = imports.misc.extensionUtils;
...
ExtensionSystem.disableExtension(ExtensionUtils.extensions['extension-uuid'].uuid);
Updating to 3.34 version, ExtensionUtils does not provide the 'extension' property, and I don't know to find the documentation about it.
How can I fix the issue?
The code you're looking for, the map of loaded extensions, is also a part of the ExtensionSystem module, whereas the ExtensionUtils module is mostly utilities for extension authors like GSettings and Gettext helpers.
The functions you are looking for are a part of the class ExtensionManager in 3.34+. You can get the ExtensionManager instance from the Main import:
// >= 3.34
const Main = imports.ui.main;
const ExtensionManager = Main.extensionManager;
ExtensionManager.disableExtension(uuid);
// <= 3.32
const ExtensionSystem = imports.misc.extensionSystem;
ExtensionSystem.disableExtension(uuid);
// Handling both versions
const Config = imports.misc.config;
if (Config.PACKAGE_VERSION.split('.')[1] >= 34) {
let manager = imports.ui.main.extensionManager;
manager.disableExtension(uuid);
} else {
let extSystem = imports.misc.extensionSystem;
extSystem.disableExtension(uuid);
}
Sources:
https://gitlab.gnome.org/GNOME/gnome-shell/blob/master/js/misc/extensionUtils.js
https://gitlab.gnome.org/GNOME/gnome-shell/blob/master/js/ui/extensionSystem.js
You can use the branch selector on the left of the GitLab page to select the version, or the history button on the right to view a list of changes to a given file.

Test the existence of a dynamically chosen class

I have data coming from an external source that I want to process. In order to do that, the objects I'm receiving are tagged with their original class name. Now I want to take that tag name and use it to populate a model in my own application. I'm stuck at the step where I check for that class having an equivalent in my codebase. Its going to look something like this:
this.objects.forEach((object) => {
if (typeof object.class_tag !== 'undefined') { //the problem line
//create class instance
}
});
In php I'd simply call class_exists to achieve this
<?php
if (class_exists($object->class_tag)) {}
What is the correct approach here?
I don't see the clear way to do this in a just one line.
One of the possible approaches is the way you register your existing classes.
For example if you use some kind of a namespace later on you can simply check the class for existance in the namespace.
Sample code:
class A {}
const a = "A"
const namespace = { A };
if (namespace[a]) {
// class exists, you can create object
const instance = new namespace[a]();
}
Probably, much better approach would be to make some service, that will registerClass, checkClass and createInstance for you. So your logic is wrapped in one place.
I found a way of doing it
(credit to https://stackoverflow.com/a/34656123/746549)
let logger = require('../javascripts/serverlog');
let util = require('util');
let Extension = require('../models/object/Extension');
const classes = {Extension: Extension};
/**
* Utility to emulate class exists / dynamic class naming
* #param className
* #returns {*}
*/
module.exports.dynamicClass = (className) => {
logger.debug(classes);
logger.debug(className);
if (classes[className]) {
return classes[className];
} else {
return false;
}
};
Usage:
let ClassOrFalse = dynamicClass.dynamicClass(object._class_tag);

How to properly call multiple environment variables within a variable definition in Node

I have two environment variables that I have saved in my local local.env.js file. I'd like to use them in place of the username and password in the following code:
var admins = {
'frank': { password: 'mypassword' },
};
When I use the code below, I get an error (Unexpected token .):
var admins = {
process.env.BASIC_AUTH_USER: {password: process.env.BASIC_AUTH_PASSWORD},
};
Any suggestions on how to do this correctly?
In ES5 and earlier, a static object declaration cannot use a "computed" value for a property name - it must be a string literal. So, you have to use an actual line of code to assign the property using the obj[computedPropName] = value; syntax. In your specific case, that would look like this:
var admins = {};
admins[process.env.BASIC_AUTH_USER] = {password: process.env.BASIC_AUTH_PASSWORD};
In ES6, you can use a computed value in a static declaration if you enclose it in the array syntax like this:
var admins = {[process.env.BASIC_AUTH_USER]: {password: process.env.BASIC_AUTH_PASSWORD}};
See this description of new ES6 features and this MDN reference for some further description of this feature.
Portions of ES6 are available in some of the latest version of browsers, in runtime environments like node.js and, of course, you can use transpilers to code in ES6, but transpile to ES5 compatible code for many features. We are, of course, a ways away from being able to rely on native ES6 support for general cross browser use (thus the interest in transpilers now).
You can use array-like-notation, like so:
var admins = {};
admins[process.env.BASIC_AUTH_USER] = {
password: process.env.BASIC_AUTH_PASSWORD
};
If BASIC_AUTH_USER is "Frank" and BASIC_AUTH_PASSWORD is "potatosalad" then you will end up with an object like this:
admins: {
Frank: {
password: 'potatosalad'
}
}
Try this
admins = {};
admins[process.env.BASIC_AUTH_USER] = {password: process.env.BASIC_AUTH_PASSWORD};

Nodejs difference between two paths

I am trying to get the difference between two path. I've come with a solution, but I am not really happy about it, even if it works. Is there a better / easier way to do this?
var firstPath = '/my/first/path'
, secondPath = '/my/first/path/but/longer'
// what I want to get is: '/but/longer'
// my code:
var firstPathDeconstruct = firstPath.split(path.sep)
, secondPathDeconstruct = secondPath.split(path.sep)
, diff = []
secondPathDeconstruct.forEach(function(chunk) {
if (firstPathDeconstruct.indexOf(chunk) < 0) {
diff.push(chunk)
}
})
console.log(diff)
// output ['but', 'longer']
Node provides a standard function, path.relative, which does exactly this and also handles all of the various relative path edge cases that you might encounter:
From the online docs:
path.relative(from, to)
Solve the relative path from from to to.
Examples:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb')
// returns
'..\\..\\impl\\bbb'
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')
// returns
'../../impl/bbb'

Resources