Как обеспечить конфигурацию функциональным способом - PullRequest
1 голос
/ 10 апреля 2020

В настоящее время я копаюсь в функциональном программировании и пытаюсь создать пакет, который должен быть настраиваемым. Я хочу, чтобы эта конфигурация была сделана только один раз. В настоящее время я сохранил некоторые из них в переменных среды, что в этом случае не является необходимым и считается плохой практикой. Также я хотел бы сохранить свои функции в чистоте, но я не знаю, как бы я мог настроить свои методы, обеспечивающие эту конфигурацию, без доступа к глобальному состоянию.

Представьте, что у меня есть такой файл:

import { readFile } from 'foo';
import { join } from 'path';

const contentPath = process.env.CONTENT_PATH || './some/path';

export const getSomething = (file) => {
 return readFile(join(contentPath, 'documents', file))
}

export const getSomethingElse = (file) => {
 return readFile(join(contentPath, 'data', file))
}

Затем у меня был такой скрипт установки (я создаю его для следующего js):

const withSvgr = require('next-svgr');
const withTM = require('next-transpile-modules')(['@baretheme/fs', '@baretheme/core']);

module.exports = (pluginOptions = {}) => (nextConfig = {}) => {
  const contentPath = pluginOptions.contentPath || 'content';
  return withTM(withSvgr({
    ...nextConfig,
    env: {
      ...nextConfig.env,
      CONTENT_PATH: contentPath,
    },
    webpack(config, options) {
      // eslint-disable-next-line no-param-reassign
      config.node = {
        ...config.node,
        fs: 'empty',
      };

      if (typeof nextConfig.webpack === 'function') {
        return nextConfig.webpack(config, options);
      }

      return config;
    },
  }));
};

Так что я мог настроить свой пакет следующим образом:

const setupMyPackage = require('my-package');

const myPackage = setupMyPackage({ ... });

module.exports = myPackage({ ... })

Мне очень нравится, как карри используется здесь, чтобы сначала получить конфигурацию плагина, а затем передать nextConfig, однако, где мне сохранить pluginOptions в моем пакете?

Решение, которое я имею в виду на данный момент создает скрипт установки следующим образом:

import { join } from 'path';
import { getSomething, getSomethingElse } from './lib';

export function setup(options) {
  const defaults = {
    documentsPath: join(options.contentPath, 'documents'),
    dataPath: join(options.contentPath 'data'),
  };

  const config = {
    ...defaults,
    ...options,
  };

  return {
    getSomething: getSomething(config), // should be curried?
    getSomethingElse: getSomethingElse(config)
  };
}

Он также использует карри, сначала предоставив конфигурацию моим методам. Однако, чтобы использовать это, вероятно, сначала нужно будет создать файл, который импортирует мои настройки, вызвать его, передать конфигурацию и снова экспортировать. Тогда ему придется импортировать этот файл вместо моего пакета. Я бы предпочел, чтобы вы сначала вызвали установку, а затем импортировали мои функции куда угодно. Возможно ли это вообще без сохранения этой конфигурации? Это плохая практика или я все усложняю?

1 Ответ

1 голос
/ 13 апреля 2020

Одним из возможных решений, которое должно быть проектным решением в самом начале вашего проекта, является использование Reader монады.

Можно использовать его для цепочки функций, которые задерживают их выполнение до тех пор, пока вы не дадите и окружение , поэтому все они получают их в качестве последнего аргумента.

Вот очень упрощенный пример использования Ramda, чтобы избежать шаблонов:

const { map, pipeK } = R
const I = x => x
const C = f => x => y => f (y) (x)

const Reader = C (map) (I)

const f = Reader (x => ({ y }) => x + y)
const g = Reader (x => ({ y }) => x + y + 2)
const h = Reader (x => ({ y }) => x + y + 2)

const compute = pipeK (f, g, h)

const env = { y: 1 }
const output = compute (1) (env)

console.log (output)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.min.js"></script>

Настало время исследовать около читателей , чтобы узнать больше!

...