@ditojs/server 0.273.0 → 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/package.json +26 -44
  2. package/src/app/Application.js +121 -117
  3. package/src/app/Validator.js +6 -3
  4. package/src/app/index.js +2 -2
  5. package/src/cli/console.js +3 -3
  6. package/src/cli/db/createMigration.js +4 -4
  7. package/src/cli/db/index.js +7 -7
  8. package/src/cli/db/listAssetConfig.js +1 -1
  9. package/src/cli/db/migrate.js +4 -4
  10. package/src/cli/db/reset.js +5 -5
  11. package/src/cli/db/rollback.js +4 -4
  12. package/src/cli/db/seed.js +6 -6
  13. package/src/cli/db/unlock.js +2 -2
  14. package/src/cli/index.js +17 -8
  15. package/src/controllers/AdminController.js +164 -158
  16. package/src/controllers/CollectionController.js +8 -29
  17. package/src/controllers/Controller.js +78 -83
  18. package/src/controllers/ControllerAction.js +37 -18
  19. package/src/controllers/MemberAction.js +2 -2
  20. package/src/controllers/ModelController.js +4 -4
  21. package/src/controllers/RelationController.js +5 -5
  22. package/src/controllers/{UserController.js → UsersController.js} +8 -13
  23. package/src/controllers/index.js +5 -5
  24. package/src/decorators/action.js +3 -3
  25. package/src/decorators/authorize.js +1 -1
  26. package/src/decorators/index.js +6 -6
  27. package/src/decorators/parameters.js +1 -1
  28. package/src/decorators/returns.js +1 -1
  29. package/src/decorators/scope.js +1 -1
  30. package/src/decorators/transacted.js +1 -1
  31. package/src/errors/AssetError.js +1 -1
  32. package/src/errors/AuthenticationError.js +1 -1
  33. package/src/errors/AuthorizationError.js +1 -1
  34. package/src/errors/ControllerError.js +1 -1
  35. package/src/errors/DatabaseError.js +12 -3
  36. package/src/errors/GraphError.js +1 -1
  37. package/src/errors/ModelError.js +1 -1
  38. package/src/errors/NotFoundError.js +1 -1
  39. package/src/errors/NotImplementedError.js +1 -1
  40. package/src/errors/QueryBuilderError.js +1 -1
  41. package/src/errors/RelationError.js +1 -1
  42. package/src/errors/ValidationError.js +1 -1
  43. package/src/errors/WrappedError.js +1 -1
  44. package/src/errors/index.js +14 -14
  45. package/src/graph/DitoGraphProcessor.js +2 -1
  46. package/src/graph/graph.js +1 -1
  47. package/src/graph/index.js +3 -3
  48. package/src/index.js +11 -9
  49. package/src/lib/index.js +2 -2
  50. package/src/middleware/createTransaction.js +1 -1
  51. package/src/middleware/findRoute.js +3 -2
  52. package/src/middleware/handleConnectMiddleware.js +88 -0
  53. package/src/middleware/handleError.js +1 -1
  54. package/src/middleware/handleRoute.js +3 -3
  55. package/src/middleware/index.js +8 -7
  56. package/src/middleware/logRequests.js +9 -9
  57. package/src/mixins/AssetMixin.js +1 -1
  58. package/src/mixins/UserMixin.js +1 -1
  59. package/src/mixins/index.js +4 -4
  60. package/src/models/AssetModel.js +2 -2
  61. package/src/models/Model.js +16 -12
  62. package/src/models/RelationAccessor.js +1 -1
  63. package/src/models/SessionModel.js +2 -2
  64. package/src/models/TimeStampedModel.js +2 -2
  65. package/src/models/UserModel.js +2 -2
  66. package/src/models/definitions/assets.js +1 -1
  67. package/src/models/definitions/filters.js +57 -44
  68. package/src/models/definitions/hooks.js +1 -1
  69. package/src/models/definitions/index.js +9 -9
  70. package/src/models/definitions/modifiers.js +1 -1
  71. package/src/models/definitions/options.js +1 -1
  72. package/src/models/definitions/properties.js +2 -2
  73. package/src/models/definitions/relations.js +1 -1
  74. package/src/models/definitions/schema.js +1 -1
  75. package/src/models/definitions/scopes.js +2 -2
  76. package/src/models/index.js +5 -5
  77. package/src/query/QueryBuilder.js +5 -5
  78. package/src/query/QueryFilters.js +50 -50
  79. package/src/query/QueryParameters.js +2 -2
  80. package/src/query/index.js +3 -3
  81. package/src/schema/formats/index.js +2 -2
  82. package/src/schema/index.js +4 -4
  83. package/src/schema/keywords/_relate.js +1 -1
  84. package/src/schema/keywords/index.js +12 -12
  85. package/src/schema/properties.test.js +1 -1
  86. package/src/schema/relations.js +1 -1
  87. package/src/schema/relations.test.js +2 -2
  88. package/src/services/index.js +1 -1
  89. package/src/storage/DiskStorage.js +1 -1
  90. package/src/storage/S3Storage.js +4 -4
  91. package/src/storage/Storage.js +1 -1
  92. package/src/storage/index.js +4 -4
  93. package/src/utils/function.test.js +1 -1
  94. package/src/utils/handler.js +17 -0
  95. package/src/utils/index.js +8 -7
  96. package/src/utils/object.test.js +1 -1
  97. package/lib/app/Application.js +0 -955
  98. package/lib/app/SessionStore.js +0 -40
  99. package/lib/app/Validator.js +0 -355
  100. package/lib/app/index.js +0 -26
  101. package/lib/cli/console.js +0 -175
  102. package/lib/cli/db/createMigration.js +0 -237
  103. package/lib/cli/db/index.js +0 -66
  104. package/lib/cli/db/listAssetConfig.js +0 -16
  105. package/lib/cli/db/migrate.js +0 -15
  106. package/lib/cli/db/reset.js +0 -27
  107. package/lib/cli/db/rollback.js +0 -15
  108. package/lib/cli/db/seed.js +0 -104
  109. package/lib/cli/db/unlock.js +0 -15
  110. package/lib/cli/index.js +0 -90
  111. package/lib/controllers/AdminController.js +0 -258
  112. package/lib/controllers/CollectionController.js +0 -263
  113. package/lib/controllers/Controller.js +0 -462
  114. package/lib/controllers/ControllerAction.js +0 -276
  115. package/lib/controllers/MemberAction.js +0 -22
  116. package/lib/controllers/ModelController.js +0 -64
  117. package/lib/controllers/RelationController.js +0 -82
  118. package/lib/controllers/UserController.js +0 -98
  119. package/lib/controllers/index.js +0 -50
  120. package/lib/decorators/action.js +0 -14
  121. package/lib/decorators/authorize.js +0 -13
  122. package/lib/decorators/index.js +0 -58
  123. package/lib/decorators/parameters.js +0 -35
  124. package/lib/decorators/returns.js +0 -26
  125. package/lib/decorators/scope.js +0 -14
  126. package/lib/decorators/transacted.js +0 -12
  127. package/lib/errors/AssetError.js +0 -19
  128. package/lib/errors/AuthenticationError.js +0 -19
  129. package/lib/errors/AuthorizationError.js +0 -19
  130. package/lib/errors/ControllerError.js +0 -24
  131. package/lib/errors/DatabaseError.js +0 -27
  132. package/lib/errors/GraphError.js +0 -19
  133. package/lib/errors/ModelError.js +0 -24
  134. package/lib/errors/NotFoundError.js +0 -19
  135. package/lib/errors/NotImplementedError.js +0 -19
  136. package/lib/errors/QueryBuilderError.js +0 -19
  137. package/lib/errors/RelationError.js +0 -36
  138. package/lib/errors/ResponseError.js +0 -46
  139. package/lib/errors/ValidationError.js +0 -19
  140. package/lib/errors/WrappedError.js +0 -24
  141. package/lib/errors/index.js +0 -122
  142. package/lib/graph/DitoGraphProcessor.js +0 -185
  143. package/lib/graph/expression.js +0 -76
  144. package/lib/graph/graph.js +0 -300
  145. package/lib/graph/index.js +0 -34
  146. package/lib/index.js +0 -82
  147. package/lib/lib/EventEmitter.js +0 -76
  148. package/lib/lib/KnexHelper.js +0 -40
  149. package/lib/lib/index.js +0 -26
  150. package/lib/middleware/attachLogger.js +0 -16
  151. package/lib/middleware/createTransaction.js +0 -36
  152. package/lib/middleware/findRoute.js +0 -35
  153. package/lib/middleware/handleError.js +0 -26
  154. package/lib/middleware/handleRoute.js +0 -29
  155. package/lib/middleware/handleUser.js +0 -36
  156. package/lib/middleware/index.js +0 -66
  157. package/lib/middleware/logRequests.js +0 -122
  158. package/lib/mixins/AssetMixin.js +0 -81
  159. package/lib/mixins/SessionMixin.js +0 -22
  160. package/lib/mixins/TimeStampedMixin.js +0 -47
  161. package/lib/mixins/UserMixin.js +0 -151
  162. package/lib/mixins/index.js +0 -42
  163. package/lib/models/AssetModel.js +0 -12
  164. package/lib/models/Model.js +0 -953
  165. package/lib/models/RelationAccessor.js +0 -41
  166. package/lib/models/SessionModel.js +0 -12
  167. package/lib/models/TimeStampedModel.js +0 -12
  168. package/lib/models/UserModel.js +0 -12
  169. package/lib/models/definitions/assets.js +0 -11
  170. package/lib/models/definitions/filters.js +0 -101
  171. package/lib/models/definitions/hooks.js +0 -11
  172. package/lib/models/definitions/index.js +0 -38
  173. package/lib/models/definitions/modifiers.js +0 -11
  174. package/lib/models/definitions/options.js +0 -11
  175. package/lib/models/definitions/properties.js +0 -87
  176. package/lib/models/definitions/relations.js +0 -11
  177. package/lib/models/definitions/schema.js +0 -11
  178. package/lib/models/definitions/scopes.js +0 -51
  179. package/lib/models/index.js +0 -50
  180. package/lib/query/QueryBuilder.js +0 -745
  181. package/lib/query/QueryFilters.js +0 -82
  182. package/lib/query/QueryParameters.js +0 -77
  183. package/lib/query/Registry.js +0 -40
  184. package/lib/query/index.js +0 -34
  185. package/lib/schema/formats/_empty.js +0 -10
  186. package/lib/schema/formats/_required.js +0 -10
  187. package/lib/schema/formats/index.js +0 -26
  188. package/lib/schema/index.js +0 -49
  189. package/lib/schema/keywords/_computed.js +0 -11
  190. package/lib/schema/keywords/_foreign.js +0 -11
  191. package/lib/schema/keywords/_hidden.js +0 -11
  192. package/lib/schema/keywords/_index.js +0 -11
  193. package/lib/schema/keywords/_instanceof.js +0 -49
  194. package/lib/schema/keywords/_primary.js +0 -11
  195. package/lib/schema/keywords/_range.js +0 -26
  196. package/lib/schema/keywords/_relate.js +0 -19
  197. package/lib/schema/keywords/_specificType.js +0 -11
  198. package/lib/schema/keywords/_unique.js +0 -11
  199. package/lib/schema/keywords/_unsigned.js +0 -11
  200. package/lib/schema/keywords/_validate.js +0 -80
  201. package/lib/schema/keywords/index.js +0 -106
  202. package/lib/schema/properties.js +0 -227
  203. package/lib/schema/properties.test.js +0 -573
  204. package/lib/schema/relations.js +0 -274
  205. package/lib/schema/relations.test.js +0 -155
  206. package/lib/services/Service.js +0 -34
  207. package/lib/services/index.js +0 -18
  208. package/lib/storage/AssetFile.js +0 -97
  209. package/lib/storage/DiskStorage.js +0 -125
  210. package/lib/storage/S3Storage.js +0 -171
  211. package/lib/storage/Storage.js +0 -209
  212. package/lib/storage/index.js +0 -34
  213. package/lib/utils/decorator.js +0 -16
  214. package/lib/utils/deprecate.js +0 -46
  215. package/lib/utils/emitter.js +0 -13
  216. package/lib/utils/function.js +0 -14
  217. package/lib/utils/function.test.js +0 -49
  218. package/lib/utils/index.js +0 -66
  219. package/lib/utils/json.js +0 -9
  220. package/lib/utils/object.js +0 -92
  221. package/lib/utils/object.test.js +0 -65
  222. package/lib/utils/scope.js +0 -14
