@ditojs/server 0.275.0 → 1.0.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 (216) hide show
  1. package/package.json +25 -43
  2. package/src/app/Application.js +105 -111
  3. package/src/app/Validator.js +6 -3
  4. package/src/app/index.js +2 -2
  5. package/src/cli/db/createMigration.js +1 -1
  6. package/src/cli/db/index.js +7 -7
  7. package/src/cli/db/listAssetConfig.js +1 -1
  8. package/src/cli/db/reset.js +1 -1
  9. package/src/cli/index.js +14 -5
  10. package/src/controllers/AdminController.js +181 -158
  11. package/src/controllers/CollectionController.js +8 -29
  12. package/src/controllers/Controller.js +71 -76
  13. package/src/controllers/ControllerAction.js +39 -17
  14. package/src/controllers/MemberAction.js +2 -2
  15. package/src/controllers/ModelController.js +4 -4
  16. package/src/controllers/RelationController.js +3 -3
  17. package/src/controllers/{UserController.js → UsersController.js} +8 -13
  18. package/src/controllers/index.js +5 -5
  19. package/src/decorators/action.js +3 -3
  20. package/src/decorators/authorize.js +1 -1
  21. package/src/decorators/index.js +6 -6
  22. package/src/decorators/parameters.js +1 -1
  23. package/src/decorators/returns.js +1 -1
  24. package/src/decorators/scope.js +1 -1
  25. package/src/decorators/transacted.js +1 -1
  26. package/src/errors/AssetError.js +1 -1
  27. package/src/errors/AuthenticationError.js +1 -1
  28. package/src/errors/AuthorizationError.js +1 -1
  29. package/src/errors/ControllerError.js +1 -1
  30. package/src/errors/DatabaseError.js +12 -3
  31. package/src/errors/GraphError.js +1 -1
  32. package/src/errors/ModelError.js +1 -1
  33. package/src/errors/NotFoundError.js +1 -1
  34. package/src/errors/NotImplementedError.js +1 -1
  35. package/src/errors/QueryBuilderError.js +1 -1
  36. package/src/errors/RelationError.js +1 -1
  37. package/src/errors/ValidationError.js +1 -1
  38. package/src/errors/WrappedError.js +1 -1
  39. package/src/errors/index.js +14 -14
  40. package/src/graph/DitoGraphProcessor.js +2 -1
  41. package/src/graph/graph.js +1 -1
  42. package/src/graph/index.js +3 -3
  43. package/src/index.js +11 -9
  44. package/src/lib/index.js +2 -2
  45. package/src/middleware/createTransaction.js +1 -1
  46. package/src/middleware/findRoute.js +3 -2
  47. package/src/middleware/handleConnectMiddleware.js +88 -0
  48. package/src/middleware/handleError.js +1 -1
  49. package/src/middleware/handleRoute.js +3 -3
  50. package/src/middleware/index.js +8 -7
  51. package/src/mixins/AssetMixin.js +1 -1
  52. package/src/mixins/UserMixin.js +1 -1
  53. package/src/mixins/index.js +4 -4
  54. package/src/models/AssetModel.js +2 -2
  55. package/src/models/Model.js +16 -12
  56. package/src/models/RelationAccessor.js +1 -1
  57. package/src/models/SessionModel.js +2 -2
  58. package/src/models/TimeStampedModel.js +2 -2
  59. package/src/models/UserModel.js +2 -2
  60. package/src/models/definitions/assets.js +1 -1
  61. package/src/models/definitions/filters.js +57 -44
  62. package/src/models/definitions/hooks.js +1 -1
  63. package/src/models/definitions/index.js +9 -9
  64. package/src/models/definitions/modifiers.js +1 -1
  65. package/src/models/definitions/options.js +1 -1
  66. package/src/models/definitions/properties.js +2 -2
  67. package/src/models/definitions/relations.js +1 -1
  68. package/src/models/definitions/schema.js +1 -1
  69. package/src/models/definitions/scopes.js +2 -2
  70. package/src/models/index.js +5 -5
  71. package/src/query/QueryBuilder.js +5 -5
  72. package/src/query/QueryFilters.js +50 -50
  73. package/src/query/QueryParameters.js +2 -2
  74. package/src/query/index.js +3 -3
  75. package/src/schema/formats/index.js +2 -2
  76. package/src/schema/index.js +4 -4
  77. package/src/schema/keywords/_relate.js +1 -1
  78. package/src/schema/keywords/index.js +12 -12
  79. package/src/schema/properties.test.js +1 -1
  80. package/src/schema/relations.js +1 -1
  81. package/src/schema/relations.test.js +2 -2
  82. package/src/services/index.js +1 -1
  83. package/src/storage/DiskStorage.js +1 -1
  84. package/src/storage/S3Storage.js +4 -4
  85. package/src/storage/Storage.js +1 -1
  86. package/src/storage/index.js +4 -4
  87. package/src/utils/function.test.js +1 -1
  88. package/src/utils/handler.js +17 -0
  89. package/src/utils/index.js +8 -7
  90. package/src/utils/object.test.js +1 -1
  91. package/lib/app/Application.js +0 -961
  92. package/lib/app/SessionStore.js +0 -40
  93. package/lib/app/Validator.js +0 -355
  94. package/lib/app/index.js +0 -26
  95. package/lib/cli/console.js +0 -175
  96. package/lib/cli/db/createMigration.js +0 -237
  97. package/lib/cli/db/index.js +0 -66
  98. package/lib/cli/db/listAssetConfig.js +0 -16
  99. package/lib/cli/db/migrate.js +0 -15
  100. package/lib/cli/db/reset.js +0 -27
  101. package/lib/cli/db/rollback.js +0 -15
  102. package/lib/cli/db/seed.js +0 -104
  103. package/lib/cli/db/unlock.js +0 -15
  104. package/lib/cli/index.js +0 -90
  105. package/lib/controllers/AdminController.js +0 -258
  106. package/lib/controllers/CollectionController.js +0 -263
  107. package/lib/controllers/Controller.js +0 -462
  108. package/lib/controllers/ControllerAction.js +0 -276
  109. package/lib/controllers/MemberAction.js +0 -22
  110. package/lib/controllers/ModelController.js +0 -64
  111. package/lib/controllers/RelationController.js +0 -82
  112. package/lib/controllers/UserController.js +0 -98
  113. package/lib/controllers/index.js +0 -50
  114. package/lib/decorators/action.js +0 -14
  115. package/lib/decorators/authorize.js +0 -13
  116. package/lib/decorators/index.js +0 -58
  117. package/lib/decorators/parameters.js +0 -35
  118. package/lib/decorators/returns.js +0 -26
  119. package/lib/decorators/scope.js +0 -14
  120. package/lib/decorators/transacted.js +0 -12
  121. package/lib/errors/AssetError.js +0 -19
  122. package/lib/errors/AuthenticationError.js +0 -19
  123. package/lib/errors/AuthorizationError.js +0 -19
  124. package/lib/errors/ControllerError.js +0 -24
  125. package/lib/errors/DatabaseError.js +0 -27
  126. package/lib/errors/GraphError.js +0 -19
  127. package/lib/errors/ModelError.js +0 -24
  128. package/lib/errors/NotFoundError.js +0 -19
  129. package/lib/errors/NotImplementedError.js +0 -19
  130. package/lib/errors/QueryBuilderError.js +0 -19
  131. package/lib/errors/RelationError.js +0 -36
  132. package/lib/errors/ResponseError.js +0 -46
  133. package/lib/errors/ValidationError.js +0 -19
  134. package/lib/errors/WrappedError.js +0 -24
  135. package/lib/errors/index.js +0 -122
  136. package/lib/graph/DitoGraphProcessor.js +0 -185
  137. package/lib/graph/expression.js +0 -76
  138. package/lib/graph/graph.js +0 -300
  139. package/lib/graph/index.js +0 -34
  140. package/lib/index.js +0 -82
  141. package/lib/lib/EventEmitter.js +0 -76
  142. package/lib/lib/KnexHelper.js +0 -40
  143. package/lib/lib/index.js +0 -26
  144. package/lib/middleware/attachLogger.js +0 -16
  145. package/lib/middleware/createTransaction.js +0 -36
  146. package/lib/middleware/findRoute.js +0 -35
  147. package/lib/middleware/handleError.js +0 -26
  148. package/lib/middleware/handleRoute.js +0 -29
  149. package/lib/middleware/handleUser.js +0 -36
  150. package/lib/middleware/index.js +0 -66
  151. package/lib/middleware/logRequests.js +0 -122
  152. package/lib/mixins/AssetMixin.js +0 -81
  153. package/lib/mixins/SessionMixin.js +0 -22
  154. package/lib/mixins/TimeStampedMixin.js +0 -47
  155. package/lib/mixins/UserMixin.js +0 -151
  156. package/lib/mixins/index.js +0 -42
  157. package/lib/models/AssetModel.js +0 -12
  158. package/lib/models/Model.js +0 -953
  159. package/lib/models/RelationAccessor.js +0 -41
  160. package/lib/models/SessionModel.js +0 -12
  161. package/lib/models/TimeStampedModel.js +0 -12
  162. package/lib/models/UserModel.js +0 -12
  163. package/lib/models/definitions/assets.js +0 -11
  164. package/lib/models/definitions/filters.js +0 -101
  165. package/lib/models/definitions/hooks.js +0 -11
  166. package/lib/models/definitions/index.js +0 -38
  167. package/lib/models/definitions/modifiers.js +0 -11
  168. package/lib/models/definitions/options.js +0 -11
  169. package/lib/models/definitions/properties.js +0 -87
  170. package/lib/models/definitions/relations.js +0 -11
  171. package/lib/models/definitions/schema.js +0 -11
  172. package/lib/models/definitions/scopes.js +0 -51
  173. package/lib/models/index.js +0 -50
  174. package/lib/query/QueryBuilder.js +0 -745
  175. package/lib/query/QueryFilters.js +0 -82
  176. package/lib/query/QueryParameters.js +0 -77
  177. package/lib/query/Registry.js +0 -40
  178. package/lib/query/index.js +0 -34
  179. package/lib/schema/formats/_empty.js +0 -10
  180. package/lib/schema/formats/_required.js +0 -10
  181. package/lib/schema/formats/index.js +0 -26
  182. package/lib/schema/index.js +0 -49
  183. package/lib/schema/keywords/_computed.js +0 -11
  184. package/lib/schema/keywords/_foreign.js +0 -11
  185. package/lib/schema/keywords/_hidden.js +0 -11
  186. package/lib/schema/keywords/_index.js +0 -11
  187. package/lib/schema/keywords/_instanceof.js +0 -49
  188. package/lib/schema/keywords/_primary.js +0 -11
  189. package/lib/schema/keywords/_range.js +0 -26
  190. package/lib/schema/keywords/_relate.js +0 -19
  191. package/lib/schema/keywords/_specificType.js +0 -11
  192. package/lib/schema/keywords/_unique.js +0 -11
  193. package/lib/schema/keywords/_unsigned.js +0 -11
  194. package/lib/schema/keywords/_validate.js +0 -80
  195. package/lib/schema/keywords/index.js +0 -106
  196. package/lib/schema/properties.js +0 -227
  197. package/lib/schema/properties.test.js +0 -573
  198. package/lib/schema/relations.js +0 -274
  199. package/lib/schema/relations.test.js +0 -155
  200. package/lib/services/Service.js +0 -34
  201. package/lib/services/index.js +0 -18
  202. package/lib/storage/AssetFile.js +0 -97
  203. package/lib/storage/DiskStorage.js +0 -125
  204. package/lib/storage/S3Storage.js +0 -171
  205. package/lib/storage/Storage.js +0 -209
  206. package/lib/storage/index.js +0 -34
  207. package/lib/utils/decorator.js +0 -16
  208. package/lib/utils/deprecate.js +0 -46
  209. package/lib/utils/emitter.js +0 -13
  210. package/lib/utils/function.js +0 -14
  211. package/lib/utils/function.test.js +0 -49
  212. package/lib/utils/index.js +0 -66
  213. package/lib/utils/json.js +0 -9
  214. package/lib/utils/object.js +0 -92
  215. package/lib/utils/object.test.js +0 -65
  216. package/lib/utils/scope.js +0 -14
