NPM, or make a Go module and publish it to GitHub. You want to make your library easy to work with by application developers. This means, you cannot write library code the same way you would write application code.
Environment Variables are great for storing passwords, configurations, and other points of data. These values in environment variables should not be committed to your git repository. In your application, you should use environment variables for your database connection strings, or API tokens to AWS. The drawback to Environment Variables, they are like globals and I don’t have to tell you globals are a bad thing.
Instead:
// Library Code
export function init(config) {
const conn = postgres(config.dbConnectionString);
}
// Application Code calling library functions
import theLibrary from 'the-library';
const myVars = {
dbConnectionString: process.env.DB_CONNECTION_STRING,
awsToken: process.env.AWS_TOKEN,
};
const result = theLibaray.init(myVars);
Even though NODE_ENV
is a very common environment variable in NodeJS / JavaScript, it should not be used in library code. The application code should handle the environment.
You heard me, don’t be printing logs. Logging creates a dependency on a logging library, or worse, just assumes console.log
in JavaScript is good enough. If you really need to log in the library, then you could accept a function from the application code that you can call to log.
For example
// Library code using logFn
function getFoo(config: any, logFn?: () => void) {
// ... stuff
// If a log function is passed in, we use it to log some data
if (logFn) {
logFn('ERROR', 'there was an error');
}
}
// Application code calling library function with log function
function logFn(level: string, str: string) {
console.log(level, ' ', str);
}
const result = theLibrary.getFoo(myVars, logFn);
Your library should not expect files to be in certain locations or even expect a path to be passed for you library to read/write. Why? What if your library is being used in AWS Lambda? What if the values in the file are not held in a file, but environment variable? Not even a location or pathname? No.
If you need some content from a file, let the calling application do the reading for you. This will make testing 100% easier and faster as well since you don’t have to have files laying around to test.
import ( "os")
func main() {
data, err := os.ReadFile("file/name.txt")
if err != nil {
println(err.Error())
os.Exit(1)
}
myLibrary.doSomething(data)
}
*The caveat of course if reading/writing to files is what your library specifically does, then … bombs away.
This is the worst of all. Never called process.exit()
(NodeJS) or os.Exit()
(Golang). You should be throwing an error in JavaScript or returning an error in Golang. Exiting the process is not for your library to decide. Maybe the application is just checking and has methods to recover or take other actions when a failure happens. If you exit the process in your library, you should be ashamed and have to sit in the corner.
Does it make sense? Committing these infractions in your library makes it much more difficult to test or work with in environments you might not have planned for. This will also make your library more flexible and portable.