resolveModel.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. const path = require('path');
  2. const once = require('../utils/objectUtils').once;
  3. const getModel = once(() => require('../model/Model'));
  4. const { isSubclassOf } = require('../utils/classUtils');
  5. function resolveModel(modelRef, modelPaths, errorPrefix) {
  6. const Model = getModel();
  7. if (typeof modelRef === 'string') {
  8. const modulePath = modelRef;
  9. let ModelClass = null;
  10. if (isAbsolutePath(modulePath)) {
  11. ModelClass = requireModel(modulePath, errorPrefix);
  12. } else if (modelPaths) {
  13. modelPaths.forEach(modelPath => {
  14. if (ModelClass === null) {
  15. ModelClass = requireModel(path.join(modelPath, modulePath), errorPrefix);
  16. }
  17. });
  18. }
  19. if (!isSubclassOf(ModelClass, Model)) {
  20. throw new Error(`${errorPrefix}: ${modulePath} is an invalid file path to a model class`);
  21. }
  22. return ModelClass;
  23. } else {
  24. if (!isSubclassOf(modelRef, Model)) {
  25. throw new Error(
  26. `${errorPrefix} is not a subclass of Model or a file path to a module that exports one. You may be dealing with a require loop. See the documentation section about require loops.`
  27. );
  28. }
  29. return modelRef;
  30. }
  31. }
  32. function requireModel(path, errorPrefix) {
  33. const Model = getModel();
  34. let mod = null;
  35. let ModelClass = null;
  36. try {
  37. mod = require(path);
  38. } catch (err) {
  39. return null;
  40. }
  41. if (isSubclassOf(mod, Model)) {
  42. ModelClass = mod;
  43. } else if (isSubclassOf(mod.default, Model)) {
  44. // Babel 6 style of exposing default export.
  45. ModelClass = mod.default;
  46. } else {
  47. Object.keys(mod).forEach(exportName => {
  48. const exp = mod[exportName];
  49. if (isSubclassOf(exp, Model)) {
  50. if (ModelClass !== null) {
  51. throw new Error(
  52. `${errorPrefix} path ${path} exports multiple models. Don't know which one to choose.`
  53. );
  54. }
  55. ModelClass = exp;
  56. }
  57. });
  58. }
  59. return ModelClass;
  60. }
  61. function isAbsolutePath(pth) {
  62. return path.normalize(pth + '/') === path.normalize(path.resolve(pth) + '/');
  63. }
  64. module.exports = {
  65. resolveModel
  66. };