lumen-framework 3.1.0 → 4.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 (258) hide show
  1. package/README.md +75 -109
  2. package/bin/lumen +23 -41
  3. package/dist/cli.cjs +856 -479
  4. package/dist/cli.cjs.map +4 -4
  5. package/dist/index.js +3284 -1720
  6. package/dist/index.js.map +4 -4
  7. package/dist/index.mjs +3263 -1699
  8. package/dist/index.mjs.map +4 -4
  9. package/dist/testing.js +280 -0
  10. package/dist/testing.js.map +7 -0
  11. package/dist/testing.mjs +252 -0
  12. package/dist/testing.mjs.map +7 -0
  13. package/dist/types/errors/links-only-error.d.ts +13 -0
  14. package/dist/types/errors/reserved-field-name-error.d.ts +13 -0
  15. package/dist/types/errors/unknown-attribute-error.d.ts +13 -0
  16. package/dist/types/index.d.ts +14 -0
  17. package/dist/types/interfaces.d.ts +1 -1
  18. package/dist/types/packages/application/index.d.ts +38 -45
  19. package/dist/types/packages/application/initialize.d.ts +3 -5
  20. package/dist/types/packages/application/interfaces.d.ts +13 -5
  21. package/dist/types/packages/application/utils/create-controller.d.ts +14 -4
  22. package/dist/types/packages/application/utils/create-serializer.d.ts +2 -2
  23. package/dist/types/packages/application/utils/normalize-port.d.ts +1 -3
  24. package/dist/types/packages/application/utils/resolve-visibility.d.ts +15 -0
  25. package/dist/types/packages/application/utils/restrict-open-namespaces.d.ts +19 -0
  26. package/dist/types/packages/application/utils/validate-attributes.d.ts +17 -0
  27. package/dist/types/packages/application/utils/validate-links-only.d.ts +19 -0
  28. package/dist/types/packages/application/utils/validate-namespaced-serializers.d.ts +3 -3
  29. package/dist/types/packages/application/utils/validate-reserved-names.d.ts +12 -0
  30. package/dist/types/packages/application/utils/warn-query-param-names.d.ts +10 -0
  31. package/dist/types/packages/cli/commands/dbcreate.d.ts +1 -1
  32. package/dist/types/packages/cli/commands/dbdrop.d.ts +1 -1
  33. package/dist/types/packages/cli/commands/destroy.d.ts +3 -2
  34. package/dist/types/packages/cli/commands/generate.d.ts +5 -5
  35. package/dist/types/packages/cli/commands/index.d.ts +0 -1
  36. package/dist/types/packages/cli/generator/index.d.ts +6 -6
  37. package/dist/types/packages/cli/generator/interfaces.d.ts +3 -3
  38. package/dist/types/packages/cli/generator/utils/create-generator.d.ts +2 -2
  39. package/dist/types/packages/cli/generator/utils/generate-type.d.ts +9 -9
  40. package/dist/types/packages/cli/generator/utils/migration-conflict.d.ts +4 -4
  41. package/dist/types/packages/cli/templates/pnpm-workspace.d.ts +15 -0
  42. package/dist/types/packages/cli/utils/create-spinner.d.ts +14 -0
  43. package/dist/types/packages/cli/utils/print-statements.d.ts +12 -0
  44. package/dist/types/packages/cli/utils/server-database.d.ts +27 -0
  45. package/dist/types/packages/compiler/interfaces.d.ts +1 -1
  46. package/dist/types/packages/config/interfaces.d.ts +10 -4
  47. package/dist/types/packages/controller/constants.d.ts +7 -2
  48. package/dist/types/packages/controller/errors/related-record-not-found-error.d.ts +4 -4
  49. package/dist/types/packages/controller/index.d.ts +364 -473
  50. package/dist/types/packages/controller/interfaces.d.ts +21 -6
  51. package/dist/types/packages/controller/utils/find-many.d.ts +2 -5
  52. package/dist/types/packages/controller/utils/find-one.d.ts +2 -5
  53. package/dist/types/packages/controller/utils/params-to-query.d.ts +8 -10
  54. package/dist/types/packages/controller/utils/resolve-relationships.d.ts +1 -3
  55. package/dist/types/packages/controller/utils/validate-relationships.d.ts +5 -3
  56. package/dist/types/packages/controller/visibility/errors.d.ts +21 -0
  57. package/dist/types/packages/controller/visibility/index.d.ts +51 -0
  58. package/dist/types/packages/database/attribute/index.d.ts +4 -6
  59. package/dist/types/packages/database/attribute/interfaces.d.ts +1 -1
  60. package/dist/types/packages/database/attribute/utils/create-attribute.d.ts +3 -5
  61. package/dist/types/packages/database/attribute/utils/create-getter.d.ts +2 -2
  62. package/dist/types/packages/database/attribute/utils/create-setter.d.ts +3 -5
  63. package/dist/types/packages/database/constants.d.ts +1 -0
  64. package/dist/types/packages/database/errors/index.d.ts +1 -0
  65. package/dist/types/packages/database/errors/invalid-driver-error.d.ts +1 -3
  66. package/dist/types/packages/database/errors/migrations-pending-error.d.ts +1 -3
  67. package/dist/types/packages/database/errors/model-missing-error.d.ts +1 -3
  68. package/dist/types/packages/database/errors/relationship-config-error.d.ts +10 -0
  69. package/dist/types/packages/database/errors/unique-constraint-error.d.ts +1 -1
  70. package/dist/types/packages/database/index.d.ts +9 -6
  71. package/dist/types/packages/database/initialize.d.ts +3 -5
  72. package/dist/types/packages/database/interfaces.d.ts +115 -25
  73. package/dist/types/packages/database/migration/index.d.ts +5 -7
  74. package/dist/types/packages/database/migration/interfaces.d.ts +2 -4
  75. package/dist/types/packages/database/migration/utils/generate-timestamp.d.ts +9 -1
  76. package/dist/types/packages/database/model/index.d.ts +348 -759
  77. package/dist/types/packages/database/model/initialize-class.d.ts +7 -1
  78. package/dist/types/packages/database/model/interfaces.d.ts +30 -12
  79. package/dist/types/packages/database/model/utils/attribute.d.ts +14 -0
  80. package/dist/types/packages/database/model/utils/get-columns.d.ts +1 -3
  81. package/dist/types/packages/database/model/utils/persistence.d.ts +5 -14
  82. package/dist/types/packages/database/model/utils/process-write-error.d.ts +2 -2
  83. package/dist/types/packages/database/model/utils/run-hooks.d.ts +7 -3
  84. package/dist/types/packages/database/model/utils/validate.d.ts +4 -1
  85. package/dist/types/packages/database/query/errors/record-not-found-error.d.ts +1 -1
  86. package/dist/types/packages/database/query/index.d.ts +179 -3
  87. package/dist/types/packages/database/query/runner/index.d.ts +1 -3
  88. package/dist/types/packages/database/query/runner/utils/build-results.d.ts +3 -4
  89. package/dist/types/packages/database/query/utils/format-select.d.ts +1 -3
  90. package/dist/types/packages/database/relationship/index.d.ts +7 -6
  91. package/dist/types/packages/database/relationship/interfaces.d.ts +16 -3
  92. package/dist/types/packages/database/relationship/utils/getters.d.ts +7 -13
  93. package/dist/types/packages/database/relationship/utils/inverse-setters.d.ts +5 -9
  94. package/dist/types/packages/database/relationship/utils/setters.d.ts +7 -13
  95. package/dist/types/packages/database/relationship/utils/unassociate.d.ts +1 -3
  96. package/dist/types/packages/database/relationship/utils/update-relationship.d.ts +6 -2
  97. package/dist/types/packages/database/transaction/index.d.ts +9 -10
  98. package/dist/types/packages/database/transaction/interfaces.d.ts +7 -1
  99. package/dist/types/packages/database/utils/connect.d.ts +16 -3
  100. package/dist/types/packages/database/utils/create-migrations.d.ts +1 -3
  101. package/dist/types/packages/database/utils/normalize-model-name.d.ts +1 -3
  102. package/dist/types/packages/database/utils/pending-migrations.d.ts +1 -3
  103. package/dist/types/packages/database/utils/primary-key-type.d.ts +10 -0
  104. package/dist/types/packages/database/utils/type-for-column.d.ts +3 -5
  105. package/dist/types/packages/database/utils/validate-relationships.d.ts +13 -0
  106. package/dist/types/packages/database/validation/errors/validation-error.d.ts +4 -4
  107. package/dist/types/packages/database/validation/index.d.ts +3 -5
  108. package/dist/types/packages/database/validation/interfaces.d.ts +1 -1
  109. package/dist/types/packages/freezeable/map/index.d.ts +1 -3
  110. package/dist/types/packages/freezeable/set/index.d.ts +1 -3
  111. package/dist/types/packages/freezeable/utils/freeze.d.ts +5 -15
  112. package/dist/types/packages/freezeable/utils/is-frozen.d.ts +1 -3
  113. package/dist/types/packages/fs/index.d.ts +7 -7
  114. package/dist/types/packages/fs/interfaces.d.ts +4 -4
  115. package/dist/types/packages/fs/utils/parse-path.d.ts +2 -2
  116. package/dist/types/packages/fs/watcher/interfaces.d.ts +1 -1
  117. package/dist/types/packages/jsonapi/errors/invalid-content-type-error.d.ts +3 -5
  118. package/dist/types/packages/jsonapi/errors/not-acceptable-error.d.ts +2 -4
  119. package/dist/types/packages/jsonapi/errors/unsupported-media-type-error.d.ts +2 -4
  120. package/dist/types/packages/jsonapi/index.d.ts +1 -1
  121. package/dist/types/packages/jsonapi/interfaces.d.ts +47 -36
  122. package/dist/types/packages/jsonapi/utils/has-media-type-params.d.ts +1 -1
  123. package/dist/types/packages/jsonapi/utils/is-jsonapi.d.ts +1 -1
  124. package/dist/types/packages/jsonapi/utils/media-type.d.ts +2 -2
  125. package/dist/types/packages/loader/builder/index.d.ts +3 -3
  126. package/dist/types/packages/loader/builder/interfaces.d.ts +7 -7
  127. package/dist/types/packages/loader/builder/utils/create-children-builder.d.ts +2 -2
  128. package/dist/types/packages/loader/builder/utils/create-parent-builder.d.ts +9 -2
  129. package/dist/types/packages/loader/builder/utils/sort-by-namespace.d.ts +2 -2
  130. package/dist/types/packages/loader/index.d.ts +1 -1
  131. package/dist/types/packages/loader/interfaces.d.ts +2 -2
  132. package/dist/types/packages/loader/resolver/index.d.ts +2 -2
  133. package/dist/types/packages/loader/resolver/utils/closest-ancestor.d.ts +2 -2
  134. package/dist/types/packages/loader/resolver/utils/closest-child.d.ts +2 -2
  135. package/dist/types/packages/logger/constants.d.ts +3 -3
  136. package/dist/types/packages/logger/errors/invalid-config-error.d.ts +5 -0
  137. package/dist/types/packages/logger/index.d.ts +65 -142
  138. package/dist/types/packages/logger/interfaces.d.ts +52 -10
  139. package/dist/types/packages/logger/request-logger/index.d.ts +3 -5
  140. package/dist/types/packages/logger/request-logger/interfaces.d.ts +5 -5
  141. package/dist/types/packages/logger/request-logger/templates.d.ts +5 -9
  142. package/dist/types/packages/logger/request-logger/utils/filter-params.d.ts +6 -1
  143. package/dist/types/packages/logger/request-logger/utils/log-json.d.ts +2 -4
  144. package/dist/types/packages/logger/request-logger/utils/log-text.d.ts +1 -3
  145. package/dist/types/packages/logger/request-logger/utils/params-for.d.ts +9 -0
  146. package/dist/types/packages/logger/utils/error-name.d.ts +7 -0
  147. package/dist/types/packages/logger/utils/line.d.ts +1 -3
  148. package/dist/types/packages/logger/writer/constants.d.ts +0 -1
  149. package/dist/types/packages/logger/writer/index.d.ts +6 -6
  150. package/dist/types/packages/logger/writer/interfaces.d.ts +2 -2
  151. package/dist/types/packages/logger/writer/utils/format-message.d.ts +2 -2
  152. package/dist/types/packages/lumenify/index.d.ts +20 -5
  153. package/dist/types/packages/lumenify/utils/create-response-proxy.d.ts +1 -1
  154. package/dist/types/packages/pm/cluster/index.d.ts +56 -7
  155. package/dist/types/packages/pm/cluster/interfaces.d.ts +2 -1
  156. package/dist/types/packages/pm/index.d.ts +2 -2
  157. package/dist/types/packages/router/definitions/context/index.d.ts +5 -7
  158. package/dist/types/packages/router/definitions/context/utils/create-definition-group.d.ts +3 -5
  159. package/dist/types/packages/router/definitions/context/utils/create-definition.d.ts +11 -6
  160. package/dist/types/packages/router/definitions/context/utils/normalize-resource-args.d.ts +4 -5
  161. package/dist/types/packages/router/definitions/index.d.ts +5 -9
  162. package/dist/types/packages/router/definitions/interfaces.d.ts +4 -4
  163. package/dist/types/packages/router/index.d.ts +23 -11
  164. package/dist/types/packages/router/interfaces.d.ts +4 -4
  165. package/dist/types/packages/router/namespace/index.d.ts +7 -9
  166. package/dist/types/packages/router/namespace/interfaces.d.ts +3 -3
  167. package/dist/types/packages/router/namespace/utils/normalize-name.d.ts +1 -3
  168. package/dist/types/packages/router/namespace/utils/normalize-path.d.ts +1 -3
  169. package/dist/types/packages/router/resource/index.d.ts +7 -8
  170. package/dist/types/packages/router/resource/interfaces.d.ts +12 -4
  171. package/dist/types/packages/router/resource/utils/normalize-only.d.ts +3 -5
  172. package/dist/types/packages/router/route/action/enhancers/resource.d.ts +1 -3
  173. package/dist/types/packages/router/route/action/enhancers/track-perf.d.ts +1 -3
  174. package/dist/types/packages/router/route/action/index.d.ts +7 -2
  175. package/dist/types/packages/router/route/action/interfaces.d.ts +4 -0
  176. package/dist/types/packages/router/route/action/utils/create-page-links.d.ts +21 -5
  177. package/dist/types/packages/router/route/action/utils/get-action-name.d.ts +1 -3
  178. package/dist/types/packages/router/route/action/utils/get-controller-name.d.ts +1 -3
  179. package/dist/types/packages/router/route/index.d.ts +13 -9
  180. package/dist/types/packages/router/route/interfaces.d.ts +7 -5
  181. package/dist/types/packages/router/route/params/errors/client-generated-id-error.d.ts +4 -4
  182. package/dist/types/packages/router/route/params/errors/forbidden-parameter-error.d.ts +4 -4
  183. package/dist/types/packages/router/route/params/errors/index.d.ts +1 -0
  184. package/dist/types/packages/router/route/params/errors/invalid-parameter-error.d.ts +4 -6
  185. package/dist/types/packages/router/route/params/errors/parameter-not-nullable-error.d.ts +4 -6
  186. package/dist/types/packages/router/route/params/errors/parameter-range-error.d.ts +9 -0
  187. package/dist/types/packages/router/route/params/errors/parameter-required-error.d.ts +4 -6
  188. package/dist/types/packages/router/route/params/errors/parameter-type-error.d.ts +4 -6
  189. package/dist/types/packages/router/route/params/errors/parameter-value-error.d.ts +4 -6
  190. package/dist/types/packages/router/route/params/errors/resource-mismatch-error.d.ts +4 -6
  191. package/dist/types/packages/router/route/params/index.d.ts +5 -9
  192. package/dist/types/packages/router/route/params/interfaces.d.ts +12 -8
  193. package/dist/types/packages/router/route/params/parameter/forbidden-parameter.d.ts +1 -1
  194. package/dist/types/packages/router/route/params/parameter/ignored-parameter.d.ts +14 -0
  195. package/dist/types/packages/router/route/params/parameter/index.d.ts +21 -5
  196. package/dist/types/packages/router/route/params/parameter/interfaces.d.ts +2 -2
  197. package/dist/types/packages/router/route/params/parameter/utils/validate-range.d.ts +3 -0
  198. package/dist/types/packages/router/route/params/parameter/utils/validate-value.d.ts +1 -3
  199. package/dist/types/packages/router/route/params/parameter-group/index.d.ts +3 -5
  200. package/dist/types/packages/router/route/params/parameter-group/utils/missing-params.d.ts +8 -0
  201. package/dist/types/packages/router/route/params/utils/get-data-params.d.ts +5 -1
  202. package/dist/types/packages/router/route/params/utils/get-default-collection-params.d.ts +1 -3
  203. package/dist/types/packages/router/route/params/utils/get-default-member-params.d.ts +5 -2
  204. package/dist/types/packages/router/route/params/utils/get-query-params.d.ts +3 -9
  205. package/dist/types/packages/router/route/params/utils/get-url-params.d.ts +1 -3
  206. package/dist/types/packages/router/route/params/utils/parse-column-value.d.ts +16 -0
  207. package/dist/types/packages/router/route/params/utils/validate-client-id.d.ts +1 -1
  208. package/dist/types/packages/router/route/params/utils/validate-resource-id.d.ts +1 -3
  209. package/dist/types/packages/router/route/params/utils/validate-type.d.ts +3 -5
  210. package/dist/types/packages/router/route/utils/get-dynamic-segments.d.ts +1 -3
  211. package/dist/types/packages/router/route/utils/get-static-path.d.ts +6 -2
  212. package/dist/types/packages/router/utils/create-replacer.d.ts +10 -2
  213. package/dist/types/packages/serializer/index.d.ts +243 -434
  214. package/dist/types/packages/serializer/interfaces.d.ts +19 -1
  215. package/dist/types/packages/serializer/utils/include-tree.d.ts +12 -3
  216. package/dist/types/packages/serializer/utils/load-linkage.d.ts +9 -3
  217. package/dist/types/packages/server/errors/error-list.d.ts +25 -0
  218. package/dist/types/packages/server/errors/method-not-allowed-error.d.ts +11 -0
  219. package/dist/types/packages/server/index.d.ts +9 -9
  220. package/dist/types/packages/server/interfaces.d.ts +59 -7
  221. package/dist/types/packages/server/request/constants.d.ts +2 -2
  222. package/dist/types/packages/server/request/index.d.ts +3 -5
  223. package/dist/types/packages/server/request/interfaces.d.ts +72 -8
  224. package/dist/types/packages/server/request/parser/errors/malformed-request-error.d.ts +3 -5
  225. package/dist/types/packages/server/request/parser/index.d.ts +6 -1
  226. package/dist/types/packages/server/request/parser/utils/format.d.ts +13 -11
  227. package/dist/types/packages/server/request/parser/utils/normalize-document.d.ts +13 -0
  228. package/dist/types/packages/server/request/parser/utils/parse-nested-object.d.ts +1 -3
  229. package/dist/types/packages/server/request/parser/utils/parse-read.d.ts +2 -4
  230. package/dist/types/packages/server/request/parser/utils/parse-write.d.ts +17 -1
  231. package/dist/types/packages/server/request/utils/get-domain.d.ts +1 -3
  232. package/dist/types/packages/server/responder/index.d.ts +1 -3
  233. package/dist/types/packages/server/responder/utils/content-type-for.d.ts +8 -0
  234. package/dist/types/packages/server/responder/utils/data-for.d.ts +3 -5
  235. package/dist/types/packages/server/responder/utils/normalize.d.ts +2 -3
  236. package/dist/types/packages/server/response/index.d.ts +3 -5
  237. package/dist/types/packages/server/response/interfaces.d.ts +14 -3
  238. package/dist/types/packages/server/utils/client-ip-for.d.ts +10 -0
  239. package/dist/types/packages/server/utils/create-server-error.d.ts +11 -3
  240. package/dist/types/packages/server/utils/request-id-for.d.ts +9 -0
  241. package/dist/types/packages/server/utils/set-cors-headers.d.ts +2 -2
  242. package/dist/types/packages/server/utils/source-for.d.ts +19 -3
  243. package/dist/types/packages/server/utils/status-for-error.d.ts +6 -0
  244. package/dist/types/packages/server/utils/validate-accept.d.ts +1 -1
  245. package/dist/types/packages/server/utils/validate-content-type.d.ts +8 -3
  246. package/dist/types/packages/testing/audit-visibility.d.ts +189 -0
  247. package/dist/types/packages/testing/index.d.ts +4 -0
  248. package/dist/types/packages/testing/start-app.d.ts +52 -0
  249. package/dist/types/packages/testing/utils/identifiers-in.d.ts +14 -0
  250. package/dist/types/testing.d.ts +9 -0
  251. package/dist/types/utils/chalk.d.ts +16 -0
  252. package/dist/types/utils/pick.d.ts +2 -2
  253. package/package.json +54 -26
  254. package/dist/types/packages/cli/commands/test.d.ts +0 -4
  255. package/dist/types/packages/logger/utils/sql.d.ts +0 -4
  256. package/dist/types/packages/router/route/params/parameter-group/utils/has-required-params.d.ts +0 -5
  257. package/dist/types/utils/create-query-string.d.ts +0 -6
  258. package/dist/types/utils/has-own-property.d.ts +0 -1
