{"id":20388564,"url":"https://github.com/efureev/layer-request","last_synced_at":"2026-04-20T04:36:54.433Z","repository":{"id":53744000,"uuid":"349505799","full_name":"efureev/layer-request","owner":"efureev","description":"Request with layer-configs","archived":false,"fork":false,"pushed_at":"2022-11-13T00:56:51.000Z","size":141,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T12:42:27.372Z","etag":null,"topics":["axios","multi-config","multi-layer","request"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/efureev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-19T17:35:47.000Z","updated_at":"2022-08-05T06:22:59.000Z","dependencies_parsed_at":"2023-01-22T21:46:03.072Z","dependency_job_id":null,"html_url":"https://github.com/efureev/layer-request","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/efureev/layer-request","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efureev%2Flayer-request","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efureev%2Flayer-request/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efureev%2Flayer-request/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efureev%2Flayer-request/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/efureev","download_url":"https://codeload.github.com/efureev/layer-request/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efureev%2Flayer-request/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32032848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T00:18:06.643Z","status":"online","status_checked_at":"2026-04-20T02:00:06.527Z","response_time":94,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["axios","multi-config","multi-layer","request"],"created_at":"2024-11-15T03:11:31.102Z","updated_at":"2026-04-20T04:36:54.412Z","avatar_url":"https://github.com/efureev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Requests with layers config manager\n\nIt allows you held on hierarchical multi-config for your axios-requests.\n\n**Base units:**\n\n- Request Config Manager: `LayerConfigManager`\n- Request Config: `LayerConfig`\n- Request: `LayerRequest`\n\n## How it works\n\nHierarchical configs:\n\n```mermaid\nflowchart LR\n\tnode[\u003cb\u003eaxios-config: base\u003c/b\u003e\u003chr\u003ename: `api`\u003cbr\u003ebase url: `/api`]\n\t\n\tnode1[\u003cb\u003eaxios-config: v1\u003c/b\u003e\u003chr\u003ename: `v1`\u003cbr\u003ebase url: `/api/v1`]\n\tnode2[\u003cb\u003eaxios-config: v2\u003c/b\u003e\u003chr\u003ename: `v2`\u003cbr\u003ebase url: `/api/v2`]\n\t\n\tnode2User[\u003cb\u003eaxios-config: v2.users\u003c/b\u003e\u003chr\u003ename: `v2.users`\u003cbr\u003ebase url: `/api/v2/users`]\n\t\n\tstyle node text-align:left\n\tstyle node1 text-align:left\n\tstyle node2 text-align:left\n\tstyle node2User text-align:left\n\t\n\tnode --\u003e node1\n\tnode --\u003e node2\n\tnode2 --\u003e node2User\n```\n\n## Basic usage\n\nAdd your config and do a request:\n\n```js\nimport { LayerRequest, globalLayerConfigManager } from '@feugene/layer-request'\n\nconst apiRequestConfig = {\n  axiosRequestConfig: {\n    baseURL: '/api',\n  }\n}\n\nconst layerApi = globalLayerConfigManager.addLayer(apiRequestConfig, 'api')\n\n//...\nconst layerRequest = new LayerRequest()\nconst request = layerRequest.useConfig('api')\nrequest.get('users').then(resp =\u003e {\n})  // --\u003e GET '/api/users'\n\n// it's all!\n// if you want to extent you config:\n\nglobalLayerConfigManager.addCopyFrom(layerApi, (targetConfig, sourceConfig) =\u003e {\n  targetConfig.axiosRequestConfig.baseURL += '/v2'\n  targetConfig.interceptors.response.push(ConsoleResponseInterceptor2)\n  targetConfig.extra.test = 'test'\n}, 'v2')\n\n// and then call it:\nconst request = layerRequest.useConfig('v2')\nrequest.get('users')  // --\u003e GET '/api/v2/users'\n```\n\n## Unit Methods\n\n### LayerConfig\n\nIt's Axios config container\n\n- clone: Clone a LayerConfig\n- getName: Returns LayerConfig's name\n- setName: Set a name to a LayerConfig\n-\n\n### LayerConfigManager\n\nIt's a LayerConfig manager\n\n- addLayer: Add LayerConfig to the container\n- getLayer: Returns a LayerConfig\n- createLayer: Creates a new LayerConfig\n- copyLayer: Copy \u0026 return a LayerConfig from an existing LayerConfig\n- copyLayerAndSetup: Copy \u0026 return a LayerConfig from an existing LayerConfig and set it up\n- addCopyFrom: Copy, set it up and add into the container\n- updateLayer: Updates currently defined LayerConfig\n- all: Returns the all LayerConfigs\n- list: Returns the all LayerConfig's names\n- reset: Clear the container\n\n### LayerRequest\n\nIt's a Request builder\n\n- useConfig: apply some defined in the manager LayerConfig and return the Axios instance\n- reset: reset all properties\n- getAxios: returns the Axios instance\n\n## Examples\n\nBasic, without config. This request already contains first Config Layer with name `/`:\n\n```js\nimport { LayerRequest } from '@feugene/layer-request'\n\nconst request = new LayerRequest()\n```\n\nBasic, with empty config layer manager or custom config:\n\n```js\nimport { buildLayerRequest } from '@feugene/layer-request'\n\nconst request = buildLayerRequest()\n```\n\nYou can transfer \"additional\" data within requests and interceptors:\n\n**In request**\n\n```js\nimport { LayerRequest, LayerConfigManager } from '@feugene/layer-request'\n\nconst m = new LayerConfigManager()\n// ...\nconst extra = {\n  store: { ... },\n  dataWrapper: true,\n  // ..\n}\nconst request = new LayerRequest(m, extra)\n```\n\n**In layer**\n\n```js\nimport { LayerRequest, layerConfigManager } from '@feugene/layer-request'\n\nconst lc = new LayerConfig({\n  axiosRequestConfig: {\n    baseURL: '/',\n  },\n  extra: {\n    store: {},\n    dataWrapper: true,\n  }\n})\n\nlayerConfigManager.addLayer(lc, 'base')\n```\n\nOr when you make request:\n\n```js\nconst request = r.useConfig(configId, { withoutDataBlock: true })\n```\n\n\u003e **Note:** layer's extras \u0026 extras bringing in `useConfig` will be merged!\n\n## Add new config layer\n\n```js\nconst r = buildLayerRequest()\n\nconst layoutApi = r.manager.addLayer((cm) =\u003e cm.createLayer({\n  axiosRequestConfig: {\n    headers: {\n      host: 'localhost',\n    },\n    baseURL: '/api',\n  },\n  interceptors: {\n    // request: [...],\n    response: [ConsoleResponseInterceptor1],\n  },\n}))\n\n// add another layer\nconst layoutV1 = r.manager.addCopyFrom(layoutApi, (targetConfig) =\u003e {\n  targetConfig.axiosRequestConfig.baseURL += '/v1'\n  targetConfig.interceptors.response.push(ConsoleResponseInterceptor2)\n})\n\n// or \nconfigForModule1 = r.manager.addLayer((cm) =\u003e {\n  const copyLayout = cm.copyLayer(layoutV1)\n\n  copyLayout.axiosRequestConfig.baseURL += '/module1'\n\n  return copyLayout\n})\n```\n\nCreate new layer by coping from existing layer and add it to the manager.\n\n```js\nr.manager.addCopyFrom('/api', (targetConfig) =\u003e {\n  targetConfig.axiosRequestConfig.baseURL += '/v2'\n})\n// or\nr.manager.addCopyFrom(layoutApi, (targetConfig) =\u003e {\n  targetConfig.axiosRequestConfig.baseURL += '/v3'\n})\n```\n\nCreate config layer with custom name `front`\n\n```js\nr.manager.addLayer((cm) =\u003e cm.copyLayer('/api'), 'front')\n```\n\nUpdate existing config layer by name (`/api`)\n\n```js\nr.manager.updateLayer('/api', (cl) =\u003e {\n  cl.axiosRequestConfig.baseURL = '/api/admin'\n})\n```\n\n## Use a request with defined config\n\n```js\nconst configId = 'api' // type of \u003cstring\u003e or \u003cLayerConfig\u003e\nconst request = r.useConfig(configId)\nrequest.post('store', { key: 1 }) // it'll do POST request on url `/api/v1/module1/store`\nrequest.get('/') // it'll make GET request on url: `/api/v1/module1`\n\nconst request = r.useConfig('/api/v2')\nrequest.get('app/users')  // --\u003e GET '/api/v2/app/users'\n  .then(resp =\u003e {\n  })\n\nrequest.post('app/users/12')  // --\u003e POST '/api/v2/app/users/12'\n  .then(resp =\u003e {\n  })\n```  \n\n## Use Interceptors\n\n```js\nimport { LayerRequest, globalLayerConfigManager } from '@feugene/layer-request'\n\n/**\n * @param {LayerConfig} layerConfig\n * @param {ExtraProperties} requestExtra\n */\nconst ConsoleLogRequestInterceptor = (layerConfig, requestExtra) =\u003e\n  /**\n   * @param {AxiosRequestConfig} axiosRequestConfig\n   * @return {AxiosRequestConfig}\n   */\n    (axiosRequestConfig) =\u003e {\n    console.info(\n      `\\t🌐 [${axiosRequestConfig.method.toUpperCase()}] ${axiosRequestConfig.baseURL}/${axiosRequestConfig.url}`,\n    )\n    return axiosRequestConfig\n  }\n\n/**\n * @param {boolean} disableLogging\n */\nconst errHandler = (disableLogging) =\u003e\n  /**\n   * @param {AxiosError} error\n   * @return {Promise\u003cAxiosError\u003e}\n   */\n    (error) =\u003e {\n    if (disableLogging) {\n      return\n    }\n    \n    console.info(\n      `\\t❌ [${error.response.config.method.toUpperCase()}]  ${\n        error.response.request.responseURL || error.response.request.res.responseUrl\n      }`,\n    )\n    return Promise.reject(error)\n  }\n\n/**\n *\n * @param {AxiosResponse} response\n * @return {AxiosResponse}\n */\nconst successHandler = (response) =\u003e {\n  console.info(\n    `\\t✅ [${response.config.method.toUpperCase()}]  ${\n      response.request.responseURL || response.request.res.responseUrl\n    }`,\n  )\n  return response\n}\n\n/**\n * @param {LayerConfig} layerConfig\n * @param {ExtraProperties} requestExtra\n * @return {[(function(AxiosResponse): AxiosResponse),(function(AxiosError): Promise\u003cAxiosError\u003e)]}\n * @constructor\n */\nconst ConsoleLogResponseInterceptor = (layerConfig, requestExtra) =\u003e [successHandler, errHandler(layerConfig.getExtra('disableErrorLogging'))]\n\nconst apiRequestConfig = {\n  axiosRequestConfig: {\n    baseURL: '/api',\n  },\n  interceptors: {\n    request: [ConsoleLogRequestInterceptor],\n    response: [ConsoleLogResponseInterceptor],\n  },\n}\n\nconst layerApi = globalLayerConfigManager.addLayer(apiRequestConfig, 'api')\n\nconst layerRequest = new LayerRequest()\nconst request = layerRequest.useConfig('api', { disableErrorLogging: true })\n\nrequest.get('/') // will not be logging http errors\n```  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefureev%2Flayer-request","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fefureev%2Flayer-request","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefureev%2Flayer-request/lists"}