You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

resource.ts 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { Client } from './client'
  2. import method, { MethodSpec, MethodFactory } from './method'
  3. const defaultBaseSpecs: { [k: string]: MethodSpec } = {
  4. list: {
  5. path: '/',
  6. method: 'GET',
  7. },
  8. get: {
  9. path: '/:id',
  10. method: 'GET',
  11. },
  12. edit: {
  13. path: '/:id',
  14. method: 'PUT',
  15. },
  16. add: {
  17. path: '/',
  18. method: 'POST',
  19. },
  20. del: {
  21. path: '/:id',
  22. method: 'DELETE',
  23. },
  24. }
  25. export interface ResourceConfig {
  26. baseRoute: string,
  27. enabledRoutes?: string[],
  28. extraMethods?: { [k:string]: MethodSpec },
  29. }
  30. export type ResourceFactory = (config: ResourceConfig) => Resource
  31. export class Resource {
  32. client: Client
  33. baseRoute: string
  34. enabledRoutes: string[]
  35. methodFactory: MethodFactory
  36. constructor (client: Client, config: ResourceConfig) {
  37. const {
  38. baseRoute,
  39. extraMethods = {},
  40. enabledRoutes = Object.keys(defaultBaseSpecs),
  41. } = config
  42. this.client = client
  43. this.baseRoute = baseRoute.trim()
  44. if (this.baseRoute.endsWith('/')) this.baseRoute = this.baseRoute.slice(0, -1)
  45. this.enabledRoutes = enabledRoutes
  46. this.methodFactory = this.generateMethodFactory()
  47. this.initialize()
  48. this.setExtraMethods(extraMethods)
  49. }
  50. initialize () {
  51. this.enabledRoutes.forEach((route) => {
  52. const routeMethod = this.methodFromRoute(route)
  53. Object.defineProperty(this, route, {
  54. value: routeMethod,
  55. writable: false,
  56. enumerable: true, // TODO: is it okay to have them enumerable ?
  57. })
  58. // Add is aliased as set
  59. if (route === 'add') {
  60. Object.defineProperty(this, 'set', {
  61. value: routeMethod,
  62. writable: false,
  63. enumerable: true, // TODO: is it okay to have them enumerable ?
  64. })
  65. }
  66. // Del is aliased as delete
  67. if (route === 'del') {
  68. Object.defineProperty(this, 'delete', {
  69. value: routeMethod,
  70. writable: false,
  71. enumerable: true, // TODO: is it okay to have them enumerable ?
  72. })
  73. }
  74. })
  75. }
  76. methodFromRoute (route: string) {
  77. let spec = defaultBaseSpecs[route]
  78. const prefix = this.baseRoute
  79. const suffix = spec.path
  80. spec = {
  81. ...spec,
  82. path: `${prefix}${suffix}`
  83. }
  84. return this.methodFactory(spec)
  85. }
  86. generateMethodFactory () {
  87. return method(this.client)
  88. }
  89. setExtraMethods (extraMethods?: { [k:string]: any }) {
  90. if (!extraMethods) return
  91. Object.entries(extraMethods)
  92. .forEach(([method, spec]) => {
  93. // TODO: should it be prefixed by basePath ?
  94. const fn = this.methodFactory(spec)
  95. Object.defineProperty(this, method, {
  96. value: fn,
  97. writable: false,
  98. enumerable: true, // TODO: is it okay to have them enumerable ?
  99. })
  100. })
  101. }
  102. }
  103. export default function resrouceGenerator (client: Client): ResourceFactory {
  104. return function (config: ResourceConfig): Resource {
  105. return new Resource(client, config)
  106. }
  107. }