@@ -1,455 +1,206 @@
1
1
  import type Serializer from '../serializer';
2
2
  import type { Model, ModelClass, Query } from '../database';
3
3
  import type { Request, Response } from '../server';
4
- import type { Controller$opts, Controller$beforeAction, Controller$afterAction } from './interfaces';
4
+ import type { Visibility } from './visibility';
5
+ import type { ControllerOptions, BeforeAction, AfterAction } from './interfaces';
5
6
  /**
6
- * ## Overview
7
- *
8
- * The Controller class is responsible for taking in requests from the outside
9
- * world and returning the appropriate response.
10
- *
11
- * Think of a Controller as a server at a restaurant. A client makes a request
12
- * to an application, that request is routed to the appropriate Controller and
13
- * then the Controller interprets the request and returns data relative to what
14
- * the client has request.
15
- *
16
- * #### Actions
17
- *
18
- * Controller actions are functions that call on a Controller in response to an
19
- * incoming HTTP request. The job of Controller actions are to return the data
20
- * that the Lumen Application will respond with.
21
- *
22
- * There is no special API for Controller actions. They are simply functions
23
- * that return a value. If an action returns a Query or Promise the resolved
24
- * value will be used rather than the immediate return value of the action.
25
- *
26
- * Below you will find a table showing the different types of responses you can
27
- * get from different action return values. Keep in mind, Lumen is agnostic to
28
- * whether or not the value is returned synchronously or resolved from a
29
- * Promise.
30
- *
31
- * | Return/Resolved Value | Response |
32
- * |------------------------------|--------------------------------------------|
33
- * | Array<Model> or Model | Serialized JSON String |
34
- * | Array or Object Literal | JSON String |
35
- * | String Literal | Plain Text |
36
- * | Number Literal | [HTTP Status Code](https://goo.gl/T2lMc7) |
37
- * | true | [204 No Content](https://goo.gl/GxKoqz) |
38
- * | false | [401 Unauthorized](https://goo.gl/60QqCW) |
39
- *
40
- * **Built-In Actions**
41
- *
42
- * Built-in actions refer to Controller actions that you get for free when
43
- * extending the Controller class (show, index, create, update, destroy). These
44
- * actions are highly optimized to load only the attributes and relationships
45
- * that are defined in the resolved Serializer for a Controller.
46
- *
47
- * If applicable, built-in actions support the following features described in
48
- * the [JSON API specification](http://jsonapi.org/):
49
- *
50
- * - [Sorting](http://jsonapi.org/format/#fetching-sorting)
51
- * - [Filtering](http://jsonapi.org/format/#fetching-filtering)
52
- * - [Pagination](http://jsonapi.org/format/#fetching-pagination)
53
- * - [Sparse Fieldsets](http://jsonapi.org/format/#fetching-sparse-fieldsets)
54
- * - [Including Related Resources](http://jsonapi.org/format/#fetching-includes)
55
- *
56
- * **Extending Built-In Actions**
57
- *
58
- * Considering the amount of functionality built-in actions provide, you will
59
- * rarely need to override the default behavior of a built-in action. In the
60
- * event that you do need to override a built-in action, you have the ability to
61
- * opt back into the built-in logic by calling the super class.
62
- *
63
- * Read actions such as index and show return a Query which allows us to chain
64
- * methods to the super call. In the following example we will extend the
65
- * default behavior of the index action to only match records that meet an
66
- * additional hard-coded set of conditions. We will still be able to use all of
67
- * the functionality that the built-in index action provides.
7
+ * The base class of an app's controllers. A controller handles the requests
8
+ * for one resource; its built-in actions — `index`, `show`, `create`,
9
+ * `update`, `destroy`, and the relationship endpoints' `showRelationship` and
10
+ * `showRelated` — read and write records with sorting, filtering, paging,
11
+ * `include` and sparse fieldsets, so a controller is mostly configuration:
68
12
  *
69
13
  * ```javascript
70
14
  * // app/controllers/posts.js
71
15
  * import { Controller } from 'lumen-framework';
72
16
  *
73
17
  * class PostsController extends Controller {
74
- * index(request, response) {
75
- * return super.index(request, response).where({
76
- * isPublic: true
77
- * });
78
- * }
79
- * }
80
- *
81
- * export default PostsController;
82
- * ```
83
- *
84
- * **Custom Actions**
85
- *
86
- * Sometimes it is necessary to add a custom action to a Controller. Lumen allows
87
- * you to do so by adding an instance method to a Controller. In the following
88
- * example you will see how to add a custom action with the name `check` to a
89
- * Controller. We are implementing this action to use as a health check for the
90
- * application so we want to return the `Number` literal `204`.
91
- *
92
- * ```javascript
93
- * // app/controllers/health.js
94
- * import { Controller } from 'lumen-framework';
95
- *
96
- * class HealthController extends Controller {
97
- * async check() {
98
- * return 204;
99
- * }
100
- * }
101
- *
102
- * export default HealthController;
103
- * ```
104
- *
105
- * The example above is nice but we can make the code a bit more concise with an
106
- * Arrow `Function`.
107
- *
108
- * ```javascript
109
- * // app/controllers/health.js
110
- * import { Controller } from 'lumen-framework';
111
- *
112
- * class HealthController extends Controller {
113
- * check = async () => 204;
114
- * }
115
- *
116
- * export default HealthController;
117
- * ```
118
- *
119
- * Using an Arrow Function instead of a traditional method Controller can be
120
- * useful when immediately returning a value. However, there are a few downsides
121
- * to using an Arrow `Function` for a Controller action, such as not being able
122
- * to call the `super class`. This can be an issue if you are looking to extend
123
- * a built-in action.
124
- *
125
- * Another use case for a custom action could be to return a specific scope of
126
- * data from a `Model`. Let's implement
127
- * a custom `drafts` route on a `PostsController`.
128
- *
129
- * ```javascript
130
- * // app/controllers/posts.js
131
- * import { Controller } from 'lumen-framework';
132
- * import Post from 'app/models/posts';
133
- *
134
- * class PostsController extends Controller {
135
- * drafts() {
136
- * return Post.where({
137
- * isPublic: false
138
- * });
139
- * }
18
+ * params = ['title', 'body', 'user'];
19
+ * sort = ['title', 'createdAt'];
20
+ * maxPerPage = 50;
140
21
  * }
141
22
  *
142
23
  * export default PostsController;
143
24
  * ```
144
25
  *
145
- * While the example above works, we would have to implement all the custom
146
- * logic that we get for free with built-in actions. Since we aren't getting too
147
- * crazy with our custom action we can likely just call the `index` action and
148
- * chain a `.where()` to it.
26
+ * Override a built-in action, or add a custom one, with a method that takes
27
+ * `(request, response)`. `index` and `show` return a {@link Query}, so an
28
+ * override can narrow it and keep everything else:
149
29
  *
150
30
  * ```javascript
151
- * // app/controllers/posts.js
152
- * import { Controller } from 'lumen-framework';
153
- *
154
31
  * class PostsController extends Controller {
155
- * drafts(request, response) {
156
- * return this.index(request, response).where({
157
- * isPublic: false
158
- * });
32
+ * index(request, response) {
33
+ * return super.index(request, response).where({ isPublic: true });
159
34
  * }
160
35
  * }
161
- *
162
- * export default PostsController;
163
36
  * ```
164
37
  *
165
- * Now we can sort, filter, and paginate our custom `drafts` route!
166
- *
167
- * #### Middleware
168
- *
169
- * Middleware can be a very powerful tool in many Node.js server frameworks. Lumen
170
- * is no exception. Middleware can be used to execute logic before or after a
171
- * Controller action is executed.
172
- *
173
- * There are two hooks where you can execute middleware functions,
174
- * `beforeAction` and `afterAction`. Functions added to the `beforeAction` hook
175
- * will execute before the Controller action and functions added to the
176
- * `afterAction` hook will be executed after the `Controller` action.
177
- *
178
- * **Context**
179
- *
180
- * Middleware functions will be bound to the Controller they are added to upon
181
- * the start of an Application.
182
- *
183
- * Due to the lexical binding of arrow functions, if you need to use the `this`
184
- * keyword within a middleware function, declare the middleware function using
185
- * the `function` keyword and not as an arrow function.
186
- *
187
- * **Scoping Middleware**
188
- *
189
- * Middleware is scoped by Controller and includes a parent Controller's
190
- * middleware recursively until the parent Controller is the root
191
- * `ApplicationController`. This allows you to implement custom logic that can
192
- * be executed for resources, namespaces, or an entire Application.
193
- *
194
- * Let's say we want to require authentication for every route in our
195
- * Application. All we have to do is move our authentication middleware function
196
- * from the example above to the `ApplicationController`.
197
- *
198
- * ```javascript
199
- * // app/controllers/application.js
200
- * import { Controller } from 'lumen-framework';
201
- *
202
- * class ApplicationController extends Controller {
203
- * beforeAction = [
204
- * async function authenticate(request) {
205
- * if (!request.currentUser) {
206
- * // 401 Unauthorized
207
- * return false;
208
- * }
209
- * }
210
- * ];
211
- * }
212
- *
213
- * export default ApplicationController;
214
- * ```
215
- *
216
- * **Execuation Order**
217
- *
218
- * Understanding the execution order of middleware functions and a `Controller`
219
- * action is essential to productivity with Lumen. Depending on what you use case
220
- * is, you may want your function to execute at different times in the
221
- * `request` / `response` cycle.
222
- *
223
- * 1. Parent `Controller` `beforeAction` hooks
224
- * 2. `Controller` `beforeAction` hooks
225
- * 3. `Controller` Action
226
- * 4. `Controller` `afterAction` hooks
227
- * 5. Parent `Controller` `afterAction` hooks
228
- *
229
- * **Modules**
230
- *
231
- * It is considered a best practice to define your middleware functions in
232
- * separate file and export them for use throughout an Application. Typically
233
- * this is done within an `app/middleware` directory.
234
- *
235
- * ```javascript
236
- * // app/middleware/authenticate.js
237
- * export default async function authenticate(request) {
238
- * if (!request.currentUser) {
239
- * // 401 Unauthorized
240
- * return false;
241
- * }
242
- * }
243
- * ```
244
- *
245
- * This keeps the Controller code clean, easier to read, and easier to modify.
246
- *
247
- * ```javascript
248
- * // app/controllers/application.js
249
- * import { Controller } from 'lumen-framework';
250
- * import authenticate from 'app/middleware/authenticate';
251
- *
252
- * class ApplicationController extends Controller {
253
- * beforeAction = [
254
- * authenticate
255
- * ];
256
- * }
257
- *
258
- * export default ApplicationController;
259
- * ```
260
- *
261
- * @class Controller
262
- * @public
38
+ * What an action returns becomes the response: a query, record or array of
39
+ * records is serialized as a JSON:API document; another object or array is
40
+ * sent as JSON, a string as the body; a number is that status, `true` a
41
+ * `204 No Content`, `false` a `401 Unauthorized`, and `undefined` a
42
+ * `404 Not Found`.
43
+ *
44
+ * A namespace's `ApplicationController` (`app/controllers/application.js`,
45
+ * `app/controllers/admin/application.js`) holds what applies to the whole
46
+ * namespace: its hooks run around every action in it, and it declares the
47
+ * {@link Controller.visibility} rules and the settings
48
+ * `rejectUnlistedAttributes`, `rejectUnlistedRelationships` and
49
+ * `maxIncludeDepth` for every controller in it. See the
50
+ * [controllers guide](https://github.com/nickschot/lux/blob/main/docs/guides/controllers.md).
263
51
  */
