Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve whitespace/comments and stringify? #208

Closed
stevenvachon opened this issue Jun 21, 2017 · 9 comments
Closed

Preserve whitespace/comments and stringify? #208

stevenvachon opened this issue Jun 21, 2017 · 9 comments

Comments

@stevenvachon
Copy link

stevenvachon commented Jun 21, 2017

Would be useful for maintaining env files.

This is what we currently have:

const before = `var1=value
var2=value

# comment
var3=value`;

const parsed = dotenv.parse(before);
//-> { var1:'value', var2:'value', var3:'value' }

const after = require('dotenv-stringify').stringify(parsed);
/*↴
var1=value
var2=value
var3=value
*/

As you can see, the comments and whitespace of the original file are lost, and parse() is to blame. This can be annoying when overwriting the original file after making changes.

This is what we could have:

const before = `var1=value
var2=value

# comment
var3=value`;

const parsed = dotenv.parse(before, { preserveStuff:true });

parsed.var2 = 'changed';

const after = dotenv.stringify(parsed);
/*↴
var1=value
var2=changed

# comment
var3=value
*/
@stevenvachon stevenvachon changed the title Preserve whitespace and stringify? Preserve whitespace/comments and stringify? Jun 21, 2017
@maxbeatty
Copy link
Contributor

Is this the same request as #197? Can you show some before and after examples?

@maxbeatty
Copy link
Contributor

Sorry, I still don't understand what you would like changed with dotenv

@stevenvachon
Copy link
Author

Updated original comment again.

@maxbeatty
Copy link
Contributor

Can you expand on your process for maintaining env files? It's not clear to me why you are editing your variables in node instead of directly in the env file.

How might this be implemented? Where would you store the order of key-values, comments, and whitespace? Feels like it may be beyond the scope of this admittedly small and focused module.

@stevenvachon
Copy link
Author

I have an initialization npm script that creates a database and a database user using data from an env file. To help automate the process, this script first:

  • duplicates the committed ".env.sample" file to ".env"
  • prompts the user to populate the values of specific variables within ".env"

Upon writing these changes, the original formatting is lost.

This is the test project in progress: https://github.com/stevenvachon/todo-express

@stevenvachon
Copy link
Author

Regarding implementation details, we could investigate json-preserve-indent.

@maxbeatty
Copy link
Contributor

That's a familiar problem. I wrote a script for jsPerf with a similar goal but did not strive to maintain any formatting. If I were in your shoes, I would move all of the defaults from .env.sample to your setup script, prompt for missing values, and then use a template literal to get a formatted output.

const fs = require("fs");
const util = require("util");
const Enquirer = require("enquirer");
const dotenv = require("dotenv");
const knex = require("knex");

const vars = {
  POSTGRES_HOST: "",
  POSTGRES_NAME: "sample",
  POSTGRES_PASSWORD: "",
  POSTGRES_USER: ""
};

const enquirer = new Enquirer();

const questions = Object.keys(vars).map(varname =>
  enquirer.question({
    name: varname,
    message: `Value for ${varname}`,
    default: vars[varname] || ""
  })
);

enquirer
  .ask(questions)
  .then(answers => {
    const containsChanges = Object.keys(vars).reduce(
      (result, varname) =>
        result || (answers[varname] && answers[varname].length),
      false
    );

    if (containsChanges) {
      return util.promisify(
        fs.writeFile(
          ".env",
          `
			# database details
			POSTGRES_HOST=${answers.POSTGRES_HOST}
			POSTGRES_NAME=${answers.POSTGRES_NAME}
			POSTGRES_PASSWORD=${answers.POSTGRES_PASSWORD}
			POSTGRES_USER=${answers.POSTGRES_USER}

			PORT=3000
		`
        )
      );
    }
  })
  .then(() => {
    dotenv.config(); // load newly created .env file

    psql = knex({
      client: "pg",
      connection: { host: process.env.POSTGRES_HOST }
    });
    return psql.raw("create database ??", process.env.POSTGRES_NAME);
  });

You could even split this into two scripts- one to prepare env and one to prepare db. Either way, I think this problem is best solved by glueing other modules together and not by expanding what dotenv does today. Good luck!

@stevenvachon
Copy link
Author

Aye, great idea. Thanks!!

@stevenvachon
Copy link
Author

stevenvachon commented Jul 9, 2017

@maxbeatty Now that I'm thinking of making my bootstrapping code a published, general purpose package, the starting env file shouldn't be within a dependency script.

I've written edit-dotenv, and it's probably simpler than this issue's proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants