title: refactor data service in Vue project
body: <p>In a Vue project that's underway, the files which are responsible for communicating with the API have been grouped into a "services" section.  While the code shown below works fine as written, it seems like simplifying it would be beneficial due to these factors:</p>
  
  <ol>
  <li>there will be several more API specific files needed to support the project</li>
  <li>the code in the 2 example API specific files shown below is essentially the same except for the value in the <code>resource</code> const</li>
  </ol>
  
  <p><strong>src/services/service.js</strong></p>
  
  <pre><code>import axios from 'axios';
  
  export default axios.create({
      baseURL: 'advancedplanningextension/api/'
  })
  </code></pre>
  
  <p>API specific files -<br>
  <strong>src/services/official-scenarios-service.js</strong></p>
  
  <pre><code>import service from './service';
  
  const resource = 'scenariolog';
  
  export default {
      get() {
          return service.get(`${resource}`);
      }
  }
  </code></pre>
  
  <p><strong>src/services/parameters-service.js</strong></p>
  
  <pre><code>import service from './service';
  
  const resource = 'parameter';
  
  export default {
      get() {
          return service.get(`${resource}`);
      }
  }
  </code></pre>
  
  <p>file to choose the right API specific file -<br>
  <strong>src/services/service-factory.js</strong></p>
  
  <pre><code>import OfficialScenariosService from './official-scenarios-service';
  import ParametersService from './parameters-service';
  
  const services = {
      officialScenarios: OfficialScenariosService,
      parameters: ParametersService
      // add more here
  }
  
  export const ServiceFactory = {
      get: name =&gt; services[name]
  }
  </code></pre>
  
  <p>plugin file -<br>
  <strong>src/plugins/service.js</strong></p>
  
  <pre><code>import { ServiceFactory } from '../services/service-factory';
  
  export default {
      install: function(Vue) {
          Object.defineProperty(Vue.prototype, '$service', { value: ServiceFactory });
      }
  }
  </code></pre>
  
  <p>pertinent code in <strong>src/main.js</strong> that shows wiring of plugin file -</p>
  
  <pre><code>import ServicePlugin from './plugins/service';
  Vue.use(ServicePlugin);
  </code></pre>
  
  <p>Example usage in <strong>src/views/official-scenarios.vue</strong> -<br></p>
  
  <pre><code>&lt;template&gt;
      {{ officialScenarios }}
  &lt;/template&gt;
  
  &lt;script&gt;
  export default {
      data() {
          return {
                  officialScenarios: []                
          }
      },
      methods: {
          async getOfficialScenarios() {
              const { data } = await this.$service.get('officialScenarios').get();            
              this.officialScenarios = data;
          }
      },
      mounted: function () {
          this.getOfficialScenarios(); 
      }
  }
  &lt;/script&gt;
  </code></pre>
  
  <p>I tried creating a <strong>src/services/generic-service.js</strong> file (to replace the 2 API specific files), with the intent of calling that from src/services/service-factory.js, but quickly realized I didn't know how to populate the <code>resource</code> when it was called in that manner.<br>
  <strong>src/services/generic-service.js</strong> -</p>
  
  <pre><code>import service from './service';
  
  let resource = '';  // don't know how to populate this from caller service-factory.js to access the correct API
  
  export default {
      get() {
          return service.get(`${resource}`);
      }
  }
  </code></pre>
  
  <p>Is there a way to set the <code>resource</code> variable when <strong>service-factory.js</strong> calls the <strong>generic-service.js</strong> file?  Or perhaps there is a way to incorporate the logic from <strong>generic-service.js</strong> directly into <strong>service-factory.js</strong>...?  Or maybe there is a simpler approach than these options...?</p>
  
  <h2><br></h2>
  
  <p><br>
  <strong>OUTCOME</strong>
  Many thanks to @Estus Flask for the answer and follow up information.  For now, I decided to put all the services logic into src/services/index.js.  If the project grows beyond needing more than <code>createService</code> I'll deal with refactoring at that point.  Below is the code that seems to be working -<br>
  <strong>src/services/index.js</strong> -</p>
  
  <pre><code>import axios from 'axios';
  
  const axiosInstance = axios.create({
      baseURL: 'advancedplanningextension/api/'
  });
  
  const createService = resource =&gt; ({
      get() {
          return axiosInstance.get(`${resource}`);
      }
      // add more here
  });
  
  const resources = {
      officialScenarios: 'scenariolog',
      parameters: 'parameter'
      // add more here
  }
  
  export const service = {
      get: name =&gt; createService(resources[name])
  }
  </code></pre>
  
  <p>The values in <code>resources</code> are the specific API endpoints.  So when the code calls the service for officialScenarios for example, the URL for that API endpoint will be 'advancedplanningextension/api/scenariolog'.</p>
  
  <p><strong>src/plugins/service.js</strong> -</p>
  
  <pre><code>import { service } from '../services/index';
  
  export default {
      install: function(Vue) {
          Object.defineProperty(Vue.prototype, '$service', { value: service });
      }
  }
  </code></pre>
  
  <p>Example usage in src/views/official-scenarios.vue remains the same as shown in the original question.</p>