vue.congfig.js not able to share javascript variable on scss variable - javascript

I am working on dynamic color on my project. So i was succeed to store variable on env and passed on vue.config.js in order to render scss color variable from env variable. but i got into problem when i had to render color value from api since api send color variable as a object. so is it possible to pass object on scss prependData as a object ?
Existing code passed from env:
I am using vuejs 2 and i am adding these code on vue.config.js.
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: `$VUE_APP_PRIMARY:${process.env.VUE_APP_PRIMARY};
$VUE_APP_FOOTER_PRIMARY_COLOR:${process.env.VUE_APP_FOOTER_PRIMARY_COLOR};
$VUE_APP_NAV_COLOR:${process.env.VUE_APP_NAV_COLOR};
$VUE_APP_CARD_BANDAGE_COLOR:${process.env.VUE_APP_CARD_BANDAGE_COLOR};
$VUE_APP_TOP_HEADER_COLOR:${process.env.VUE_APP_TOP_HEADER_COLOR};
$VUE_APP_TOP_HEADER_FONT_COLOR:${process.env.VUE_APP_TOP_HEADER_FONT_COLOR};
$VUE_APP_NAV_COLOR:${process.env.VUE_APP_NAV_COLOR};
$VUE_APP_NAV_PRIMARY_COLOR:${process.env.VUE_APP_NAV_PRIMARY_COLOR};
$VUE_APP_DARK_BTN:${process.env.VUE_APP_DARK_BTN};
$VUE_APP_DARK_BTN_COLOR:${process.env.VUE_APP_DARK_BTN_COLOR};
$VUE_APP_BRAND_BTN:${process.env.VUE_APP_BRAND_BTN};
$VUE_APP_BRAND_BTN_COLOR:${process.env.VUE_APP_BRAND_BTN_COLOR};
$VUE_APP_ERROR_MESSAGE_COLOR:${process.env.VUE_APP_ERROR_MESSAGE_COLOR};
$VUE_APP_FONT_FAMILY:${process.env.VUE_APP_FONT_FAMILY};
$VUE_APP_FONT_HEADER:${process.env.VUE_APP_FONT_HEADER};
$VUE_APP_BACKGROUND:${process.env.VUE_APP_BACKGROUND};
$VUE_APP_BACKGROUND_IMAGE:${process.env.VUE_APP_BACKGROUND_IMAGE};
$VUE_APP_CHOOSE_CATEGORY:${process.env.VUE_APP_CHOOSE_CATEGORY};
$VUE_APP_PLACEHOLDER:${process.env.VUE_APP_PLACEHOLDER};
$VUE_APP_BTN:${process.env.VUE_APP_BTN};
$VUE_APP_FOOTER_LINK:${process.env.VUE_APP_FOOTER_LINK};
$VUE_APP_MULTIPLE_TAG:${process.env.VUE_APP_MULTIPLE_TAG};
$VUE_APP_CART_BTN_BACKGROUND:${process.env.VUE_APP_CART_BTN_BACKGROUND};
$VUE_APP_CART_BTN:${process.env.VUE_APP_CART_BTN};
$VUE_APP_ORDER_INFO_CARD:${process.env.VUE_APP_ORDER_INFO_CARD};
$VUE_APP_CARD_BTN_DELETE_BACKGROUND:${process.env.VUE_APP_CARD_BTN_DELETE_BACKGROUND};
$VUE_APP_CARD_BTN_DELETE:${process.env.VUE_APP_CARD_BTN_DELETE};
$VUE_APP_CARD_BTN_HOVER:${process.env.VUE_APP_CARD_BTN_HOVER};
`
}
}
}
}
Code i want but compiler send error:
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: {
'$VUE_APP_FOOTER_PRIMARY_COLOR': process.env.VUE_APP_FOOTER_PRIMARY_COLOR,
'$VUE_APP_NAV_COLOR': process.env.VUE_APP_NAV_COLOR,
'$VUE_APP_CARD_BANDAGE_COLOR': process.env.VUE_APP_CARD_BANDAGE_COLOR,
'$VUE_APP_TOP_HEADER_COLOR': process.env.VUE_APP_TOP_HEADER_COLOR,
'$VUE_APP_TOP_HEADER_FONT_COLOR': process.env.VUE_APP_TOP_HEADER_FONT_COLOR,
'$VUE_APP_NAV_PRIMARY_COLOR': process.env.VUE_APP_NAV_PRIMARY_COLOR,
'$VUE_APP_DARK_BTN': process.env.VUE_APP_DARK_BTN,
'$VUE_APP_DARK_BTN_COLOR': process.env.VUE_APP_DARK_BTN_COLOR,
'$VUE_APP_BRAND_BTN': process.env.VUE_APP_BRAND_BTN,
'$VUE_APP_BRAND_BTN_COLOR': process.env.VUE_APP_BRAND_BTN_COLOR,
'$VUE_APP_ERROR_MESSAGE_COLOR': process.env.VUE_APP_ERROR_MESSAGE_COLOR,
'$VUE_APP_FONT_FAMILY': process.env.VUE_APP_FONT_FAMILY,
'$VUE_APP_FONT_HEADER': process.env.VUE_APP_FONT_HEADER,
'$VUE_APP_BACKGROUND': process.env.VUE_APP_BACKGROUND,
'$VUE_APP_BACKGROUND_IMAGE': process.env.VUE_APP_BACKGROUND_IMAGE,
'$VUE_APP_CHOOSE_CATEGORY': process.env.VUE_APP_CHOOSE_CATEGORY,
'$VUE_APP_PLACEHOLDER': process.env.VUE_APP_PLACEHOLDER,
'$VUE_APP_BTN': process.env.VUE_APP_BTN,
'$VUE_APP_FOOTER_LINK': process.env.VUE_APP_FOOTER_LINK,
'$VUE_APP_MULTIPLE_TAG': process.env.VUE_APP_MULTIPLE_TAG,
'$VUE_APP_CART_BTN_BACKGROUND': process.env.VUE_APP_CART_BTN_BACKGROUND,
'$VUE_APP_CART_BTN': process.env.VUE_APP_CART_BTN,
'$VUE_APP_ORDER_INFO_CARD': process.env.VUE_APP_ORDER_INFO_CARD,
'$VUE_APP_CARD_BTN_DELETE_BACKGROUND': process.env.VUE_APP_CARD_BTN_DELETE_BACKGROUND,
'$VUE_APP_CARD_BTN_DELETE': process.env.VUE_APP_CARD_BTN_DELETE,
'$VUE_APP_CARD_BTN_HOVER': process.env.VUE_APP_CARD_BTN_HOVER
}
}
}
}
}
Error:
Npm issue