@@ -1,11 +1,14 @@
1
1
  import pico from 'picocolors'
2
- import { getOwnProperty, getAllKeys, describeFunction } from '@/utils'
3
- import { EventEmitter } from '@/lib'
4
- import ControllerAction from './ControllerAction'
5
- import MemberAction from './MemberAction'
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
@@ -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,10 +92,10 @@ 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
- pico.magenta(verb.toUpperCase())
98
+ pico.magenta(method.toUpperCase())
96
99
  } ${
97
100
  pico.green(this.url)
98
101
  }${
@@ -102,7 +105,7 @@ export class Controller {
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,56 @@
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,
15
+ 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
27
+ this.method = method
28
+ this.path = path
29
+ this.scope = scope
30
+ this.authorize = authorize || _authorize
16
31
  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)
32
+ transacted ||
33
+ controller.transacted || (
34
+ // Core graph and assets operations are always transacted, unless the
35
+ // method is 'get':
36
+ core && method !== 'get' && (
37
+ controller.graph ||
38
+ controller.assets
39
+ )
40
+ )
22
41
  )
23
42
  this.authorization = controller.processAuthorize(this.authorize)
24
43
  this.app = controller.app
25
- this.paramsName = ['post', 'put', 'patch'].includes(this.verb)
44
+ this.paramsName = ['post', 'put', 'patch'].includes(this.method)
26
45
  ? 'body'
