lumen-framework 3.1.1 → 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 +3273 -1719
  6. package/dist/index.js.map +4 -4
  7. package/dist/index.mjs +3251 -1697
  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,10 +1,26 @@
1
- import type { Server$ErrorSource } from '../interfaces';
1
+ import type { ServerErrorSource } from '../interfaces';
2
2
  /**
3
3
  * Map an internal parameter path to a JSON:API error `source`. Paths under
4
4
  * `data` are request document members and become a JSON Pointer
5
5
  * (`data.attributes.isPublic` -> `/data/attributes/is-public`); anything else
6
6
  * is a query parameter (`page.size` -> `page[size]`).
7
7
  *
8
- * @private
8
+ * @internal
9
9
  */
10
- export default function sourceFor(path: string): Server$ErrorSource;
10
+ export default function sourceFor(path: string): ServerErrorSource;
11
+ /**
12
+ * A parameter path as the client writes it, for error messages: request
13
+ * document members dasherized and dotted (`data.attributes.is-public`), query
14
+ * parameters in brackets (`filter[created-at]`, `page[size]`).
15
+ *
16
+ * @internal
17
+ */
18
+ export declare function nameFor(path: string): string;
19
+ /**
20
+ * A member name or relationship path as it appears in documents, keeping a
21
+ * `sort` value's leading `-` (`-createdAt` -> `-created-at`,
22
+ * `comments.user` stays dotted). Anything but a string is returned as is.
23
+ *
24
+ * @internal
25
+ */
26
+ export declare function memberPathFor(value: unknown): unknown;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The status an error is answered with: its own `statusCode`, or `500`.
3
+ *
4
+ * @internal
5
+ */
6
+ export default function statusForError(err: unknown): number;
@@ -3,6 +3,6 @@
3
3
  * type and *all* instances of it are modified with media type parameters.
4
4
  * An Accept header without the JSON:API media type is left alone.
5
5
  *
6
- * @private
6
+ * @internal
7
7
  */
8
8
  export default function validateAccept(accept?: string): true;
@@ -1,8 +1,13 @@
1
1
  /**
2
2
  * JSON:API 1.0: respond 415 if the Content-Type is the JSON:API media type
3
3
  * with any media type parameters. A missing or different Content-Type is
4
- * also answered with 415, since that is the only type the server accepts.
4
+ * also answered with 415, since that is the only type a resource accepts.
5
5
  *
6
- * @private
6
+ * A plain route (`json`) takes any JSON body, so `application/json` (with
7
+ * any parameters, such as `charset`) is accepted there too.
8
+ *
9
+ * @internal
7
10
  */