Related

JHipster Blueprint - Generate files with a specific path using templates | Get default java package name

EDIT : the former question was "JHipster Blueprint - How to get default Java package name ?"
I am developing a blueprint with JHipster that overrides the entity-server sub-generator. The desired behaviour is to replace all files in /src/main/java/defaultpackageName/domain/ from the project generated by the blueprint with my generated files. This is my code (files.js):
const entityServerFiles = {
noHibernate: [
//domain files
{
path: 'src/main/java/XXX/domain/',
templates: [
{
file: 'Entity.java',
renameTo: generator => `${generator.persistClass}.java`
}
]
}
]
};
function writeFiles() {
return {
write() {
this.writeFilesToDisk(entityServerFiles, this, false);
}
}
}
module.exports = {
writeFiles
};
For now it just creates a folder XXX in /src/main/java/ with my generated files in it.
What would I need to write in the XXX in path: 'src/main/java/XXX/domain/' in order to generate the files at the right place?
I did some digging on github on the generator-jhipster project and the prompt asking the user for the default java package name is in /generator-jhipster/generators/java/index.cjs/. This is the whole code https://github.com/jhipster/generator-jhipster/blob/main/generators/java/index.cjs
But I just took the important part:
const {
PACKAGE_NAME,
PACKAGE_NAME_DEFAULT_VALUE,
PRETTIER_JAVA_INDENT,
PRETTIER_JAVA_INDENT_DEFAULT_VALUE,
BUILD_TOOL,
BUILD_TOOL_DEFAULT_VALUE,
BUILD_TOOL_PROMPT_CHOICES,
} = require('./constants.cjs');
get prompting() {
return {
async showPrompts() {
if (this.shouldSkipPrompts()) return;
await this.prompt(
[
{
name: PACKAGE_NAME,
type: 'input',
validate: input => this.validatePackageName(input),
message: 'What is your default Java package name?',
default: () => this.sharedData.getConfigDefaultValue(PACKAGE_NAME, PACKAGE_NAME_DEFAULT_VALUE),
},
],
this.config
);
},
};
}
From what I understand, I just need to access the PACKAGE_NAME constant from my blueprint and it should work. Any ideas?
I just found the solution...
const entityServerFiles = {
noHibernate: [
//domain files
{
path: 'src/main/java/',
templates: [
{
file: 'package/domain/Entity.java',
renameTo: generator => `${generator.entityAbsoluteFolder}/domain/${generator.persistClass}.java`
}
]
}
]
};
function writeFiles() {
return {
write() {
this.writeFilesToDisk(entityServerFiles, this, false);
}
}
}
module.exports = {
writeFiles
};
The path property specifies the path inside the templates folder. Meanwhile, you can specify the path you want your files to be generated inside the project in the renameTo property.
So the answer to my question is ${generator.entityAbsoluteFolder} which had nothing to do with my original hypothesis, but this question can also be useful for writing templates in general.

