Статьи

Избавьтесь от Node.js Config Grunt Work

Недавно мы начали использовать конфигурацию модуля NPM в наших проектах Node.js. Это действительно хороший способ, позволяющий нашим клиентам настраивать их программное обеспечение после его доставки. IMHO, одна из самых приятных функций — это средство, позволяющее вам определять пользовательские переменные среды для любого заданного configпараметра.

Например, если ваш файл конфигурации config/default.jsonвыглядит

{
  "dirs": {
    "upload": "/tmp",
    "extracted": "/tmp"
  }
}

Затем вы можете создать еще один файл с именем config/custom-environment-variables.jsonкак

{
  "dirs": {
    "upload": "MYAPP_DIRS_UPLOAD",
    "extracted": "MYAPP_DIRS_EXTRACTED"
  }
}

это позволяет администратору переопределять значения конфигурации в файлах .json с переменными среды. Например, если он установит MYAPP_DIRS_UPLOADдля /var/uploads, то configвернется /var/uploadsвместо /tmp. Хорошо, правда?

Однако для больших проектов или для ленивых разработчиков, таких как я, легко забыть добавить запись в config/custom-environment-variables.jsonкаждый раз, когда вы добавляете запись в config/default.json(или любой другой файл конфигурации).

Видишь ли, я действительно ненавижу грубую работу. Поскольку я поддерживаю бесценную черту лени , я создал и опубликовал модуль NPM под названием, config-cev-generatorкоторый заботится о создании config/custom-environment-variables.jsonфайла для меня. Кстати, «cev» означает «пользовательскую переменную среды», которую вы, вероятно, уже заметили. Теперь вы можете создать это для вас! Только что

$ npm install -g config-cev-generator

и ты готов к работе.

Например, в проекте Node.js, который использует config, откройте командную строку в корне проекта и попробуйте команду

$ cev

Вы увидите, что все ваши переменные конфигурации готовы к использованию в качестве переменных среды, напечатанных на стандартный вывод. Чтобы сохранить его, просто перенаправьте вывод в config/custom-environment-variables.json. Например, учитывая приведенный выше файл конфигурации, cevгенерирует

$ cev
{
  "dirs": {
    "upload": "NODE_APP_DIRS_UPLOAD",
    "extracted": "NODE_APP_DIRS_EXTRACTED"
  }
}

Префикс по умолчанию — это NODE_APPразделитель _, а переменные окружения (являющиеся переменными окружения) по умолчанию имеют верхний регистр. Но ждать! Есть еще кое-что!  cevхорошо настраивается:

$ cev --help
USAGE: node cev [OPTION1] [OPTION2]... arg1 arg2...
The following options are supported:
  -s, --separator      Separator. ("_" by default)
  -p, --prefix         Prefix. ("NODE_APP" by default)
  -c, --casing         Casing: "upper", "lower", or "unchanged". ("upper" by default)
  -f, --pretty         Format prettily with given number of spaces for indentation. ("2" by default)
  -e, --empties              If present, preserves sections that wouldn't have any environment variables.  Functions are always skipped.
  -v, --verbose              Be verbose.

Вызов

$ cev --prefix MYAPP --casing lower

доходность

{
  "dirs": {
    "upload": "myapp_dirs_upload",
    "extracted": "myapp_dirs_extracted"
  }
}

Для маленьких проектов, кого это волнует, разве вы действительно ленивы, верно? Но для крупных проектов это может стать действительно раздражающим. Рассмотрим этот config/default.jsonфайл:

{
  "dirs": {
    "upload": "",
    "extracted": "",
    "regex": "",
    "format": ""
  },
  "tz": "",
  "webserver": {
    "name": "DEFAULT",
    "port": 4879,
    "pfx": "cert/cert.pfx",
    "passphrase": "",
    "public": "cert/public.crt.pem",
    "ca": "cert/root-ca.crt.pem",
    "cakey": "cert/root-ca.key.pem"
  },
  "encryption": {
    "public": {
      "keyfile": "keys/public.pem",
      "key": ""
    }
  },
  "email": {
    "username": "",
    "password": "",
    "from": "",
    "host": "smtp.google.com",
    "port": 25
  },
  "ios": {
    "root": "ios",
    "plist": "MyApp.plist.ejs",
    "ipa": "MyApp.ipa",
    "bundleIdentifier": "0000000000.com.scispike.MyApp",
    "subtitle": "SciSpike MyApp",
    "title": "SciSpikeMyApp"
  }
}

Писать config/custom-environment-variables.jsonдля этого было бы просто отстой. Проверь это:

