Sails object not available in log.js - javascript

Im building a custom logger using Winston in Sails. I would like to set a log level variable in all of my various environment configs and reference that variable in the log.js file. This seems to work in my controllers with a reference of sails.config.variableName but the same reference in log.js throws: Details:ReferenceError: sails is not defined Can someone tell me how to reference this variable from the config? Is there some sort of require statement that I can add?
I would rather not set the level with some sort of switch/conditional that references the env variable used to start up the application in the log.js (ie. process.env.myEnvironment)

The best way to handle this, even though you may not like it, would be to pass it in as an ENVIRONMENT VARIABLE to Sails at startup instead of using the env/{name}.js files. log.js loads before the full Sails object and you can't reference it. I recommend using:
process.env.{your variable name}
ex: process.env.LOG_LEVEL
Where logLevel is passed to the sails.js app at startup using:
>> LOG_LEVEL=info NODE_ENV=dev node app.js
In this scenario both LOG_LEVEL and NODE_ENV are available to you in the log.js file.
But it's not a "switch" as much as it's an environment specific setting. Externalizing environment specific entities is actually a common practice and recommended for cloud environments where you can alter the values without having to redeploy code.
When running in containers you can easily change the log level from DEBUG to INFO and cycle your containers without redeploying your code. You then switch it back the same way without any downtime.

Related

What's the difference between exposing environment variables in nextjs through the next.config.js vs with the NEXT_PUBLIC prefix?

According to the nextjs documentation, if I want to expose my environment variables to the browser I can just prefix them with NEXT_PUBLIC in my .env.local file, like so:
NEXT_PUBLIC_VAR=7
However, it looks like I can also expose my environment variables to the browser by using next.config.js, like so:
module.exports = {
env: {
PUBLIC_VAR: process.env.PUBLIC_VAR,
},
}
And this will add to the javascript bundle
What is the difference between these two strategies?
NEXT_PUBLIC is a new feature added. Before, in order to set up environment variables, we had to set up both server and client, separately.
Environment variables that are placed in the .env file would be available only on the server-side, if you want to make your env variables available on the client-side you had to use next.config.js. We follow the separation of concerns principle here.
But setting env variables for the browser in the next.config was too much unnecessary typing. This was an example in next.config.js for the client side env:
module.exports = {
env: {
AUTH0_NAMESPACE: process.env.AUTH0_NAMESPACE,
BASE_URL: process.env.BASE_URL
}
}
With NEXT_PUBLIC, env variables will be available both client-side and server-side. env variables that are set with NEXT_PUBLIC will be exposed to the browser. So make sure that you do not expose sensitive data to the browser.
So in summary, adding the prefix NEXT_PUBLIC to your environment variables will have the same effect of exposing to the browser your environment variables as exposing them through next.config.js.
try this:
place this to .env or env.development file. NOT to next.config.js
MY_VAR=10
then run this:
console.log("MY var",process.env.MY_VAR);
both inside client component and getServerSideProps function.
if you check the browser console, you will get undefined, but on terminal, you will see
MY var 10
The difference between to the two is the one of them uses a .env file whereas the other uses the next.config file. Since Next.js 9.4, loading environment variables with .env files are now supported.
However, to clarify one thing in your question, all environment variables within the .env file don't have to be prefixed with NEXT_PUBLIC, only the ones you want exposed to the browser, any without that prefix will only be accessible on the server.

Sharing global between JavaScript files without using modules/exports

