{"id":15731547,"url":"https://github.com/tuchk4/presets","last_synced_at":"2025-03-31T02:49:00.477Z","repository":{"id":74998315,"uuid":"56492223","full_name":"tuchk4/presets","owner":"tuchk4","description":"Presets machine","archived":false,"fork":false,"pushed_at":"2017-07-24T10:03:07.000Z","size":9,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-06T07:46:46.823Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tuchk4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-04-18T08:53:19.000Z","updated_at":"2016-04-18T08:54:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"28174bcb-fc4a-4023-bd5a-c1a080cc6fb9","html_url":"https://github.com/tuchk4/presets","commit_stats":{"total_commits":9,"total_committers":1,"mean_commits":9.0,"dds":0.0,"last_synced_commit":"2c354119e1d388f6a1d73426fbc2295b70fca1af"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuchk4%2Fpresets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuchk4%2Fpresets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuchk4%2Fpresets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuchk4%2Fpresets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tuchk4","download_url":"https://codeload.github.com/tuchk4/presets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246408101,"owners_count":20772229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T00:02:08.790Z","updated_at":"2025-03-31T02:49:00.459Z","avatar_url":"https://github.com/tuchk4.png","language":"JavaScript","readme":"# Presets\n[![Build Status](https://travis-ci.org/tuchk4/presets.svg?branch=master)](https://travis-ci.org/tuchk4/presets)\n\nPresets collection merger. \n\n## Motivation\n\nThere are a lot of npm packages with documentation, a lot of local configurable modules and every time \nI should read / learn documentation to configuration package to meet my requirements. Or search for guidelines and tutorials.\nAnd that configuration code will be copied from project to project.\n \nFor example - we have a lot of projects with webpack and karma. That configs are almost the same. \nWebpack common sections:\n  \n  - Plugins for production (optimization)\n  - Plugins for development (devtool, define etc.)\n  - resolve attr.\n  - context attr.\n  - resolveLoader fallback\n\nWebpack different sections:\n\n  - entry\n  - externals\n  - loaders \n\nSure we could move common code to separated repository and it always will be up to date for all projects (even possible to \nbind to specific version). But this is not good solution: For karma config - we should do the same. Or we want to\nuse webpack production configuration from boilerplate repository at github, where community always suggest best ways and\npractices.\n\nThis also could be applicable to:\n \n  - api configuration\n  - components configuration\n  - cli tasks configuration\n  - environment configuration\n  - routing configuration\n  - middleware configuration (express / redux etc.)\n  - generating higher-ordered functions\n    \n## Сoncepts\n\n**preset** - simple function with return statement. Could be configured with higher-order function. Returned value is depends\non preset's context.\n\n**merger** - function that merge presets. Responsible for the way how presets should be merged: \n\n  - should preset's results be merged at the root level?\n  - should preset's results be merged at all nested levels?\n  - should some attributes be merged or overridden?\n  - should some attributes be merged or overridden if already exists?\n  - if preset's result is function - each next preset should be the higher-order function. What function's arguments \nbehaviour should be in this way? \n\n    \n## API\n\n  - **presets(props = {})** - Takes props (optional) that will be passed to each preset's function. Could be used for\nconfiguration. Returns presetsCollection function. \n  - **presetsCollection(...presets)** - Takes presets collection (strings or functions). Returns collectionMerge function.\n  - **collectionMerge(merger, initialValue = {})** -  Takes merger function (required, details below) and initial value (optional).\nReturns merged result. \n\n### Presets\n\n```js\nimport presets from 'presets';\n```\n**presets(props)** - returns function for configuring presets collection. props - optional argument and if exists -\nit will be passed as first arguments for each preset in collection.\n\n### Presets collection\n\n```js\nimport presets from 'presets';\nconst pipe = presets({\n  // ...\n});\n```\n\n**pipe(...presets)** - returns function for prepared presets collection merge. Takes presets (strings or functions) as arguments.\nIs presets is string - will try to find preset in `node_modules`. Preset's package name - 'preset-${name}'.\nIn this way - preset's module export - should be a function. Next steps are same as below (if preset is function).\n\n```js\nimport presets from 'presets';\nconst presetsCollection = presets({\n  // ...\n});\n\nconst mergeCollection = presetsCollection({\n  'webpack-production', // will search for \"preset-webpack-production\" in node_modules\n  'webpack-hot-reload'  // will search for \"preset-webpack-hot-reload\" in node_modules\n});\n```\n\nIs preset is function - it will be executed and it's result will be merged with other presets using merge function.\n    \n```js\nimport presets from 'presets';\nconst presetsCollection = presets({\n  // ...\n});\n\nconst mergeCollection = presetsCollection({\n  (props) =\u003e {\n    return {\n      // ...\n    };\n  }\n});\n```\n\nAnd combined:\n\n```js\nimport presets from 'presets';\nconst presetsCollection = presets({\n  // ...\n});\n\nconst mergeCollection = presetsCollection({\n  'webpack-production', // will search for \"preset-webpack-production\" in node_modules\n  'webpack-hot-reload'  // will search for \"preset-webpack-hot-reload\" in node_modules\n   (props) =\u003e {\n      return {\n        // ...\n      };\n   }\n});\n```\n\nThere is list of existing presets and it's description and the end of documentation.\n\n### Collection merge\n\n```js\nimport presets from 'presets';\nimport merge from 'merge';\n\nconst presetsCollection = presets({\n  // ...\n});\n\nconst mergeCollection = presetsCollection({\n  // ...\n});\n\nconst initialValue = {\n  // ...\n};\n\nconst config = mergeCollection(merge, initialValue);\n```\n\n**merge** - simple function that merge preset's results. \nExample of it's very simple implementation:\n\n```js\nconst merge = (collectionConfig, presetConfig) =\u003e ({\n  ...collectionConfig,\n  ...presetConfig\n});\n```\n\nAccording to merge requirements - could be more complex. \nThere is list of merge functions and it's description and the end of documentation.\n    \n    \n## Install\n\n`npm install --save presets`\n\n## Abstract example\n\n```js\nimport presets from 'presets';\nimport merge from 'presets/merge';\n\nconst presetsCollection = presets({\n  // ...\n});\n\n// will search for 'presets-foo', 'presets-bar', 'presets-baz' in node_modules\nconst mergeCollection = presetsCollection('foo', 'bar', 'baz');\n\n\nconst initialConfig = {\n  // ....\n};\n\nconst config = mergeCollection(merge, initialConfig);\n```\n\n## Real example\n\nWebpack:\n```js\nimport presets from 'presets';\nimport webpackMerge from 'webpack-merge';\nimport webpackIndexTemplates from 'webpack-index-templates';\n\nconst presetsCollection = presets();\n\nconst mergeCollection = presetsCollection(\n  'webpack-production', \n  'webpack-dev',\n  'webpack-react-toolbox',\n  'webpack-build-logs',\n  'webpack-hot-reload',\n  webpackIndexTemplates({\n    src: './index.html',\n    dest: 'index.html',\n    variables: {\n      // ...\n    }\n  }),\n  \n  webpackIndexTemplates({\n    src: './index.html',\n    dest: 'index-staging.html',\n    variables: {\n      // ...\n    }\n  }),\n);\n\nconst initialWebpackConfig = {\n  entry: {\n    app: [\n      'babel-polyfill',\n      './scripts/master'\n    ]\n  },\n};\n\nconst webpackConfig = mergeCollection(webpackMerge, initialWebpackConfig);\n```\n\nKarma:\n```js\nimport presets from 'presets';\nimport karmaMerge from 'karma-merge';\n\nconst presetsCollection = presets();\n\nconst mergeCollection = presetsCollection(\n  'karma-webpack',\n  'karma-coverage',\n  'karma-chrome',\n  'karma-mocha',\n  'karma-phantomjs',\n  'karma-gremlins'\n);\n\nconst initialKarmaConfig = {\n  files: [\n    'src/**/*/__tests__/*.js'\n  ]\n};\n\nconst karmaConfig = mergeCollection(karmaMerge, initialKarmaConfig);\n```\n\nAPi configuration:\n```js\nimport presets from 'presets';\nimport functionalMerge from 'presets/functional-merge';\n\nconst presetsCollection = presets();\n\nconst mergeCollection = presetsCollection(\n  'fetch',\n  'cross-browser',\n  'cache-request'\n);\n\n\nconst api = mergeCollection(functionalMerge);\n\napi('POST /users/1', {\n  // ... request\n});\n```\n\nReact component configuration:\n```js\nimport presets from 'presets';\nimport merge from 'presets/merge';\n\nimport aclPresets form 'acl-presets';\n\nconst presetsCollection = presets();\n\nconst mergeCollection = presetsCollection(\n  props =\u003e \u003cButton ...props/\u003e,\n  aclPresets({\n    admin: () =\u003e { //... },\n    guest: () =\u003e { //... }\n  }),\n);\n\n\nconst AclButton = mergeCollection(merge);\n```\n\nExpress configurations\n```js\nimport presets from 'presets';\nimport merge from 'presets/merge';\n\nconst presetsCollection = presets();\n\nconst mergeCollection = presetsCollection(\n  'express-auth',\n  'express-secure-routing',\n  'express-spa'\n);\n\n\nconst server = mergeCollection(merge);\n```\n\n## Contribute\n\n`npm test` - run tests.\n`npm run test-dev` - monitors the file system for changes and run tests\n`npm run dev` - monitors the file system for changes and transpile ES6 code. Very and very useful when packages is linked (`npm link`)\n\nIf you develop presets - make pull request add link to your presets with little description.\n \n  \n## Troubleshooting\n\n### Configurable string presets \n\nIf use presets as functions - preset could be configured:\n```js\nimport presets from 'presets';\n\nconst configurablePreset = (options) =\u003e {\n  // ...\n  return props =\u003e {\n    // ...\n  }\n}\n\nconst presetsCollection = presets();\n\nconst mergeCollection = presetsCollection({\n  configurablePreset({\n    // ...  presets configuration here\n  })\n});\n```\n\nBut if use preset from node_modules (eg. external presets) that should be auto-imported - we should import it manually\nand use as function. So this way is not very pretty (auto-import feature is not using).\n\n```js\nimport presets from 'presets';\nimport presetWebpackProduction from 'preset-webpack-production';\n\nconst presetsCollection = presets({\n  // ...\n});\n\nconst mergeCollection = presetsCollection({\n  presetWebpackProduction({\n    // ...  presets configuration here\n   })\n});\n```\n\nOne of the way to improve this - use something like `.presetsrc` (but there are also some problems: could not be configured\naccording to current environment or via dynamic options):\n```js\n{\n  \"webpack-production\": {\n     // ...\n  }\n}\n```\n\nSecond way: use configuration hook:\n\n```js\nimport presets from 'presets';\n\nconst presetsCollection = presets({\n  // ...\n});\n\npresetsCollection.hooks.configuration('webpack-production', () =\u003e {\n  return {\n    // ...\n  }\n});\n\nconst mergeCollection = presetsCollection({\n  'webpack-production'\n});\n```\n\nIf you have ideas - just let me know. Also there is issue#1 for discussing.\n\n## Presets list\n\n  - preset-webpack-production\n  - preset-webpack-development\n  - preset-webpack-index-templates\n  - preset-karma\n  - preset-bivrost-api\n  \n## Mergers list\n\n  - root-merge\n  - deep-merge\n  - webpack-merge\n  - functional-merge\n\n\n\n     \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuchk4%2Fpresets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftuchk4%2Fpresets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuchk4%2Fpresets/lists"}