8
- export default function validateContentType(contentType?: string): true;
11
+ export default function validateContentType(contentType?: string, { json }?: {
12
+ json?: boolean;
13
+ }): true;
@@ -0,0 +1,189 @@
1
+ import type Application from '../application';
2
+ /**
3
+ * Which records of one type a request may see, for {@link auditVisibility}:
4
+ * every one (`true`), the ids listed, or the ids a function accepts.
5
+ */
6
+ export type VisibleRecords = true | ReadonlyArray<string | number> | ((id: string) => boolean);
7
+ /** The options of {@link auditVisibility}. */
8
+ export type AuditVisibilityOptions = {
9
+ /**
10
+ * The namespace to audit: `''` (the default) for the root, `'admin'` for
11
+ * `/admin`. Nested namespaces are audited on their own.
12
+ */
13
+ namespace?: string;
14
+ /**
15
+ * What the request may see, keyed by type. Written by hand, independently
16
+ * of the app's visibility rules: it is what they are checked against. A
17
+ * type left out may not appear at all.
18
+ */
19
+ visible: Record<string, VisibleRecords>;
20
+ /**
21
+ * Headers sent with every request, such as the `Authorization` of the user
22
+ * the audit is for.
23
+ */
24
+ headers?: Record<string, string>;
25
+ /**
26
+ * The ids to request each type's routes with (`GET /posts/:id`,
27
+ * `/posts/:id/comments`, …), keyed by type: visible and hidden ones
28
+ * alike. A type left out is requested with every id in the database, so
29
+ * keep the database small or list the ids.
30
+ */
31
+ ids?: Record<string, ReadonlyArray<string | number>>;
32
+ /**
33
+ * Query parameters a read requires, keyed by the type it serves: they are
34
+ * sent with that type's list, its records by id, and every related
35
+ * endpoint that serves it (`/posts/:id/comments` serves `comments`, and
36
+ * takes the parameters of the comments' controller). Relationship
37
+ * endpoints take none.
38
+ *
39
+ * ```javascript
40
+ * query: { comments: { fromDate: '2026-01-01' } }
41
+ * ```
42
+ */
43
+ query?: Record<string, Record<string, string>>;
44
+ /**
45
+ * Where the application is served, when not by `app` itself: a server
46
+ * started as a separate process (`lumen serve`), such as
47
+ * `'http://localhost:4000'`. `app` still provides the routes, the
48
+ * include paths and the ids, so it must be booted in the test, but need
49
+ * not listen.
50
+ */
51
+ origin?: string;
52
+ /**
53
+ * Called with each document a read answers with, for checks beyond which
54
+ * records appear, such as the fields a request may see of each. Return a
55
+ * message, or several, for each problem found: each is reported as a
56
+ * violation of that request. May be async.
57
+ *
58
+ * ```javascript
59
+ * onDocument({ document }) {
60
+ * return document.included
61
+ * ?.filter(({ type, attributes }) => type === 'users' && attributes.email)
62
+ * .map(({ id }) => `users ${id} shows its email`);
63
+ * }
64
+ * ```
65
+ */
66
+ onDocument?: (response: AuditedDocument) => DocumentCheckResult | Promise<DocumentCheckResult>;
67
+ };
68
+ /**
69
+ * The read a request was made to, as the route defines it: so a check need
70
+ * not parse the URL to know which record it is about.
71
+ */
72
+ export type AuditedRoute = {
73
+ /** The action, as hooks see it. */
74
+ action: 'index' | 'show' | 'showRelationship' | 'showRelated';
75
+ /**
76
+ * The route's resource type: for a relationship or related endpoint, the
77
+ * owner's (`posts` for `/posts/3/comments`).
78
+ */
79
+ type: string;
80
+ /**
81
+ * The id in the URL: the record of a `show`, the owner of a relationship
82
+ * or related endpoint. None for a list.
83
+ */
84
+ id?: string;
85
+ /** The relationship of a relationship or related endpoint (`comments`). */
86
+ relationship?: string;
87
+ };
88
+ /** A document a read answered with, for `onDocument`. */
89
+ export type AuditedDocument = {
90
+ /** The request, as a path and query string. */
91
+ url: string;
92
+ /** Its status. */
93
+ status: number;
94
+ /** The read the request was made to. */
95
+ route: AuditedRoute;
96
+ /** The parsed JSON:API document. */
97
+ document: Record<string, unknown>;
98
+ };
99
+ /**
100
+ * What `onDocument` returns: a message for each problem found, or nothing
101
+ * when there is none.
102
+ */
103
+ export type DocumentCheckResult = string | ReadonlyArray<string> | null | undefined | void;
104
+ /**
105
+ * A record a response contained that the audit's `visible` does not allow; a
106
+ * relationship or related endpoint that answered for an owner `visible` does
107
+ * not allow; a request that failed with an error other than `401`, `403` or
108
+ * `404`, so that what it serves could not be checked; or a problem
109
+ * `onDocument` found.
110
+ */
111
+ export type VisibilityViolation = {
112
+ /** The request, as a path and query string. */
113
+ url: string;
114
+ /** Its status. */
115
+ status: number;
116
+ /**
117
+ * The record's type, if the violation is a record: one the response named,
118
+ * or the hidden owner an endpoint answered for.
119
+ */
120
+ type?: string;
121
+ /** The record's id, if the violation is a record. */
122
+ id?: string;
123
+ /**
124
+ * What is wrong, for a hidden owner an endpoint answered for and for what
125
+ * `onDocument` found.
126
+ */
127
+ message?: string;
128
+ };
129
+ /** What {@link auditVisibility} found. */
130
+ export type VisibilityAudit = {
131
+ /** Every request made, as a path and query string. */
132
+ requests: Array<string>;
133
+ /** What should not have been in a response, in request order. */
134
+ violations: Array<VisibilityViolation>;
135
+ /**
136
+ * Every record the responses named, keyed by type: as primary data,
137
+ * included or as linkage, allowed or not, each id once. Compare it with
138
+ * what the request should see to check that the audit reached it all.
139
+ */
140
+ seen: Record<string, Array<string>>;
141
+ };
142
+ /**
143
+ * Request every read a namespace serves — each list, each record by id, each
144
+ * relationship and related endpoint, without `include` and with every path
145
+ * it accepts, following every page — and report each record in a response that
146
+ * `visible` does not allow: in `data`, in `included`, or in any
147
+ * relationship's linkage. A relationship or related endpoint that answers
148
+ * for an owner `visible` does not allow is reported too, whatever it
149
+ * answers with: that it answers reveals the owner. A `401`, `403` or `404`
150
+ * (for a hidden record) reveals nothing and passes; any other error is
151
+ * reported, since the read it answers went unchecked.
152
+ *
153
+ * Visibility rules apply to every one of these paths, but scoping in an
154
+ * `index` or `show` override, or in a hook keyed on the action, does not.
155
+ * This checks the result rather than the mechanism, against a list written
156
+ * by hand:
157
+ *
158
+ * ```javascript
159
+ * import { auditVisibility } from 'lumen-framework/testing';
160
+ *
161
+ * it('shows a member only public posts and their comments', async () => {
162
+ * const { violations } = await auditVisibility(app, {
163
+ * namespace: 'members',
164
+ * headers: { Authorization: `Bearer ${memberToken}` },
165
+ * visible: {
166
+ * posts: [publicPost.id],
167
+ * comments: [commentOnPublicPost.id],
168
+ * users: true
169
+ * }
170
+ * });
171
+ *
172
+ * expect(violations).toEqual([]);
173
+ * });
174
+ * ```
175
+ *
176
+ * Requests are made one at a time, to `app` itself (which must then be
177
+ * listening, as {@link startApp} leaves it) or to `origin`. Custom routes are
178
+ * not requested. Each route is requested once per
179
+ * id (and per page), so run it against a small fixture database, or narrow
180
+ * the ids with `ids`.
181
+ *
182
+ * @param app - The application, listening.
183
+ * @param options - What to audit, and what the request may see.
184
+ * @returns Every request made, every violation found, and every record
185
+ * seen.
186
+ * @throws When the namespace serves no reads, so a mistyped namespace cannot
187
+ * pass by checking nothing.
188
+ */
189
+ export default function auditVisibility(app: Application, { namespace, visible, headers, ids, query: required, origin, onDocument }: AuditVisibilityOptions): Promise<VisibilityAudit>;
@@ -0,0 +1,4 @@
1
+ export { default as auditVisibility } from './audit-visibility';
2
+ export { default as startApp } from './start-app';
3
+ export type { StartAppOptions, StartedApp } from './start-app';
4
+ export type { AuditedDocument, AuditedRoute, AuditVisibilityOptions, DocumentCheckResult, VisibilityAudit, VisibilityViolation, VisibleRecords } from './audit-visibility';
@@ -0,0 +1,52 @@
1
+ import type Application from '../application';
2
+ /** The options of {@link startApp}. */
3
+ export type StartAppOptions = {
4
+ /**
5
+ * The environment to boot in: which `config/environments/*.js` and which
6
+ * entry of `config/database.js` apply. Sets `NODE_ENV` when given, and
7
+ * defaults it to `'test'` when unset, until `close()` restores it.
8
+ */
9
+ env?: string;
10
+ /** The port to listen on. `0`, the default, takes a free one. */
11
+ port?: number;
12
+ };
13
+ /** An application {@link startApp} booted. */
14
+ export type StartedApp = {
15
+ /** The application, for {@link auditVisibility} and the models. */
16
+ app: Application;
17
+ /** Where it listens, such as `'http://localhost:53017'`. */
18
+ origin: string;
19
+ /**
20
+ * Stops the server, closes the database connections, and restores
21
+ * `NODE_ENV` to what it was before `startApp()`.
22
+ */
23
+ close: () => Promise<void>;
24
+ };
25
+ /**
26
+ * Boot the app at `path` in the test's own process, from its compiled
27
+ * bundle (`dist/bundle.js`), and listen on a free port.
28
+ *
29
+ * ```javascript
30
+ * import { startApp } from 'lumen-framework/testing';
31
+ *
32
+ * let app, origin, close;
33
+ *
34
+ * beforeAll(async () => {
35
+ * ({ app, origin, close } = await startApp(process.cwd()));
36
+ * });
37
+ *
38
+ * afterAll(() => close());
39
+ * ```
40
+ *
41
+ * The bundle must be compiled for the environment first, as `lumen build`
42
+ * and the `lumen db:*` commands do. Its model classes are set up once per
43
+ * process, so start an app once and share it between test files; starting
44
+ * the same one again throws. `NODE_ENV` holds the app's environment until
45
+ * `close()`.
46
+ *
47
+ * @param path - The app's root directory.
48
+ * @param options - The environment and port.
49
+ * @returns The application, where it listens, and how to stop it.
50
+ * @throws When the app at `path` was already started in this process.
51
+ */
52
+ export default function startApp(path: string, { env, port }?: StartAppOptions): Promise<StartedApp>;
@@ -0,0 +1,14 @@
1
+ /** A resource's `type` and `id`. */
2
+ export type Identifier = {
3
+ type: string;
4
+ id: string;
5
+ };
6
+ /**
7
+ * Every resource a JSON:API document names: its primary data, its `included`
8
+ * resources, and the linkage of each one's relationships. A relationship
9
+ * endpoint's primary data is linkage itself, so it is covered the same way.
10
+ * Ids are strings, as JSON:API sends them.
11
+ *
12
+ * @internal
13
+ */
14
+ export default function identifiersIn(document: unknown): Array<Identifier>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Helpers for an app's tests, imported from `lumen-framework/testing`. They
3
+ * are kept out of the main entry, so they never reach an app's runtime
4
+ * bundle.
5
+ *
6
+ * @module lumen-framework/testing
7
+ */
8
+ export { auditVisibility, startApp } from './packages/testing';
9
+ export type { AuditedDocument, AuditedRoute, AuditVisibilityOptions, DocumentCheckResult, StartAppOptions, StartedApp, VisibilityAudit, VisibilityViolation, VisibleRecords } from './packages/testing';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The framework's chalk instance — equivalent to chalk's default export, which
3
+ * is itself a `Chalk` built without options (same colour-level detection).
4
+ *
5
+ * Built from the *named* `Chalk` export on purpose. chalk is ESM-only from v5
6
+ * on, and the app compiler re-bundles `dist/index.mjs` to CommonJS. Importing
7
+ * from an ES module, esbuild gives a default import Node's CommonJS semantics
8
+ * (the whole `require()` result), and `require()` of an ES module returns its
9
+ * namespace — so `import chalk from 'chalk'` would make `chalk.yellow`
10
+ * undefined inside an app. Named imports resolve correctly either way. An
11
+ * ESLint rule keeps the default import out of `src/`.
12
+ *
13
+ * @private
14
+ */
15
+ declare const chalk: import("chalk").ChalkInstance;
16
+ export default chalk;
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * The result is `Partial<T>` rather than Flow's `T`: keys may be dropped, both
5
5
  * because the caller asked for a subset and because undefined values are
