Home Reference Source

src/types/index.js

  1. import Immutable from 'immutable';
  2.  
  3. import TypeClass from './type';
  4. import {registerDataTypes, registerViewTypes} from './register';
  5.  
  6. /**
  7. * Constant that represents data types.
  8. */
  9. export const DATA = 'data';
  10. /**
  11. * Constant that represents view types.
  12. */
  13. export const VIEW = 'view';
  14.  
  15. /**
  16. * The pool of data types. When a new data type is registered, it is stored
  17. * here `Type.typeName -> Type`.
  18. */
  19. export const data = {};
  20. /**
  21. * The pool of view types. When a new view type is registered, it is stored
  22. * here `Type.typeName -> Type`.
  23. */
  24. export const view = {};
  25.  
  26. const types = {
  27. [DATA]: data,
  28. [VIEW]: view
  29. };
  30.  
  31. registerDataTypes(registerType.bind(null, DATA));
  32. registerViewTypes(registerType.bind(null, VIEW));
  33.  
  34. /**
  35. * Registers a custom data or view type. They must inherit from the appropriate
  36. * base class (see {@link DataType} and {@link ViewType}).
  37. *
  38. * @param type - One of `Types.DATA`, `Types.VIEW`
  39. * @param {DataType|ViewType} Type - The class to be registered
  40. * @throws Will throw an error if an invalid `type` is passed in.
  41. */
  42. export function registerType(type, Type) {
  43. if (!types[type]) {
  44. throw new Error(`The type "${type}" does not exist. (while creating "${Type.typeName}")`);
  45. }
  46.  
  47. if (!Type.typeName) {
  48. throw new Error('A Type without a name cannot be registered');
  49. }
  50.  
  51. // Bro, do you even type??
  52. types[type][Type.typeName] = Type;
  53. }
  54.  
  55. /**
  56. * Parse an Immutable Map object and return the resulting field. The Immutable
  57. * Map field must contain a `type` field which represents the `typeName` to
  58. * attempt to parse the field as.
  59. *
  60. * @param type - One of `Types.DATA`, `Types.VIEW`
  61. * @param {Immutable.Map} field - The field represented by an Immutable Map.
  62. * @throws Will throw an error if an invalid `type` or `field.get('type')` is passed in.
  63. */
  64. export function parseField(type, field) {
  65. if (!types[type]) {
  66. throw new Error(`The type "${type}" does not exist (with field: "${field}")`);
  67. }
  68.  
  69. if (!field) {
  70. throw new Error(`Cannot parse a null field (of type: "${type}")`);
  71. }
  72.  
  73. if (field instanceof TypeClass) {
  74. return field;
  75. }
  76.  
  77. if (type == VIEW && typeof field == 'string') {
  78. // Allow named view type lookups.
  79. return field;
  80. }
  81.  
  82. field = Immutable.fromJS(field);
  83.  
  84. if (!field.get('type')) {
  85. throw new Error(`Cannot parse a field with an empty type (with type and field: "${type}" "${field}")`);
  86. }
  87.  
  88. if (!types[type][field.get('type')]) {
  89. throw new Error(`Invalid field of type "${field.get('type')}" (with type and field: "${type}", "${field}")`);
  90. }
  91.  
  92. return types[type][field.get('type')].parse(field, parseField.bind(null, type));
  93. }