I have a self contained JavaScript function in one file, and some Mocha BDD tests in another file that reference it using [nodejs] require(). So in my function under test I export using module.exports. That's all well and good, in the IDE/build.
Now my function under test is actually an external virtual endpoint, which when deployed into a cloud instance, runs standalone inside a JSVM sandbox (Otto) which has no support for exports or modules, and is ES5 based (it does however embed a version of the Underscore library). If I leave the nodejs module definition in there when I deploy to cloud, it kicks off an error at runtime (as Otto doesn't recognise modules). So I want to remove it, and use some vanilla JS mechanism for the linkage back to the Mocha tests and test runner.
So my question is, if I can't use nodejs or requirejs modules, how can I link my Mocha tests in one file to a JS function in another? I had a play with placing a function closure (which most module implementations use) in the file under test, and Otto is happy with this, as its vanilla JS, but any variable with global scope in the file is still not visible from my test file, so there is no linkage.
Any thoughts?
From a quick look at the Otto docs, it looks like Otto only wants whole files and (as you've said) doesn't recogise commonjs modules from node.
If you've got many files I would recommend bundling them into a single file with webpack/browserify/etc, which is how most people convert modules for use in the browser, which similarily doesn't recognise commonjs modules without tooling.
Alternatively, you could convert all the module.exports to simple var declarations, concatenate the files together and hope you don't have a naming collision.
I don't see anything in the docs about having access to a window or global object to hang globals onto, which limits your options
One of my colleague came up with a suggestion to use closure in the file under test which gets deployed into the cloud instance, if you are running under Nodejs, and conditionally do the export. I added the small anonymous closure below to do this, and Otto doesn't complain.
(function () {
if (typeof module != 'undefined') {
module.exports = pdp_virtual_endpoint;
}
}());
Not sure why I didn't think about this earlier :)

What's the proper way of setting environment variable in Netlify functions?

What's the proper way of setting environment variables in netlify? I would like to be able to set different values for the variables depending on the environment.
Pseudo code:
let host;
if (process.env.GATSBY_CUSTOM_CONTEXT === 'production') {
host = process.env.PRODUCTION_HOST
} else if (process.env.GATSBY_CUSTOM_CONTEXT === 'development') {
host = process.env.DEVELOPMENT_HOST
}
I have tried passing env variable thru CLI, like GATSBY_CUSTOM_CONTEXT=production gatsby build and I also tried using same command with cross-env.
My other attempt used netlify.toml:
[build]
base = "/"
publish = "public"
command = "yarn build"
functions = "src/functions"
[context.production]
[context.production.environment]
GATSBY_CUSTOM_CONTEXT = "production"
All of these options worked with netlify dev locally, but in production GATSBY_CUSTOM_CONTEXT is always undefined.
The reason you can't resolve the environment variables in your Netlify functions is because as of the time of your question, Netlify does not transfer the environment variables from the netlify.toml file.
You must put them into the admin panel in your site settings in the app.netlify.com dashboard.
Unfortunately, what you're looking to doesn't seem to be currently supported. Though they provide an alternative approach.
I found this snippet on their docs:
CALLING ENVIRONMENT VARIABLES
Using environment variables directly as
values ($VARIABLENAME) in your netlify.toml file is not supported.
However, the following workflow can be used to substitute values in
the file with environment variable values, assuming you are only
trying to change headers or redirects. The rest of the file is read
BEFORE your build — but those sections are read AFTER the build
process.
Add a placeholder like HEADER_PLACEHOLDER somewhere in the netlify.toml redirects or headers sections.
Create an environment variable, for example PROD_API_LOCATION, with the desired value. You can create environment variables in the
toml file or in our UI. You might use the latter to keep sensitive
values out of your repository.
Prepend a replacement command to your build command. Here’s an example for a site using yarn build to build: sed -i
s/HEADER_PLACEHOLDER/${PROD_API_LOCATION}/g netlify.toml && yarn build
Taken from here: https://www.netlify.com/docs/netlify-toml-reference/

Comment/Uncomment code based on condition

I have been using the gulp-remove-code plugin to remove the specific code from the source files, when I need to change the environment from staging to production or vice-versa. Most of the changed code is API keys and boolean flags. This is for JS, Python, and Yaml files.
The problem with the approach is that, I need to keep the original file at a separate place, since it removes the other environment code.
Instead of removing the code based on a variable, I want to comment or uncomment code, so that I can do an in-place gulp.dest() without having a separate file.
Is there any way to do it via 'gulp' or using the 'gulp-remove-code' plugin or any other plugin?
I use npm module config for that purposes.
All you have to do is:
set NODE_ENV env variable
add config files with the same names as NODE_ENV variable
set NODE_CONFIG_DIR env variable
This approach is very convenient.

Meteor + flowtype

I was playing around with all tools/technics I know to try to make Meteor and Flowtype to be friends. I made a meteor package to run flowtype checker as a linter. It works, but brings more troubles than help to my project so far. The problem is that flow does not have an easy way to declare all global libs interfaces, so when it checks my code, it of cause does not know anything about Meteor or Session global variables. Do I have to convert all Meteor API to an interface for Flow?
It also has troubles to understand the way we use to define global vars in Meteor.
Have anybody tried to fix this issues and how?
What you need is an interface file.
You need to do the following:
Declare the .flowconfig file (it's automatically created when you run flow init).
Create a folder to store your interface files that is ignored by Meteor so it doesn't try to parse it. Meteor ignores certain folder patterns, so you could try mkdir .interfaces. Add the folder to the [libs] section of your .flowconfig, comme ça:
[libs]
.interfaces/
Inside, you can create declarations for your global modules. To create one for Meteor, you can try to touch .interfaces/meteor.js and write something along these lines:
declare class Meteor {
isClient: boolean;
}
Let me know if that works. Still learning flowtype myself.

Categories

Resources