6
- * filtered out. The cast is confined to the return, where the dynamic key
7
- * access makes the shape unknowable to the compiler.
6
+ * filtered out. The casts are confined to the boundaries, where the dynamic
7
+ * key access makes the shape unknowable to the compiler.
8
8
  *
9
9
  * @private
10
10
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumen-framework",
3
- "version": "3.1.1",
3
+ "version": "4.0.0",
4
4
  "description": "Build scalable, Node.js-powered REST APIs with almost no code.",
5
5
  "keywords": [
6
6
  "mvc",
@@ -15,7 +15,10 @@
15
15
  "bugs": {
16
16
  "url": "https://github.com/nickschot/lux/issues"
17
17
  },
18
- "repository": "github:nickschot/lux",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "github:nickschot/lux"
21
+ },
19
22
  "license": "MIT",
20
23
  "author": "Nick Schot <nickschot@gmail.com>",
21
24
  "contributors": [
@@ -27,6 +30,19 @@
27
30
  "main": "dist/index.js",
28
31
  "module": "dist/index.mjs",
29
32
  "types": "./dist/types/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/types/index.d.ts",
36
+ "module": "./dist/index.mjs",
37
+ "default": "./dist/index.js"
38
+ },
39
+ "./testing": {
40
+ "types": "./dist/types/testing.d.ts",
41
+ "module": "./dist/testing.mjs",
42
+ "default": "./dist/testing.js"
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
30
46
  "bin": {
31
47
  "lumen": "bin/lumen"
32
48
  },
@@ -37,46 +53,58 @@
37
53
  "LICENSE"
38
54
  ],
39
55
  "dependencies": {
40
- "ansi-regex": "^5.0.1",
41
- "chalk": "^4.1.2",
42
- "commander": "^2.20.3",
43
- "esbuild": "^0.28.1",
56
+ "chalk": "^6.0.1",
57
+ "commander": "^15.0.0",
58
+ "esbuild": "^0.28.2",
44
59
  "fb-watchman": "^2.0.2",
45
- "inflection": "^1.13.4",
60
+ "inflection": "^3.0.2",
46
61
  "knex": "^3.3.0",
47
- "ora": "^5.4.1"
62
+ "ora": "^9.4.1"
48
63
  },
49
64
  "devDependencies": {
50
- "@eslint/js": "^9.39.5",
51
- "@types/inflection": "1.13.2",
52
- "@types/node": "^20.19.43",
53
- "@vitest/coverage-v8": "^4.1.10",
54
- "eslint": "^9.39.5",
65
+ "@eslint/js": "^10.0.1",
66
+ "@faker-js/faker": "^10.6.0",
67
+ "@types/node": "^22.20.5",
68
+ "@vitest/coverage-v8": "^5.0.3",
69
+ "ajv": "^8.20.0",
70
+ "ajv-formats": "^3.0.1",
71
+ "eslint": "^10.12.0",
55
72
  "eslint-config-prettier": "^10.1.8",
56
- "faker": "4.1.0",
57
- "globals": "^17.7.0",
73
+ "globals": "^17.13.0",
58
74
  "lumen-framework": "link:.",
59
- "node-fetch": "^2.7.0",
60
- "prettier": "^3.9.5",
61
- "release-plan": "^0.18.0",
62
- "shx": "^0.3.4",
63
- "sinon": "2.2.0",
75
+ "prettier": "^3.9.9",
76
+ "release-plan": "^0.20.1",
77
+ "shx": "^0.4.0",
78
+ "sinon": "22.1.0",
79
+ "typedoc": "^0.28.20",
64
80
  "typescript": "^6.0.3",
65
- "typescript-eslint": "^8.64.0",
66
- "vitest": "^4.1.10"
81
+ "typescript-eslint": "^8.71.1",
82
+ "vitest": "^5.0.3"
67
83
  },