$ cev --prefix MYAPP
{
  "dirs": {
    "upload": "MYAPP_DIRS_UPLOAD",
    "extracted": "MYAPP_DIRS_EXTRACTED",
    "regex": "MYAPP_DIRS_REGEX",
    "format": "MYAPP_DIRS_FORMAT"
  },
  "tz": "MYAPP_TZ",
  "webserver": {
    "name": "MYAPP_WEBSERVER_NAME",
    "port": "MYAPP_WEBSERVER_PORT",
    "pfx": "MYAPP_WEBSERVER_PFX",
    "passphrase": "MYAPP_WEBSERVER_PASSPHRASE",
    "public": "MYAPP_WEBSERVER_PUBLIC",
    "ca": "MYAPP_WEBSERVER_CA",
    "cakey": "MYAPP_WEBSERVER_CAKEY"
  },
  "encryption": {
    "public": {
      "keyfile": "MYAPP_ENCRYPTION_PUBLIC_KEYFILE",
      "key": "MYAPP_ENCRYPTION_PUBLIC_KEY"
    }
  },
  "email": {
    "username": "MYAPP_EMAIL_USERNAME",
    "password": "MYAPP_EMAIL_PASSWORD",
    "from": "MYAPP_EMAIL_FROM",
    "host": "MYAPP_EMAIL_HOST",
    "port": "MYAPP_EMAIL_PORT"
  },
  "ios": {
    "root": "MYAPP_IOS_ROOT",
    "plist": "MYAPP_IOS_PLIST",
    "ipa": "MYAPP_IOS_IPA",
    "bundleIdentifier": "MYAPP_IOS_BUNDLEIDENTIFIER",
    "subtitle": "MYAPP_IOS_SUBTITLE",
    "title": "MYAPP_IOS_TITLE"
  }
}

Хорошо, а?

Вот кое-что, что может принести вам бонусные баллы среди ваших соратников (читай: ленивые программисты). Добавьте config-cev-generatorк вашему package.json«с devDependencies, затем вызовите проект локальной cevкоманды , прежде чем что — нибудь интересное. Например, рассмотрим этот package.jsonфрагмент:

  ...
  "devDependencies": {
    "config-cev-generator": "^0.1.4"
  },
  "scripts": {
    "cev": "$(npm bin)/cev --prefix COOLNESS > config/custom-environment-variables.json",
    "pretest": "npm run cev",
    "prestart": "npm run cev",
    "prerestart": "npm run cev",
    ...
  },
  ...

Теперь, всякий раз, когда вы запускаете тест или ваше приложение, вы не должны забывать config/custom-environment-variables.jsonсинхронизировать его с остальной частью вашей конфигурации! Проверь это:

$ npm install
npm WARN package.json cev-test@1.0.0 No description
npm WARN package.json cev-test@1.0.0 No repository field.
npm WARN package.json cev-test@1.0.0 No README data
config-cev-generator@0.1.4 node_modules/config-cev-generator
├── stdio@0.2.7
└── config@1.15.0
$ npm test

> cev-test@1.0.0 pretest /Users/matthew/temp/cev-test
> npm run cev


> cev-test@1.0.0 cev /Users/matthew/temp/cev-test
> $(npm bin)/cev --prefix COOLNESS > config/custom-environment-variables.json


> cev-test@1.0.0 test /Users/matthew/temp/cev-test
> echo 'you should run tests here'

you should run tests here
$ cat config/custom-environment-variables.json
{
  "dirs": {
    "upload": "COOLNESS_DIRS_UPLOAD",
    "extracted": "COOLNESS_DIRS_EXTRACTED",
    "regex": "COOLNESS_DIRS_REGEX",
    "format": "COOLNESS_DIRS_FORMAT"
  },
  "tz": "COOLNESS_TZ",
  "webserver": {
    "name": "COOLNESS_WEBSERVER_NAME",
    "port": "COOLNESS_WEBSERVER_PORT",
    "pfx": "COOLNESS_WEBSERVER_PFX",
    "passphrase": "COOLNESS_WEBSERVER_PASSPHRASE",
    "public": "COOLNESS_WEBSERVER_PUBLIC",
    "ca": "COOLNESS_WEBSERVER_CA",
    "cakey": "COOLNESS_WEBSERVER_CAKEY"
  },
  "encryption": {
    "public": {
      "keyfile": "COOLNESS_ENCRYPTION_PUBLIC_KEYFILE",
      "key": "COOLNESS_ENCRYPTION_PUBLIC_KEY"
    }
  },
  "email": {
    "username": "COOLNESS_EMAIL_USERNAME",
    "password": "COOLNESS_EMAIL_PASSWORD",
    "from": "COOLNESS_EMAIL_FROM",
    "host": "COOLNESS_EMAIL_HOST",
    "port": "COOLNESS_EMAIL_PORT"
  },
  "ios": {
    "root": "COOLNESS_IOS_ROOT",
    "plist": "COOLNESS_IOS_PLIST",
    "ipa": "COOLNESS_IOS_IPA",
    "bundleIdentifier": "COOLNESS_IOS_BUNDLEIDENTIFIER",
    "subtitle": "COOLNESS_IOS_SUBTITLE",
    "title": "COOLNESS_IOS_TITLE"
  }
}

Пожалуйста. И да здравствует лень.

Модуль npm находится по адресу  https://www.npmjs.com/package/config-cev-generator, а общедоступное git-репозиторий — по адресу  https://github.com/SciSpike/node-config-cev-generator . Вопросы приветствуются; тянуть запросы приветствуются!  :)



Для получения дополнительной информации, пожалуйста, свяжитесь с info@scispike.com

Молниеносная разработка программного обеспечения!