Replacing variable with #rollup/plugin-replace throws error

Problem
I am trying to inject / replace environment variables with #rollup/plugin-replace. Unfortunately, I get this error:
TypeError: can't convert undefined to object
Code
// rollup.config.js
import replace from "#rollup/plugin-replace";
import { config } from "dotenv";
config();
export default {
// ...
plugins: [
replace({
values: { YOUTUBE_API: JSON.stringify(process.env.YOUTUBE_API) },
preventAssignment: true,
}),
// ...
}
And I call it like this:
onMount(() => {
(async function getPopular() {
videos = await axios.get("https://www.googleapis.com/youtube/v3/videos", {
part: "id, snippet, suggestions",
chart: "mostPopular",
key: YOUTUBE_API,
});
})();
});
What I tried
I logged out the variable and so can confirm that it exists. Also, if I remove the stringify function, I get another error:
ReferenceError: blablabblub is not defined
I have done this successfully in other projects. What the heck is wrong here?
So after some digging around with the same issue, I found it was related to object assignment. For example:
export default {
// ...
plugins: [
replace({
values: {
env: {
API_URL: process.env.API_URL,
API_VERSION: process.env.API_VERSION,
}
},
preventAssignment: true,
}),
// ...
}
// in some JS or Svelte file
const config = {
host: env.API_URL,
version: env.API_VERSION
}
// The above will result in a reference error of 'env' not being defined.
// in the same JS or Svelte file..
const envVars = env;
const config = {
host: envVars.API_URL,
version: envVars.API_VERSION
}
// this works just fine!
I haven't had anymore time to investigate, but my gut feeling is that rollup won't replace variable names when they are nested inside an object assignment. It might be nice for an optional flag to allow this, but it might also get very messy hence why they didn't do it.
I hope this helps if it's still an issue for you.

Vue 2 watch fails for mixin data property, but works if the component has the data property

I am trying to move some functionality to a vue mixin from the component, to be able to use it in multiple components.
This (simplified version of the code) works:
export default {
data() {
return {
file: {},
audioPlayer: {
sourceFile: null,
},
};
},
watch: {
'audioPlayer.SourceFile': function (nextFile) {
console.log('new sourceFile');
this.$data.file = nextFile;
},
}
}
But if I move the audioPlayer data object to a mixin, the watch does no longer fire.
Is this expected behavior?
N.b. I resolved this by directly making the 'file' data property into a computed value, which works in this particular case, but the behavior is still strange.
You need a lowercase s. sourceFile not SourceFile
watch: {
'audioPlayer.sourceFile': function (nextFile) {
console.log('new sourceFile');
this.$data.file = nextFile;
},
}

Using Javascript Variables in scss

It's going to be awhile that I'm trying to find a solution to use javascript variables has scss value.
Let me explain my issue.
I use VueJs/Vuetify and I've got two entry point for my theme.
The first one is a json file like that :
module.exports = {
primary: { base: '#4d7cff', dark: '#2756d8', light: '#96b0fb' },
secondary: { base: '#00bda5', dark: '#209284', light: '#cef1ec' },
content: { base: '#37467a', dark: '#242c47', light: '#c3cbe6' },
danger: { base: '#e43858', dark: '#d22545', light: '#E36d83' },
success: { base: '#00c28d', dark: '#199c79', light: '#0bebae' },
accent: '#f5f8fa',
gradient: 'linear-gradient(45deg, #00bda5, #4d7cff)'
}
This file is required and use by vuetify two create custom color values and works perfectly.
The second one is a simple scss file :
// Theme colors
$color-primary-base: #4d7cff;
$color-primary-dark: #2756d8;
$color-primary-light: #96b0fb;
$color-secondary-base: #4d7cff;
$color-secondary-dark: #209284;
$color-secondary-light: #cef1ec;
$color-content-base: #37467a;
$color-content-dark: #242c47;
$color-content-light: #c3cbe6;
$color-danger-base: #e43858;
$color-danger-dark: #d22545;
$color-danger-light: #ff8097;
$color-success-base: #00c28d;
$color-success-dark: #199c79;
$color-success-light: #14e1a9;
$color-accent: #f5f8fa;
My goal would be to connect the json file with the scss variables to have one entry point for the entire app.
Why do this ?
Vuetify offers a scss variable overload system to modify the style of the components.
the idea would be to control this overload from the javascript file
In addition to that, due to vuetify limits, there are certains points where I must to control the color in a responsive context (for example a white header on desktop and blue on mobile) and therefore am obliged to use scss variables.
I've find this article on medium who at first sight seems to answers my problem.
But when I try to test it I've got the following error :
in ./src/assets/styles/vuetify.scss
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
ValidationError: Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'options'. These properties are valid:
object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }
at validate (C:\Users\33770\Documents\Calimed\novalys-front\node_modules\schema-utils\dist\validate.js:96:11)
at Object.loader (C:\Users\33770\Documents\Calimed\novalys-front\node_modules\sass-loader\dist\index.js:36:28)
Vuetify.scss
#import './novalys/map.scss';
#import '~vuetify/src/styles/main.sass';
vue.config.js
const sass = require('node-sass')
const sassUtils = require('node-sass-utils')(sass)
const sassVars = require(__dirname + '/src/theme/index.js')
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: `#import "#/assets/styles/novalys/map.scss";`,
options: {
functions: {
'get($keys)': function(keys) {
keys = keys.getValue().split('.')
let result = sassVars
let i
for (i = 0; i < keys.length; i++) {
result = result[keys[i]]
}
result = sassUtils.castToSass(result)
return result
}
}
}
}
}
},
transpileDependencies: ['vuetify']
}
Can someone here would help me to find a possible solution ?
I've heard about an inverse solution by exporting a scss variable like that
:export {
some-variable: 'some-value';
}
But my idea is to have the entry point in json not a scss file.
Thank you in advance !

How do I mock a module that is minified?

I created a component to be used as a package. We are using third party code supplied to us, a config file (initOpinionLab.js) and a .min.js file (opinionlab.min.js). I am trying to write unit tests for my component. A module that index.js is dependent upon is a minified file located here ../vendor/opinionlab.min.js.
Since this is a component that is used as a node module. I created a __mocks__ file adjacent to the node_modules directory (https://jestjs.io/docs/en/manual-mocks.html) so that when my index.spec.js file looks for this, it will look to the mocks file. How do I mock this minified module if I don't know what it does or returns? I just made this export function up.
root of app/__mocks__ /opinionlab.min.js
export const aFunctionFromOpinionLab = jest.fn(() => Promise.resolve({}))
src/index.js
import '../vendor/opinionlab.min'
import '../assets/style.css'
import initOpinionLab from './initOpinionLab'
export default {
name: 'FeedbackLink',
props: {
linkText: {
type: String,
default: 'Feedback'
},
clientId: {
type: String,
default: null
},
flow: {
type: String,
default: null
},
srcCorrelationId: {
type: String,
default: null
}
},
mounted () {
console.log(this.clientId, this.flow, this.srcCorrelationId, 'this is from mounted line 26')
initOpinionLab({
clientId: this.clientId,
flow: this.flow,
srcCorrelationId: this.srcCorrelationId
})
},
methods: {
launchOpinionLab () {
window.OOo.inlineFeedbackShow()
}
},
template: '<a #click="launchOpinionLab" class="opinionlab-link">{{ linkText }}</a>'
}
src/index.spec.js
import FeedbackLink from '#src/index'
import { shallowMount } from '#vue/test-utils'
jest.mock('../vendor/opinionlab.min.js')
describe('FeedbackLink', () => {
const wrapper = shallowMount(FeedbackLink, {
propsData: {
linkText: 'Feedback',
clientId: 'abc12345',
flow: 'NEW_USER',
srcCorrelationId: 'xyz9876'
}
})
it('[positive] should render correct contents', () => {
expect(wrapper.html()).toMatchSnapshot()
})
})
So you are trying to write unit test for a 3rd party library? This kind of goes against the idea of unit testing your code since you at some point have to assume the other code has its own unit test already. I understand you mocking the 3rd party code so you can get yours to run, but a mock should not care about how the code works, and instead just provides the needed output so your actual code can run.
I would suggest stubbing the code or just returning a known testable value so you can at minimum unit test your code, and not worry about the inner workings of the opinionlab.min.js , as the value gained from trying to parse through a minified fiel will not be worth the time.

Categories