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 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. route = route.toLowerCase()
  53. const routeMethod = this.methodFromRoute(route)
  54. Object.defineProperty(this, route, {
  55. value: routeMethod,
  56. writable: false,
  57. enumerable: true,
  58. })
  59. // Add is aliased as set
  60. if (route === 'add') {
  61. Object.defineProperty(this, 'set', {
  62. value: routeMethod,
  63. writable: false,
  64. enumerable: true,
  65. })
  66. }
  67. // Del is aliased as delete
  68. if (route === 'del') {
  69. Object.defineProperty(this, 'delete', {
  70. value: routeMethod,
  71. writable: false,
  72. enumerable: true,
  73. })
  74. }
  75. })
  76. }
  77. methodFromRoute (route: string) {
  78. let spec = defaultBaseSpecs[route]
  79. if (!spec) throw new Error(`An unsupported default route, ${route}, requested.`)
  80. const prefix = this.baseRoute
  81. const suffix = spec.path
  82. spec = {
  83. ...spec,
  84. path: `${prefix}${suffix}`
  85. }
  86. return this.methodFactory(spec)
  87. }
  88. generateMethodFactory () {
  89. return method(this.client)
  90. }
  91. setExtraMethods (extraMethods?: { [k:string]: MethodSpec }) {
  92. if (!extraMethods) return
  93. Object.entries(extraMethods)
  94. .forEach(([method, spec]) => {
  95. const sep = spec.path.startsWith('/') ? '' : '/'
  96. spec = {
  97. ...spec,
  98. path: `${this.baseRoute}${sep}${spec.path}`,
  99. }
  100. const fn = this.methodFactory(spec)
  101. Object.defineProperty(this, method, {
  102. value: fn,
  103. writable: false,
  104. enumerable: true,
  105. })
  106. })
  107. }
  108. }
  109. export default function resrouceGenerator (client: Client): ResourceFactory {
  110. return function (config: ResourceConfig): Resource {
  111. return new Resource(client, config)
  112. }
  113. }