68
84
  "engines": {
69
- "node": ">= 20"
85
+ "node": ">= 22.14"
70
86
  },
71
- "volta": {
72
- "node": "20.20.2"
87
+ "devEngines": {
88
+ "runtime": [
89
+ {
90
+ "name": "node",
91
+ "version": "22.23.3",
92
+ "onFail": "download"
93
+ },
94
+ {
95
+ "name": "node",
96
+ "version": ">=22.14",
97
+ "onFail": "warn"
98
+ }
99
+ ]
73
100
  },
74
101
  "scripts": {
75
102
  "build": "node build.mjs",
76
103
  "build:debugger": "node test/utils/debugger/build.mjs",
77
104
  "build:types": "tsc -p tsconfig.build.json",
78
- "clean": "shx rm -rf coverage dist test/test-app/dist",
105
+ "clean": "shx rm -rf coverage dist docs/api test/test-app/dist",
79
106
  "debugger": "node --enable-source-maps test/utils/debugger/dist/debug.js",
107
+ "docs:api": "typedoc",
80
108
  "format": "prettier --write .",
81
109
  "format:check": "prettier --check .",
82
110
  "lint": "eslint .",
@@ -1,4 +0,0 @@
1
- /**
2
- * @private
3
- */
4
- export declare function test(): Promise<void>;
@@ -1,4 +0,0 @@
1
- /**
2
- * @private
3
- */
4
- export default function sql(strings: readonly string[], ...values: unknown[]): string;
@@ -1,5 +0,0 @@
1
- import type ParameterGroup from '../index';
2
- /**
3
- * @private
4
- */
5
- export default function hasRequiredParams(group: ParameterGroup, params: Record<string, unknown>): boolean;
@@ -1,6 +0,0 @@
1
- /**
2
- * A replacement for querystring.stringify that supports nested objects.
3
- *
4
- * @private
5
- */
6
- export default function createQueryString(src: Record<string, unknown>, prop?: string): string;
@@ -1 +0,0 @@
1
- export default function hasOwnProperty(target: object, key: string): boolean;