I am trying to find the best method to create swappable providers for mock/live data in an Angular 2 / Ionic 2 app.
I wish to define the Providers path only once, and then use that defined service class throughout the rest of the app.
At the moment I have generated the following file structure.
├── src/
│ ├── app
│ │ ├── app.component.ts
│ │ ├── app.module.ts
│ │ ├── ...
│ ├── providers
│ │ ├── providers.service.ts
│ │ ├── api
│ │ │ ├── product.service.ts
│ │ │ ├── ...
│ │ ├── mock
│ │ │ ├── product.service.ts
│ │ │ ├── ...
│ │ ├── local
│ │ │ ├── events.service.ts
│ │ │ ├── settings.service.ts
│ │ │ ├── ...
The approach I am attempting to use is to declare the paths of the services only once, in providers.service.ts (below).
providers.service.ts
// Local
import { EventService } from './local/event.service';
import { SettingsService } from './local/settings.service';
// API
import { ContentfulService } from './api/contentful.service';
// import { ProductService } from './api/product.service';
// import { ProductService } from './api/product.service';
// import { CartService } from './api/cart.service';
// import { WatchListService } from './api/watchlist.service';
// import { MediaModelService } from './api/media-model.service';
// Mock
import { MockService } from './mock/mock.service';
import { ProductService } from './mock/product.service';
import { CartService } from './mock/cart.service';
import { WatchListService } from './mock/watchlist.service';
import { MediaModelService } from './mock/media-model.service';
export {
EventService,
SettingsService,
ContentfulService,
ProductService,
CartService,
WatchListService,
MockService,
MediaModelService
};
As you can see this class essentially defines the providers and their paths, and I can swap which mock/live services are used. I can then import each of these services throughout the app by simply pointing the import statement to this file only, and not the full relative path of each e.g.
import {EventService} from '../providers/providers.service';
import {ProductService} from '../providers/providers.service';
This works for the most part, however, issues begin to arise when one service requires the other.
e.g. CartService requires ProductService as part of it’s constructor.
cart.service.ts
import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import {Storage} from '@ionic/storage';
import {EventService} from '../providers.service';
import {ProductService} from '../providers.service';
@Injectable()
export class CartService {
constructor(public storage: Storage, public http: Http, public productService: ProductService, public event: EventService) {
}
}
This results in the following error:
Uncaught TypeError: Cannot read property 'prototype' of undefined
at __extends (media-model.service.ts:48)
at product.service.ts:10
at Object.<anonymous> (product.service.ts:66)
at __webpack_require__ (bootstrap ac59def…:19)
at Object.<anonymous> (main.js:6886)
at __webpack_require__ (bootstrap ac59def…:19)
at Object.<anonymous> (main.js:121964)
at __webpack_require__ (bootstrap ac59def…:19)
at Object.<anonymous> (main.js:110562)
at __webpack_require__ (bootstrap ac59def…:19)
The strange thing is, is that media-model service isn’t used or declared anywhere in relation to product.service. It is as though it is trying to resolve everything in the providers.service.ts. I feel like I am really close, but I just can’t see the issue!
p.s. The providers are declared the main app module/component correctly. If I swap their import paths to their true relative paths rather than via the providers.service.ts approach it’s all good.
Does anyone have an idea why this approach doesn’t work? To me its seems like a dependency issue, but I’m not 100% sure how I can resolve, or if the approach would never work.
Would love some enlightenment.