@@ -1,11 +1,14 @@
1
- import chalk from 'chalk'
2
- import { getOwnProperty, getAllKeys, describeFunction } from '@/utils'
3
- import { EventEmitter } from '@/lib'
4
- import ControllerAction from './ControllerAction'
5
- import MemberAction from './MemberAction'
1
+ import pico from 'picocolors'
2
+ import { EventEmitter } from '../lib/index.js'
3
+ import ControllerAction from './ControllerAction.js'
4
+ import MemberAction from './MemberAction.js'
6
5
  import {
7
6
  ResponseError, WrappedError, ControllerError, AuthorizationError
8
- } from '@/errors'
7
+ } from '../errors/index.js'
8
+ import {
9
+ getOwnProperty, getAllKeys, processHandlerParameters, describeFunction,
10
+ formatJson, deprecate
11
+ } from '../utils/index.js'
9
12
  import {
10
13
  isObject, isString, isArray, isBoolean, isFunction, asArray, equals,
11
14
  parseDataPath, normalizeDataPath
@@ -44,11 +47,11 @@ export class Controller {
44
47
  this.url = namespace ? `/${namespace}${url}` : url
45
48
  this.log(
46
49
  `${
47
- namespace ? chalk.green(`/${namespace}/`) : ''
50
+ namespace ? pico.green(`/${namespace}/`) : ''
48
51
  }${
49
- chalk.cyan(path)
52
+ pico.cyan(path)
50
53
  }${
51
- chalk.white(':')
54
+ pico.white(':')
52
55
  }`,
53
56
  this.level
54
57
  )
@@ -73,10 +76,10 @@ export class Controller {
73
76
 
74
77
  const addAction = key => {
75
78
  const value = this[key]
76
- // NOTE: Only add instance methods that have a @action() decorator,
77
- // which in turn sets the `verb` property on the method, or action objects
78
- // which have the `verb` property:
79
- if (value?.verb) {
79
+ // NOTE: Only add instance methods that have a @action() decorator, which
80
+ // in turn sets the `method` property on the method, as well as action
81
+ // objects which provide the `method` property:
82
+ if (value?.method) {
80
83
  controller[key] = value
81
84
  }
82
85
  }
@@ -89,20 +92,20 @@ export class Controller {
89
92
  return controller
90
93
  }
91
94
 
92
- setupRoute(verb, url, transacted, authorize, action, handlers) {
95
+ setupRoute(method, url, transacted, authorize, action, middlewares) {
93
96
  this.log(
94
97
  `${
95
- chalk.magenta(verb.toUpperCase())
98
+ pico.magenta(method.toUpperCase())
96
99
  } ${
97
- chalk.green(this.url)
100
+ pico.green(this.url)
98
101
  }${
99
- chalk.cyan(url.slice(this.url.length))
102
+ pico.cyan(url.slice(this.url.length))
100
103
  } ${
101
- chalk.white(this.describeAuthorize(authorize))
104
+ pico.white(this.describeAuthorize(authorize))
102
105
  }`,
103
106
  this.level + 1
104
107
  )
105
- this.app.addRoute(verb, url, transacted, handlers, this, action)
108
+ this.app.addRoute(method, url, transacted, middlewares, this, action)
106
109
  }
107
110
 
108
111
  setupActions(type) {
@@ -110,26 +113,25 @@ export class Controller {
110
113
  values: actions,
111
114
  authorize
112
115
  } = this.processValues(this.inheritValues(type))
113
- for (const [name, handler] of Object.entries(actions)) {
114
- this.setupAction(type, actions, name, handler, authorize[name])
116
+ for (const [name, action] of Object.entries(actions)) {
117
+ // Replace the action object with the converted action handler, so they
118
+ // too can benefit from prototypal inheritance:
119
+ actions[name] = this.setupAction(
120
+ type, actions, name, action, authorize[name]
121
+ )
115
122
  }
116
123
  return actions
117
124
  }
118
125
 
119
- setupAction(
120
- type,
121
- actions,
122
- name,
123
- handler,
124
- authorize,
125
- // These values are only changed when called from
126
- // `CollectionController.setupAction()`:
127
- verb = 'get',
128
- // The default path for actions is the normalized name.
129
- path = this.app.normalizePath(name)
130
- ) {
131
- if (!isFunction(handler)) {
132
- handler = setupHandlerFromObject(handler, actions)
126
+ setupAction(type, actions, name, action, authorize) {
127
+ const handler = isFunction(action) ? action
128
+ : isObject(action) ? convertActionObject(name, action, actions)
129
+ : null
130
+ // Action naming convention: `'<method> <path>'`, or just `'<method>'` for
131
+ // the default methods.
132
+ let [method, path = ''] = name.split(' ')
133
+ if (!isMethodAction(method)) {
134
+ path = name
133
135
  }
134
136
  // Custom member actions have their own class so they can fetch the members
135
137
  // ahead of their call.
@@ -137,14 +139,15 @@ export class Controller {
137
139
  this.setupActionRoute(
138
140
  type,
139
141
  // eslint-disable-next-line new-cap
140
- new actionClass(this, handler, type, name, verb, path, authorize)
142
+ new actionClass(this, handler, type, name, method, path, authorize)
141
143
  )
144
+ return handler
142
145
  }
143
146
 
144
147
  setupActionRoute(type, action) {
145
148
  const url = this.getUrl(type, action.path)
146
- const { verb, transacted, authorize } = action
147
- this.setupRoute(verb, url, transacted, authorize, action, [
149
+ const { method, transacted, authorize } = action
150
+ this.setupRoute(method, url, transacted, authorize, action, [
148
151
  async ctx => {
149
152
  try {
150
153
  const res = await action.callAction(ctx)
@@ -232,6 +235,7 @@ export class Controller {
232
235
  ])
233
236
  }
234
237
 
238
+ // @return {Application|Function} [app or function]
235
239
  compose() {
236
240
  // To be overridden in sub-classes, if the controller needs to install
237
241
  // middleware. For normal routes, use `this.app.addRoute()` instead.
@@ -250,11 +254,11 @@ export class Controller {
250
254
 
251
255
  inheritValues(type) {
252
256
  // Gets the controller class's instance field for a given action type, e.g.
253
- // `controller` (Controller), `collection`, `member` (ModelController,
254
- // RelationController), `relation` (RelationController), and sets up an
257
+ // `controller` (`Controller`), `collection`, `member` (`ModelController`,
258
+ // `RelationController`), `relation` (`RelationController`), and sets up an
255
259
  // inheritance chain for it that goes all the way up to it base class (e.g.
256
- // CollectionController), so that the default definitions for all http verbs
257
- // can be correctly inherited and overridden while using `super.<action>()`.
260
+ // `CollectionController`), so that the default definitions for all HTTP
261
+ // methods can be inherited and overridden while using `super.<action>()`.
258
262
  const parentClass = Object.getPrototypeOf(this.constructor)
259
263
  // Create one instance of each controller class up the chain in order to
260
264
  // get to their definitions of the inheritable values. Cache both instance
@@ -389,7 +393,7 @@ export class Controller {
389
393
  return result
390
394
  },
391
395
  // Create a new object for the filtered `values` that keeps inheritance
392
- // intact. This is required by `setupHandlerFromObject()`, to support
396
+ // intact. This is required by `convertActionObject()`, to support
393
397
  // `super` in handler functions.
394
398
  Object.create(Object.getPrototypeOf(values))
395
399
  ),
@@ -400,14 +404,14 @@ export class Controller {
400
404
 
401
405
  async emitHook(type, handleResult, ctx, ...args) {
402
406
  let result = handleResult ? args.shift() : undefined
403
- for (const handler of this.listeners(type)) {
407
+ for (const listener of this.listeners(type)) {
404
408
  if (handleResult) {
405
- const res = await handler.call(this, ctx, result, ...args)
409
+ const res = await listener.call(this, ctx, result, ...args)
406
410
  if (res !== undefined) {
407
411
  result = res
408
412
  }
409
413
  } else {
410
- await handler.call(this, ctx, ...args)
414
+ await listener.call(this, ctx, ...args)
411
415
  }
412
416
  }
413
417
  return result
@@ -503,62 +507,53 @@ EventEmitter.mixin(Controller.prototype)
503
507
 
504
508
  const inheritanceMap = new WeakMap()
505
509
 
506
- function setupHandlerFromObject(object, actions) {
510
+ function convertActionObject(name, object, actions) {
507
511
  const {
508
512
  handler,
509
513
  action,
510
514
  authorize,
515
+ transacted,
516
+ scope,
511
517
  parameters,
512
518
  returns,
513
- scope,
514
- transacted
519
+ ...rest
515
520
  } = object
516
521
 
517
522
  // In order to suport `super` calls in the `handler` function in object
518
523
  // notation, deploy this crazy JS sorcery:
519
524
  Object.setPrototypeOf(object, Object.getPrototypeOf(actions))
520
525
 
521
- handler.authorize = authorize
522
- handler.transacted = transacted
523
-
524
526
  if (action) {
525
- const [verb, path] = asArray(action)
526
- handler.verb = verb
527
+ deprecate(`action.action is deprecated. Use action.method and action.path instead.`)
528
+ const [method, path] = asArray(action)
529
+ handler.method = method
527
530
  handler.path = path
528
531
  }
529
532
 
530
- if (parameters) {
531
- const [_parameters, options] = parameters
532
- const hasOptions = isArray(_parameters)
533
- handler.parameters = hasOptions ? _parameters : parameters
534
-
535
- // If validation options are provided, expose them through
536
- // `handler.options.parameters`, see ControllerAction
537
- if (hasOptions) {
538
- handler.options = {
539
- ...handler.options,
540
- parameters: options
541
- }
542
- }
533
+ if (!handler) {
534
+ throw new Error(`Missing handler in '${name}' action: ${formatJson(object)}`)
543
535
  }
544
536
 
545
- if (returns) {
546
- const [_returns, options] = asArray(returns)
547
- handler.returns = _returns
537
+ handler.authorize = authorize ?? null
538
+ handler.transacted = transacted ?? null
539
+ handler.scope = scope ? asArray(scope) : null
548
540
 
549
- // If validation options are provided, expose them through
550
- // `handler.options.returns`, see ControllerAction
551
- if (options) {
552
- handler.options = {
553
- ...handler.options,
554
- parameters: options
555
- }
556
- }
557
- }
541
+ processHandlerParameters(handler, 'parameters', parameters)
542
+ processHandlerParameters(handler, 'returns', returns)
558
543
 
559
- if (scope) {
560
- handler.scope = asArray(scope)
561
- }
544
+ return Object.assign(handler, rest)
545
+ }
562
546
 
563
- return handler
547
+ function isMethodAction(name) {
548
+ return {
549
+ get: true,
550
+ delete: true,
551
+ post: true,
552
+ put: true,
553
+ patch: true,
554
+ head: true,
555
+ options: true,
556
+ trace: true,
557
+ connect: true
558
+ }[name]
564
559
  }
@@ -1,37 +1,53 @@
1
1
  import { isString, isObject, asArray, clone } from '@ditojs/utils'
2
2
 
3
3
  export default class ControllerAction {
4
- constructor(controller, handler, type, name, verb, path, authorize) {
4
+ constructor(controller, handler, type, name, _method, _path, _authorize) {
5
+ const {
6
+ core = false,
7
+ // Allow decorators on actions to override the predetermined defaults for
8
+ // `method`, `path` and `authorize`:
9
+ // TODO: `handler.method` and `handler.path` were deprecated in March
10
+ // 2022, remove later and only set the valued passed to constructor then.
11
+ method = _method,
12
+ path = _path,
13
+ scope,
14
+ authorize = _authorize,
15
+ transacted = controller.transacted,
16
+ parameters,
17
+ returns,
18
+ options = {},
19
+ ...additional
20
+ } = handler
21
+
5
22
  this.controller = controller
6
23
  this.handler = handler
7
24
  this.type = type
8
25
  this.name = name
9
26
  this.identifier = `${type}:${name}`
10
- // Allow decorators on actions to override the predetermined defaults for
11
- // `verb`, `path` and `authorize`:
12
- this.verb = handler.verb || verb
13
- // Use ?? instead of || to allow '' to override the path.
14
- this.path = handler.path ?? path
15
- this.authorize = handler.authorize || authorize
16
- this.transacted = !!(
17
- handler.transacted ||
18
- controller.transacted ||
19
- // Core graph and assets operations are always transacted, unless the verb
20
- // is 'get':
21
- handler.core && verb !== 'get' && (controller.graph || controller.assets)
27
+ this.method = method
28
+ this.path = path
29
+ this.scope = scope
30
+ this.authorize = authorize
31
+ this.transacted = !!(transacted || (
32
+ // Core graph and assets operations are always transacted, unless the
33
+ // method is 'get':
34
+ core && method !== 'get' && (
35
+ controller.graph ||
36
+ controller.assets
37
+ ))
22
38
  )
23
39
  this.authorization = controller.processAuthorize(this.authorize)
24
40
  this.app = controller.app
25
- this.paramsName = ['post', 'put', 'patch'].includes(this.verb)
41
+ this.paramsName = ['post', 'put', 'patch'].includes(this.method)
26
42
  ? 'body'
27
43
  : 'query'
28
- const { parameters, returns, options = {} } = this.handler
29
44
  this.parameters = this.app.compileParametersValidator(parameters, {
30
45
  async: true,
31
- ...options.parameters, // See @parameters() decorator
46
+ ...options.parameters,
32
47
  dataName: this.paramsName
33
48
  })
34
49
  this.returns = this.app.compileParametersValidator(
50
+ // TODO: Shouldn't we set `this.returns` to null instead?
35
51
  returns ? [returns] : [],
36
52
  {
37
53
  async: true,
@@ -43,12 +59,15 @@ export default class ControllerAction {
43
59
  dataName: 'returns'
44
60
  }
45
61
  )
62
+ // Copy over the additional properties, e.g. `cached` so application
63
+ // middleware can implement caching mechanisms:
64
+ Object.assign(this, additional)
46
65
  }
47
66
 
48
67
  // Possible values for `from` are:
49
68
  // - 'path': Use `ctx.params` which is mapped to the route / path
50
- // - 'query': Use `ctx.request.query`, regardless of the action's verb.
51
- // - 'body': Use `ctx.request.body`, regardless of the action's verb.
69
+ // - 'query': Use `ctx.request.query`, regardless of the action's method.
70
+ // - 'body': Use `ctx.request.body`, regardless of the action's method.
52
71
  getParams(ctx, from = this.paramsName) {
53
72
  const value = from === 'path' ? ctx.params : ctx.request[from]
54
73
  // koa-bodyparser always sets an object, even when there is no body.
@@ -1,4 +1,4 @@
1
- import ControllerAction from './ControllerAction'
1
+ import ControllerAction from './ControllerAction.js'
2
2
 
3
3
  export default class MemberAction extends ControllerAction {
4
4
  // @override
@@ -9,7 +9,7 @@ export default class MemberAction extends ControllerAction {
9
9
 
10
10
  // @override
11
11
  async getMember(ctx, param) {
12
- // member @parameters() can provide special query parameters as well,
12
+ // member parameters can provide special query parameters as well,
13
13
  // and they can even controll `forUpdate()` behavior:
14
14
  // {
15
15
  // member: true,
@@ -1,9 +1,9 @@
1
1
  import pluralize from 'pluralize'
2
2
  import { isObject, camelize } from '@ditojs/utils'
3
- import { ControllerError } from '@/errors'
4
- import { CollectionController } from './CollectionController'
5
- import { RelationController } from './RelationController'
6
- import { setupPropertyInheritance } from '@/utils'
3
+ import { CollectionController } from './CollectionController.js'
4
+ import { RelationController } from './RelationController.js'
5
+ import { ControllerError } from '../errors/index.js'
6
+ import { setupPropertyInheritance } from '../utils/index.js'
7
7
 
8
8
  export class ModelController extends CollectionController {
9
9
  setup() {
@@ -1,8 +1,8 @@
1
- import chalk from 'chalk'
2
- import { ControllerError } from '@/errors'
3
- import { CollectionController } from './CollectionController'
4
- import { setupPropertyInheritance, getScope } from '@/utils'
1
+ import pico from 'picocolors'
5
2
  import { asArray } from '@ditojs/utils'
3
+ import { CollectionController } from './CollectionController.js'
4
+ import { ControllerError } from '../errors/index.js'
5
+ import { setupPropertyInheritance, getScope } from '../utils/index.js'
6
6
 
7
7
  export class RelationController extends CollectionController {
8
8
  constructor(parent, object, relationInstance, relationDefinition) {
@@ -32,7 +32,7 @@ export class RelationController extends CollectionController {
32
32
  // Initialize:
33
33
  this.path = this.app.normalizePath(this.name)
34
34
  this.url = `${this.parent.url}/${this.parent.getPath('member', this.path)}`
35
- this.log(`${chalk.blue(this.path)}${chalk.white(':')}`, this.level)
35
+ this.log(`${pico.blue(this.path)}${pico.white(':')}`, this.level)
36
36
  // Copy over all fields in the relation object except the ones that are
37
37
  // going to be inherited in `setup()` (relation, member, allow), for
38
38
  // settings like scope, etc.
@@ -1,11 +1,8 @@
1
- import { action } from '@/decorators'
2
- import { ModelController } from './ModelController'
1
+ import { ModelController } from './ModelController.js'
3
2
 
4
- // TODO: Rename to UsersController?
5
- export class UserController extends ModelController {
3
+ export class UsersController extends ModelController {
6
4
  collection = {
7
- @action('post')
8
- async login(ctx) {
5
+ async 'post login'(ctx) {
9
6
  let user
10
7
  let error
11
8
  try {
@@ -26,8 +23,7 @@ export class UserController extends ModelController {
26
23
  }
27
24
  },
28
25
 
29
- @action('post')
30
- async logout(ctx) {
26
+ async 'post logout'(ctx) {
31
27
  let success = false
32
28
  if (this.isAuthenticated(ctx)) {
33
29
  await ctx.logout()
@@ -39,19 +35,18 @@ export class UserController extends ModelController {
39
35
  }
40
36
  },
41
37
 
42
- @action('get')
43
- session(ctx) {
38
+ 'get session'(ctx) {
44
39
  const authenticated = this.isAuthenticated(ctx)
45
40
  return {
46
41
  authenticated,
47
42
  user: authenticated ? ctx.state.user : null
43
+
48
44
  }
49
45
  },
50
46
 
51
- @action('get')
52
- self(ctx) {
47
+ 'get self'(ctx) {
53
48
  return this.isAuthenticated(ctx)
54
- ? this.member.find.call(
49
+ ? this.member.get.call(
55
50
  this,
56
51
  this.getContextWithMemberId(ctx, ctx.state.user.$id())
57
52
  )
@@ -1,5 +1,5 @@
1
- export * from './Controller'
2
- export * from './ModelController'
3
- export * from './RelationController'
4
- export * from './AdminController'
5
- export * from './UserController'
1
+ export * from './Controller.js'
2
+ export * from './ModelController.js'
3
+ export * from './RelationController.js'
4
+ export * from './AdminController.js'
5
+ export * from './UsersController.js'
@@ -1,8 +1,8 @@
1
- import { createDecorator } from '@/utils'
1
+ import { createDecorator } from '../utils/index.js'
2
2
 
3
- export function action(verb, path) {
3
+ export function action(method, path) {
4
4
  return createDecorator(value => {
5
- value.verb = verb
5
+ value.method = method
6
6
  value.path = path
7
7
  })
8
8
  }
@@ -1,4 +1,4 @@
1
- import { createDecorator } from '@/utils'
1
+ import { createDecorator } from '../utils/index.js'
2
2
 
3
3
  export function authorize(authorize) {
4
4
  return createDecorator(value => {
@@ -1,6 +1,6 @@
1
- export * from './action'
2
- export * from './authorize'
3
- export * from './parameters'
4
- export * from './returns'
5
- export * from './scope'
6
- export * from './transacted'
1
+ export * from './action.js'
2
+ export * from './authorize.js'
3
+ export * from './parameters.js'
4
+ export * from './returns.js'
5
+ export * from './scope.js'
6
+ export * from './transacted.js'
@@ -1,5 +1,5 @@
1
1
  import { isArray, isObject } from '@ditojs/utils'
2
- import { createDecorator, deprecate, formatJson } from '@/utils'
2
+ import { createDecorator, deprecate, formatJson } from '../utils/index.js'
3
3
 
4
4
  export function parameters(parameters, options) {
5
5
  if (isObject(parameters)) {
@@ -1,5 +1,5 @@
1
1
  import { isObject } from '@ditojs/utils'
2
- import { createDecorator, formatJson } from '@/utils'
2
+ import { createDecorator, formatJson } from '../utils/index.js'
3
3
 
4
4
  export function returns(returns, options) {
5
5
  if (!isObject(returns)) {
@@ -1,4 +1,4 @@
1
- import { createDecorator } from '@/utils'
1
+ import { createDecorator } from '../utils/index.js'
2
2
 
3
3
  export function scope(...scopes) {
4
4
  return createDecorator(value => {
@@ -1,4 +1,4 @@
1
- import { createDecorator } from '@/utils'
1
+ import { createDecorator } from '../utils/index.js'
2
2
 
3
3
  export const transacted = createDecorator(value => {
4
4
  value.transacted = true
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class AssetError extends ResponseError {
4
4
  constructor(error) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class AuthenticationError extends ResponseError {
4
4
  constructor(error) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class AuthorizationError extends ResponseError {
4
4
  constructor(error) {
@@ -1,5 +1,5 @@
1
- import { ResponseError } from './ResponseError'
2
1
  import { isFunction } from '@ditojs/utils'
2
+ import { ResponseError } from './ResponseError.js'
3
3
 
4
4
  export class ControllerError extends ResponseError {
5
5
  constructor(controller, error) {
@@ -1,11 +1,20 @@
1
- import { WrappedError } from './WrappedError'
2
- import {
1
+ import { WrappedError } from './WrappedError.js'
2
+ // TODO: Import directly once we can move to Objection 3 and this is fixed:
3
+ // import {
4
+ // DBError,
5
+ // DataError,
6
+ // CheckViolationError,
7
+ // NotNullViolationError,
8
+ // ConstraintViolationError
9
+ // } from 'objection'
10
+ import objection from 'objection'
11
+ const {
3
12
  DBError,
4
13
  DataError,
5
14
  CheckViolationError,
6
15
  NotNullViolationError,
7
16
  ConstraintViolationError
8
- } from 'objection'
17
+ } = objection
9
18
 
10
19
  export class DatabaseError extends WrappedError {
11
20
  constructor(error, overrides) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class GraphError extends ResponseError {
4
4
  constructor(error) {
@@ -1,5 +1,5 @@
1
- import { ResponseError } from './ResponseError'
2
1
  import { isFunction } from '@ditojs/utils'
2
+ import { ResponseError } from './ResponseError.js'
3
3
 
4
4
  export class ModelError extends ResponseError {
5
5
  constructor(model, error) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class NotFoundError extends ResponseError {
4
4
  constructor(error) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class NotImplementedError extends ResponseError {
4
4
  constructor(error) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class QueryBuilderError extends ResponseError {
4
4
  constructor(error) {
@@ -1,4 +1,4 @@
1
- import { WrappedError } from './WrappedError'
1
+ import { WrappedError } from './WrappedError.js'
2
2
  import { isObject } from '@ditojs/utils'
3
3
 
4
4
  export class RelationError extends WrappedError {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class ValidationError extends ResponseError {
4
4
  constructor(error) {