264
52
  declare class Controller {
265
53
  /**
266
- * An array of custom query parameter keys that are allowed to reach a
267
- * Controller instance from an incoming `HTTP` request.
268
- *
269
- * For security reasons, query parameters passed to Controller actions from an
270
- * incoming request other than sort, filter, and page must have their key
271
- * whitelisted.
54
+ * Query parameters an action may read beyond the JSON:API ones (`sort`,
55
+ * `filter`, `page`, `include`, `fields`). Any other query parameter is a
56
+ * `400 Bad Request`. A listed one arrives in `request.params`:
272
57
  *
273
58
  * ```javascript
274
- * class UsersController extends Controller {
275
- * // Allow the following custom query parameters to be used for this
276
- * // Controller's actions.
277
- * query = [
278
- * 'cache'
279
- * ];
59
+ * class PostsController extends Controller {
60
+ * query = ['search'];
61
+ *
62
+ * index(request, response) {
63
+ * const { search } = request.params;
64
+ * const posts = super.index(request, response);
65
+ *
66
+ * return search ? posts.where({ body: search }) : posts;
67
+ * }
280
68
  * }
281
69
  * ```
282
70
  *
283
- * @property query
284
- * @type {Array}
285
- * @default []
286
- * @public
71
+ * Name them with a character other than a–z (`search-term`, `searchTerm`):
72
+ * JSON:API reserves all-lowercase names for itself, and Lumen warns about
73
+ * them at boot.
287
74
  */
288
75
  query: Array<string>;
289
76
  /**
290
- * An array of sort query parameter values that are allowed to reach a
291
- * Controller instance from an incoming `HTTP` request.
292
- *
293
- * If you do not override this property all of the attributes specified in the
294
- * Serializer that represents a Controller's resource. If the Serializer
295
- * cannot be resolved, this property will default to an empty array.
296
- *
297
- * @property sort
298
- * @type {Array}
299
- * @default []
300
- * @public
77
+ * The attributes `?sort=` accepts, each also with `-` for descending.
78
+ * Defaults to every attribute the controller's serializer outputs; anything
79
+ * else is a `400 Bad Request`. Each must be a column of the model's table,
80
+ * or the app refuses to boot.
301
81
  */
302
82
  sort: Array<string>;
303
83
  /**
304
- * An array of filter query parameter keys that are allowed to reach a
305
- * Controller instance from an incoming `HTTP` request.
306
- *
307
- * If you do not override this property all of the attributes specified in the
308
- * Serializer that represents a Controller's resource. If the Serializer
309
- * cannot be resolved, this property will default to an empty array.
310
- *
311
- * @property filter
312
- * @type {Array}
313
- * @default []
314
- * @public
84
+ * The attributes `?filter[…]=` accepts. Defaults to every attribute the
85
+ * controller's serializer outputs; anything else is a `400 Bad Request`.
86
+ * Each must be a column of the model's table, or the app refuses to boot.
315
87
  */
316
88
  filter: Array<string>;
317
89
  /**
318
- * An array of parameter keys that are allowed to reach a Controller instance
319
- * from an incoming `POST` or `PATCH` request body.
90
+ * The attributes and relationships a `POST` or `PATCH` body may set.
320
91
  *
321
- * If you do not override this property all of the attributes specified in the
322
- * Serializer that represents a Controller's resource. If the Serializer
323
- * cannot be resolved, this property will default to an empty array.
92
+ * ```javascript
93
+ * class PostsController extends Controller {
94
+ * params = ['title', 'body', 'user'];
95
+ * }
96
+ * ```
324
97
  *
325
- * @property params
326
- * @type {Array}
327
- * @default []
328
- * @public
98
+ * An attribute the model has but this list doesn't name is ignored (dropped
99
+ * from `request.params`), so clients may send read-only attributes back; a
100
+ * relationship like that is answered with `403 Forbidden`.
101
+ * {@link Controller.rejectUnlistedAttributes} and
102
+ * {@link Controller.rejectUnlistedRelationships} change either. A member the
103
+ * model doesn't have at all is a `400 Bad Request`.
329
104
  */
330
105
  params: Array<string>;
331
106
  /**
332
- * Functions to execute on each request handled by a `Controller` before the
333
- * `Controller` action is executed.
334
- *
335
- * Functions added to the `beforeAction` hook behave similarly to `Controller`
336
- * actions, however, they are expected to return `undefined`. If a middleware
337
- * function returns a value other than `undefined` the `request` / `response`
338
- * cycle will end before remaining middleware and/or Controller actions are
339
- * executed. This makes the `beforeAction` hook a very powerful tool for
340
- * dealing with many common tasks, such as authentication.
341
- *
342
- * Functions called from the `beforeAction` hook will have `request` and
343
- * `response` objects passed as arguments.
344
- *
345
- * **Example:**
107
+ * Hooks that run before each action, called with `(request, response)`.
108
+ * Returning nothing lets the request continue; returning anything else ends
109
+ * it, with that value as the response (`false` → `401 Unauthorized`, a
110
+ * number → that status):
346
111
  *
347
112
  * ```javascript
348
- * import { Controller } from 'lumen-framework';
349
- *
350
- * const UNSAFE_METHODS = /(?:POST|PATCH|DELETE)/i;
351
- *
352
- * function isAdmin(user) {
353
- * if (user) {
354
- * return user.isAdmin;
355
- * }
356
- *
357
- * return false;
358
- * }
359
- *
360
- * async function authentication(request) {
361
- * const { method, currentUser } = request;
362
- * const isUnsafe = UNSAFE_METHODS.test(method);
363
- *
364
- * if (isUnsafe && !isAdmin(currentUser)) {
365
- * return false; // 401 Unauthorized if the current user is not an admin.
113
+ * async function requireUser(request) {
114
+ * if (!request.currentUser) {
115
+ * return false;
366
116
  * }
367
117
  * }
368
118
  *
369
119
  * class PostsController extends Controller {
370
- * beforeAction = [
371
- * authentication
372
- * ];
120
+ * beforeAction = [requireUser];
373
121
  * }
374
- *
375
- * export default PostsController;
376
122
  * ```
377
123
  *
378
- * @property beforeAction
379
- * @type {Array}
380
- * @default []
381
- * @public
124
+ * The hooks of a namespace's `ApplicationController` run around every action
125
+ * in the namespace, before the controller's own. Hooks run after the
126
+ * request's parameters are validated, and are called with `this` as the
127
+ * controller that declares them (use `function`, not an arrow function, to
128
+ * read it).
382
129
  */
383
- beforeAction: Array<Controller$beforeAction>;
130
+ beforeAction: Array<BeforeAction>;
384
131
  /**
385
- * Functions to execute on each request handled by a `Controller` after the
386
- * `Controller` action is executed.
387
- *
388
- * Functions called from the `afterAction` hook will have `request` and
389
- * `response` objects passed as arguments as well as a third `payload`
390
- * argument. The `payload` argument is a reference to the resolved data of
391
- * the Controller action that was called within the current `request` /
392
- * `response` cycle. You need to explicitly return this `payload` in order for
393
- * the afterAction to resolve with it's data. If you return a modified value
394
- * from a function added to the `afterAction` hook, that value will be used
395
- * instead of the resolved data from the preceding Controller action.
396
- * Subsequent hooks called from an `afterAction` hook will will use the value
397
- * returned or resolved from the preceding hook. This makes `afterAction` a
398
- * great place to modify the data you are sending back to the client.
399
- *
400
- * **Example:**
132
+ * Hooks that run after each action, called with
133
+ * `(request, response, payload)`. `payload` is the action's result — for a
134
+ * resource, the JSON:API document about to be sent. What a hook returns is
135
+ * sent instead, and passed to the next hook, so return `payload` when
136
+ * leaving it as it is:
401
137
  *
402
138
  * ```javascript
403
- * import { Controller } from 'lumen-framework';
404
- *
405
- * async function addCopyright(request, response, payload) {
406
- * const { action } = request;
407
- *
408
- * if (payload && action !== preflight) {
409
- * return {
410
- * ...payload,
411
- * meta: {
412
- * copyright: '2016 (c) Postlight'
413
- * }
414
- * };
139
+ * async function addVersion(request, response, payload) {
140
+ * if (payload && payload.jsonapi) {
141
+ * return { ...payload, meta: { ...payload.meta, apiVersion: '2' } };
415
142
  * }
416
143
  *
417
144
  * return payload;
418
145
  * }
419
146
  *
420
147
  * class ApplicationController extends Controller {
421
- * afterAction = [
422
- * addCopyright
423
- * ];
148
+ * afterAction = [addVersion];
424
149
  * }
425
- *
426
- * export default ApplicationController;
427
150
  * ```
428
151
  *
429
- * @property afterAction
430
- * @type {Array}
431
- * @default []
432
- * @public
152
+ * A namespace `ApplicationController`'s `afterAction` hooks run after the
153
+ * controller's own.
433
154
  */
434
- afterAction: Array<Controller$afterAction>;
155
+ afterAction: Array<AfterAction>;
435
156
  /**
436
- * The default amount of items to include per each response of the index
437
- * action if a `?page[size]` query parameter is not specified.
438
- *
439
- * @property defaultPerPage
440
- * @type {Number}
441
- * @default 25
442
- * @public
157
+ * The page size of `index` when the request gives no `?page[size]=`.
443
158
  */
444
159
  defaultPerPage: number;
160
+ /**
161
+ * The largest `?page[size]=` `index` accepts. A larger one is a
162
+ * `400 Bad Request`, as is a `page[size]` or `page[number]` below 1.
163
+ */
164
+ maxPerPage: number;
165
+ /**
166
+ * Answer an attribute the model has but `params` does not list with
167
+ * `403 Forbidden` (an unsupported update, per JSON:API) instead of ignoring
168
+ * it. Off by default: clients like ember-data send every attribute back on
169
+ * save, read-only ones (`createdAt`) included.
170
+ *
171
+ * Set on a namespace's `ApplicationController`, it applies to every
172
+ * controller in the namespace (and in namespaces nested in it) that does not
173
+ * set it itself — whatever class those controllers extend.
174
+ *
175
+ * @default false
176
+ */
177
+ rejectUnlistedAttributes: boolean;
178
+ /**
179
+ * Answer a relationship the model has but `params` does not list with
180
+ * `403 Forbidden` (an unsupported update, per JSON:API). Turn it off to
181
+ * ignore such relationships instead, for clients that send every
182
+ * `belongsTo` back on save (ember-data). Like `rejectUnlistedAttributes`,
183
+ * setting it on a namespace's `ApplicationController` sets it for the whole
184
+ * namespace:
185
+ *
186
+ * ```javascript
187
+ * class ApplicationController extends Controller {
188
+ * rejectUnlistedRelationships = false;
189
+ * }
190
+ * ```
191
+ *
192
+ * @default true
193
+ */
194
+ rejectUnlistedRelationships: boolean;
445
195
  /**
446
196
  * How many relationships deep an `?include` path may go on this
447
197
  * controller's routes. `comments.reactions.user` is 3 levels deep; with `1`
448
198
  * only direct relationships (`comments`) can be included. Paths deeper than
449
- * this are rejected with `400 Bad Request`.
199
+ * this are rejected with `400 Bad Request`; `0` turns `?include` off.
450
200
  *
451
- * Set it on `ApplicationController` to change it for the whole app, or on a
452
- * single controller to override it there.
201
+ * Set on a namespace's `ApplicationController`, it applies to every
202
+ * controller in the namespace (and in namespaces nested in it) that does not
203
+ * set it itself — whatever class those controllers extend.
453
204
  *
454
205
  * ```javascript
455
206
  * class ApplicationController extends Controller {
@@ -461,10 +212,10 @@ declare class Controller {
461
212
  * relationships, and each nested level costs its own queries per request, so
462
213
  * keep this small.
463
214
  *
464
- * @property maxIncludeDepth
465
- * @type {Number}
215
+ * In a namespace without {@link Controller.visibility} rules it defaults to
216
+ * `0`: nothing there scopes the included records.
217
+ *
466
218
  * @default 3
467
- * @public
468
219
  */
469
220
  maxIncludeDepth: number;
470
221
  /**
@@ -489,168 +240,308 @@ declare class Controller {
489
240
  * serialize or `include` (down to each controller's `maxIncludeDepth`) has
490
241
  * no Serializer in that namespace, listing each missing one.
491
242
  *
492
- * @property serializerFallback
493
- * @type {Boolean}
494
243
  * @default true
495
- * @public
496
244
  */
497
245
  serializerFallback: boolean;
498
246
  /**
499
- * The Serializer to serialize (and validate, and load) related resources of
500
- * this Controller's responses with: the related model's Serializer in this
501
- * Controller's namespace, falling back to the root one.
247
+ * Which rows of each type a request may see, declared once per namespace on
248
+ * its `ApplicationController`. Each rule receives a query of its type and
249
+ * the request, and returns the query narrowed:
250
+ *
251
+ * ```javascript
252
+ * // app/controllers/application.js
253
+ * class ApplicationController extends Controller {
254
+ * static visibility = {
255
+ * posts: query => query.isPublic(),
256
+ * comments: (query, { currentUser }) =>
257
+ * query.where({ userId: currentUser.id })
258
+ * };
259
+ * }
260
+ * ```
261
+ *
262
+ * Lumen applies the rule wherever it loads rows of that type for a request
263
+ * in the namespace: `index` and its page links, `show`, `update` and
264
+ * `destroy` (a hidden record is `404 Not Found`, like a missing one), every
265
+ * relationship's resource linkage, `included` resources at any depth, and
266
+ * the related records referenced by a `create` or `update` (a hidden one is
267
+ * reported as not found). A to-one relationship to a hidden record is
268
+ * serialized as `null`; a to-many one leaves it out.
269
+ *
270
+ * Rules must be synchronous and may only add conditions (`where`, `not`,
271
+ * `whereBetween`, `whereRaw`, or model scopes built from them). Load what
272
+ * a rule needs in a `beforeAction` hook and read it from the request.
273
+ *
274
+ * A nested namespace follows its parent namespace's rules unless its
275
+ * `ApplicationController` declares its own — whether that class extends
276
+ * `Controller` or the parent's `ApplicationController`, and also when the
277
+ * namespace has no `ApplicationController`. Replace them, or build on them
278
+ * through `super` in a class that extends the parent's:
279
+ *
280
+ * ```javascript
281
+ * // app/controllers/admin/application.js
282
+ * class AdminApplicationController extends Controller {
283
+ * static visibility = {}; // admins see everything
284
+ * }
285
+ *
286
+ * // app/controllers/members/application.js
287
+ * class MembersApplicationController extends ApplicationController {
288
+ * static visibility = { ...super.visibility, drafts: … };
289
+ * }
290
+ * ```
291
+ *
292
+ * Declaring `visibility` on any other controller is a boot error: types are
293
+ * included across controllers, so a rule must hold for the whole
294
+ * namespace.
295
+ *
296
+ * Rules do not apply to queries an application builds itself, such as a
297
+ * custom action's `Post.where(...)` or a relationship read from a model
298
+ * (`await post.comments`). Narrow those with `visible()`.
299
+ *
300
+ * **Visibility rules and model scopes**
301
+ *
302
+ * A model scope (`static scopes` on a Model, e.g. `Post.isPublic()`) is a
303
+ * reusable piece of a query: it narrows the one query it is called on, and
304
+ * only when application code calls it. A visibility rule is an access
305
+ * policy: Lumen applies it to every query it issues for a request. The two
306
+ * compose — a rule is usually written with a scope.
307
+ *
308
+ * | | Model scope | Visibility rule |
309
+ * |-------------------|----------------------|-------------------------|
310
+ * | Declared on | the Model | a namespace's |
311
+ * | | | `ApplicationController` |
312
+ * | Applied | where code calls it | to every query Lumen |
313
+ * | | | issues for the request |
314
+ * | Sees the request | no | yes |
315
+ * | Per namespace | no | yes |
316
+ * | May use | any query method | conditions only |
317
+ * | `unscope()` | removes it | cannot remove it |
318
+ *
319
+ * Scoping a built-in action is not the same as hiding records. With
320
+ *
321
+ * ```javascript
322
+ * class PostsController extends Controller {
323
+ * index(request) {
324
+ * return super.index(request).isPublic();
325
+ * }
326
+ * }
327
+ * ```
328
+ *
329
+ * private posts are left out of `GET /posts`, but are still served by
330
+ * `GET /posts/:id`, listed in the `posts` linkage of a user and in
331
+ * `included` for `/users?include=posts`, linked from a comment's `post`,
332
+ * and accepted as the `post` of a new comment. `posts: query =>
333
+ * query.isPublic()` as a visibility rule closes every one of those paths.
334
+ *
335
+ * A namespace without rules, its own or a parent's, gets conservative
336
+ * defaults: `maxIncludeDepth` is `0` (no includes), resources serve no
337
+ * relationship or related endpoints unless they ask for them, and the app
338
+ * warns at boot. `static visibility = {}` declares that a namespace may see
339
+ * everything, and lifts them.
340
+ */
341
+ static visibility: Visibility;
342
+ /**
343
+ * Narrow `query` with the visibility rule for its type that applies to
344
+ * `request`'s namespace, as the built-in actions do.
345
+ *
346
+ * ```javascript
347
+ * class PostsController extends Controller {
348
+ * drafts(request) {
349
+ * return this.visible(Post.where({ isPublic: false }), request);
350
+ * }
351
+ * }
352
+ * ```
353
+ *
354
+ * @param query - A query of any type.
355
+ * @param request - The request object.
356
+ * @returns The same query, narrowed.
357
+ */
358
+ visible<Q extends Query<unknown>>(query: Q, request: Request): Q;
359
+ /**
360
+ * The Serializer to serialize (and validate the `fields` of) related
361
+ * resources of this Controller's responses with: the related model's
362
+ * Serializer in this Controller's namespace, falling back to the root one.
502
363
  *
503
364
  * Always this Controller's namespace — not its Serializer's, which is the
504
365
  * root one when the namespace has no Serializer for this resource.
505
366
  *
506
- * @method serializerFor
507
- * @private
367
+ * @internal
508
368
  */
509
369
  serializerFor(model: ModelClass): Serializer<Model>;
510
370
  /**
511
371
  * The resolved Model for a Controller instance.
512
372
  *
513
- * @property model
514
- * @type {Model}
515
- * @private
373
+ * @internal
516
374
  */
517
375
  model: ModelClass<Model>;
518
376
  /**
519
377
  * A reference to the root Controller for the namespace that a Controller
520
378
  * instance is a member of.
521
379
  *
522
- * @property parent
523
- * @type {?Controller}
524
- * @private
380
+ * @internal
525
381
  */
526
382
  parent: Controller | null;
527
383
  /**
528
384
  * The namespace that a Controller instance is a member of.
529
385
  *
530
- * @property namespace
531
- * @type {String}
532
- * @private
386
+ * @internal
533
387
  */
534
388
  namespace: string;
535
389
  /**
536
390
  * The resolved Serializer for a Controller instance.
537
391
  *
538
- * @property serializer
539
- * @type {Serializer}
540
- * @private
392
+ * @internal
541
393
  */
542
394
  serializer: Serializer<Model>;
543
395
  /**
544
396
  * A Map instance containing a reference to all the Controller within an
545
397
  * Application instance.
546
398
  *
547
- * @property controllers
548
- * @type {Map}
549
- * @private
399
+ * @internal
550
400
  */
551
401
  controllers: Map<string, Controller>;
402
+ /**
403
+ * The visibility rules of this Controller's namespace, resolved at boot
404
+ * from the `static visibility` of the closest `ApplicationController`, from
405
+ * its own namespace's up, that declares rules.
406
+ *
407
+ * @internal
408
+ */
409
+ visibility: Visibility;
410
+ /**
411
+ * Whether this Controller's namespace, or one it is nested in, declares
412
+ * visibility rules — `static visibility = {}` included. Without any, the
413
+ * namespace gets conservative defaults (see `restrictOpenNamespaces()`).
414
+ * Resolved at boot.
415
+ *
416
+ * @internal
417
+ */
418
+ hasVisibilityRules: boolean;
552
419
  /**
553
420
  * A boolean value representing whether or not a Controller instance has a
554
421
  * Model.
555
422
  *
556
- * @property hasModel
557
- * @type {Boolean}
558
- * @private
423
+ * @internal
559
424
  */
560
425
  hasModel: boolean;
561
426
  /**
562
427
  * A boolean value representing whether or not a Controller instance is within
563
428
  * a namespace.
564
429
  *
565
- * @property hasNamespace
566
- * @type {Boolean}
567
- * @private
430
+ * @internal
568
431
  */
569
432
  hasNamespace: boolean;
570
433
  /**
571
434
  * A boolean value representing whether or not a Controller instance has a
572
435
  * Serializer.
573
436
  *
574
- * @property hasSerializer
575
- * @type {Boolean}
576
- * @private
437
+ * @internal
577
438
  */
578
439
  hasSerializer: boolean;
579
- constructor({ model, namespace, serializer }: Controller$opts);
440
+ constructor({ model, namespace, serializer }: ControllerOptions);
580
441
  /**
581
- * This method supports filtering, sorting, pagination, including
582
- * relationships, and sparse fieldsets via query parameters. For more
583
- * information, see the [fetching resources](https://goo.gl/q7FVgZ) section of
584
- * the JSON API specification.
442
+ * `GET /posts`: the records, sorted, filtered and paged by the request's
443
+ * query parameters, with its `include` and `fields`. Visibility rules apply.
585
444
  *
586
- * @method index
587
- * @param {Request} request - The request object.
588
- * @param {Response} response - The response object.
589
- * @return {Promise} Resolves with an array of Model instances.
590
- * @public
445
+ * @param request - The request.
446
+ * @param response - The response. Unused by the built-in action, but every
447
+ * action is called with it, so an override can take it.
448
+ * @returns A query of the page of records; narrow it in an override.
591
449
  */
592
- index(req: Request): Query<Array<Model>>;
450
+ index(request: Request, response?: Response): Query<Array<Model>>;
593
451
  /**
594
- * This method supports including relationships, and sparse fieldsets via
595
- * query parameters. For more information, see the [fetching resources](
596
- * https://goo.gl/q7FVgZ) section of the JSON API specification.
597
- *
598
- * @method show
599
- * @param {Request} request - The request object.
600
- * @param {Response} response - The response object.
601
- * @return {Promise} Resolves with a Model instance with the id equal to the
602
- * id url parameter.
603
- * @public
452
+ * `GET /posts/1`: the record with the route's id, with the request's
453
+ * `include` and `fields`. Visibility rules apply; a record the request may
454
+ * not see, like a missing one, is a `404 Not Found`.
455
+ *
456
+ * @param request - The request.
457
+ * @param response - The response. Unused by the built-in action, but every
458
+ * action is called with it, so an override can take it.
459
+ * @returns A query of the record; narrow it in an override.
604
460
  */
605
- show(req: Request): Query<Model>;
461
+ show(request: Request, response?: Response): Query<Model>;
606
462
  /**
607
- * Create and return a single Model instance that the Controller instance
608
- * represents. For more information, see the [creating resources](
609
- * https://goo.gl/4Obc9t) section of the JSON API specification.
610
- *
611
- * @method create
612
- * @param {Request} request - The request object.
613
- * @param {Response} response - The response object.
614
- * @return {Promise} Resolves with the newly created Model instance.
615
- * @public
463
+ * `GET /posts/1/relationships/comments`, a relationship endpoint: resolves
464
+ * the resource that owns the relationship (`request.route.relationship`),
465
+ * whose resource linkage is the response.
466
+ *
467
+ * The resource is resolved through this controller's `show`, asking for its
468
+ * primary key only, so whatever `show` enforces holds here too: an override
469
+ * that narrows its query or rejects the request applies, and a resource the
470
+ * request may not see is a `404 Not Found`. Hooks see the action
471
+ * `showRelationship` (`request.route.type` is `relationship`).
472
+ *
473
+ * @param request - The request.
474
+ * @param response - The response. Unused by the built-in action, but every
475
+ * action is called with it, so an override can take it.
476
+ * @returns A query of the owning record.
616
477
  */
617
- create(req: Request, res: Response): Promise<Model>;
478
+ showRelationship(request: Request, response?: Response): Query<Model>;
618
479
  /**
619
- * Update and return a single Model instance that the Controller instance
620
- * represents. For more information, see the [updating resources](
621
- * https://goo.gl/o2ZdOR)section of the JSON API specification.
622
- *
623
- * @method update
624
- * @param {Request} request - The request object.
625
- * @param {Response} response - The response object.
626
- * @return {Promise} Resolves with the updated Model if changes occur.
627
- * Resolves with the number `204` if no changes occur.
628
- * @public
480
+ * `GET /posts/1/comments`, a related endpoint: the resources the
481
+ * relationship `request.route.relationship` of the record with the route's id
482
+ * points to.
483
+ *
484
+ * The query parameters are those of the related type's controller: for a
485
+ * to-many relationship they page, sort and filter like its `index`, for a
486
+ * to-one one they include and select like its `show`. Visibility rules apply
487
+ * to the related resources; the owning record is resolved with
488
+ * {@link Controller.showRelationship} first, so one the request may not see
489
+ * is a `404 Not Found`. Hooks see the action `showRelated`
490
+ * (`request.route.type` is `related`).
491
+ *
492
+ * @param request - The request.
493
+ * @param response - The response. Unused by the built-in action, but every
494
+ * action is called with it, so an override can take it.
495
+ * @returns A query of the related records (to-many), or of the related record
496
+ * (to-one, resolving with `undefined` when there is none).
497
+ */
498
+ showRelated(request: Request, response?: Response): Query<Array<Model>> | Query<Model>;
499
+ /**
500
+ * `POST /posts`: creates a record from the request body's attributes and
501
+ * relationships, after checking that every related record exists and is
502
+ * visible (a `404 Not Found` otherwise). Answers `201 Created` with a
503
+ * `Location` header.
504
+ *
505
+ * @param request - The request.
506
+ * @param response - The response, for the status and `Location` header.
507
+ * @returns Resolves with the new record.
508
+ */
509
+ create(request: Request, response: Response): Promise<Model>;
510
+ /**
511
+ * `PATCH /posts/1`: updates the record with the route's id from the request
512
+ * body, after checking that every related record exists and is visible.
513
+ * A record the request may not see is a `404 Not Found`.
514
+ *
515
+ * @param request - The request.
516
+ * @param response - The response. Unused by the built-in action, but every
517
+ * action is called with it, so an override can take it.
518
+ * @returns Resolves with the updated record, or with `204` (`204 No Content`)
519
+ * when nothing changed.
629
520
  */
630
- update(req: Request): Promise<number | Model>;
521
+ update(request: Request, response?: Response): Promise<number | Model>;
631
522
  /**
632
- * Destroy a single Model instance that the Controller instance represents.
633
- * For more information, see the [deleting resources](https://goo.gl/nUZn8t)
634
- * section of the JSON API specification.
523
+ * `DELETE /posts/1`: deletes the record with the route's id. A record the
524
+ * request may not see is a `404 Not Found`.
635
525
  *
636
- * @method destroy
637
- * @param {Request} request - The request object.
638
- * @param {Response} response - The response object.
639
- * @return {Promise} Resolves with the number `204`.
640
- * @public
526
+ * @param request - The request.
527
+ * @param response - The response. Unused by the built-in action, but every
528
+ * action is called with it, so an override can take it.
529
+ * @returns Resolves with `204` (`204 No Content`).
641
530
  */
642
- destroy(req: Request): Promise<number>;
531
+ destroy(request: Request, response?: Response): Promise<number>;
643
532
  /**
644
- * Respond to HEAD or OPTIONS requests.
533
+ * Answers `OPTIONS` requests: `204 No Content`, with the path's methods in
534
+ * `Allow`.
645
535
  *
646
- * @method preflight
647
- * @param {Request} request - The request object.
648
- * @param {Response} response - The response object.
649
- * @return {Promise} Resolves with the number `204`.
650
- * @public
536
+ * @param request - The request. Unused.
537
+ * @param response - The response. Unused by the built-in action, but every
538
+ * action is called with it, so an override can take it.
539
+ * @returns Resolves with `204`.
651
540
  */
652
- preflight(): Promise<number>;
541
+ preflight(request?: Request, response?: Response): Promise<number>;
653
542
  }
654
543
  export default Controller;
655
- export { BUILT_IN_ACTIONS } from './constants';
656
- export type { Controller$opts, Controller$builtIn, Controller$beforeAction, Controller$afterAction } from './interfaces';
544
+ export { BUILT_IN_ACTIONS, NAMESPACE_SETTINGS } from './constants';
545
+ export { Scope } from './visibility';
546
+ export type { Visibility } from './visibility';
547
+ export type { ControllerOptions, BuiltInAction, BeforeAction, AfterAction } from './interfaces';