27
46
  : 'query'
28
- const { parameters, returns, options = {} } = this.handler
29
47
  this.parameters = this.app.compileParametersValidator(parameters, {
30
48
  async: true,
31
- ...options.parameters, // See @parameters() decorator
49
+ ...options.parameters,
32
50
  dataName: this.paramsName
33
51
  })
34
52
  this.returns = this.app.compileParametersValidator(
53
+ // TODO: Shouldn't we set `this.returns` to null instead?
35
54
  returns ? [returns] : [],
36
55
  {
37
56
  async: true,
@@ -43,12 +62,15 @@ export default class ControllerAction {
43
62
  dataName: 'returns'
44
63
  }
45
64
  )
65
+ // Copy over the additional properties, e.g. `cached` so application
66
+ // middleware can implement caching mechanisms:
67
+ Object.assign(this, additional)
46
68
  }
47
69
 
48
70
  // Possible values for `from` are:
49
71
  // - '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.
72
+ // - 'query': Use `ctx.request.query`, regardless of the action's method.
73
+ // - 'body': Use `ctx.request.body`, regardless of the action's method.
52
74
  getParams(ctx, from = this.paramsName) {
53
75
  const value = from === 'path' ? ctx.params : ctx.request[from]
54
76
  // 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
1
  import pico from 'picocolors'
2
- import { ControllerError } from '@/errors'
3
- import { CollectionController } from './CollectionController'
4
- import { setupPropertyInheritance, getScope } from '@/utils'
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) {
@@ -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) {
@@ -1,4 +1,4 @@
1
- import { ResponseError } from './ResponseError'
1
+ import { ResponseError } from './ResponseError.js'
2
2
 
3
3
  export class WrappedError extends ResponseError {
4
4
  constructor(error, overrides, defaults = {