json-rest-api 1.0.22 → 1.0.24

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 (290) hide show
  1. package/CLAUDE.md +1 -2
  2. package/JSKIT_BACKEND_MIGRATION_TRACKER.txt +180 -0
  3. package/README.md +22 -1
  4. package/SINGLE_VALIDATION_CONTRACT_TODO.txt +172 -0
  5. package/docs/API.md +196 -38
  6. package/docs/COMPARISON.md +2 -2
  7. package/docs/GUIDE/GUIDE_1_Initial_Setup.md +111 -5
  8. package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +5 -1
  9. package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +3 -1
  10. package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +12 -60
  11. package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +2 -2
  12. package/docs/GUIDE/GUIDE_3_Field_Transformations.md +5 -1
  13. package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +2 -0
  14. package/docs/GUIDE/GUIDE_X_Autofiltering.md +355 -0
  15. package/docs/GUIDE/GUIDE_X_Fastify.md +78 -0
  16. package/docs/GUIDE/GUIDE_X_Knex_Schema_And_Migrations.md +370 -0
  17. package/docs/GUIDE/GUIDE_X_Query_Projections.md +159 -0
  18. package/docs/GUIDE/GUIDE_X_Writing_Plugins.md +199 -0
  19. package/docs/GUIDE/index.md +18 -9
  20. package/docs/QUICKSTART.md +5 -1
  21. package/docs/index.md +1 -1
  22. package/index.js +3 -2
  23. package/lib/enhanced-logger.js +1 -1
  24. package/package.json +6 -2
  25. package/plugins/core/bulk-operations-plugin.js +26 -34
  26. package/plugins/core/connectors/express-plugin.js +97 -190
  27. package/plugins/core/connectors/fastify-plugin.js +206 -0
  28. package/plugins/core/connectors/lib/busboy-detector.js +4 -4
  29. package/plugins/core/connectors/lib/connector-core.js +195 -0
  30. package/plugins/core/connectors/lib/transport-http-helpers.js +122 -0
  31. package/plugins/core/connectors/lib/transport-route-schemas.js +92 -0
  32. package/plugins/core/lib/anyapi/schema-utils.js +43 -4
  33. package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +4 -1
  34. package/plugins/core/lib/dbIntrospection.js +1078 -0
  35. package/plugins/core/lib/dbTablesOperations.js +1111 -160
  36. package/plugins/core/lib/querying/knex-cross-table-search.js +0 -7
  37. package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +5 -3
  38. package/plugins/core/lib/querying/knex-process-includes.js +3 -4
  39. package/plugins/core/lib/querying/knex-query-helpers.js +21 -76
  40. package/plugins/core/lib/querying/knex-relationship-includes.js +468 -215
  41. package/plugins/core/lib/querying/query-builder-utils.js +19 -0
  42. package/plugins/core/lib/querying/query-field-sort-helpers.js +135 -0
  43. package/plugins/core/lib/querying/sort-helpers.js +33 -0
  44. package/plugins/core/lib/querying/storage-adapter-utils.js +51 -0
  45. package/plugins/core/lib/querying/url-helpers.js +8 -2
  46. package/plugins/core/lib/querying-writing/compile-schemas.js +20 -5
  47. package/plugins/core/lib/querying-writing/knex-field-helpers.js +83 -14
  48. package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +13 -12
  49. package/plugins/core/lib/querying-writing/query-field-helpers.js +88 -0
  50. package/plugins/core/lib/querying-writing/request-contracts.js +590 -0
  51. package/plugins/core/lib/querying-writing/resource-id-normalization.js +131 -0
  52. package/plugins/core/lib/querying-writing/schema-helpers.js +0 -2
  53. package/plugins/core/lib/querying-writing/simplified-helpers.js +4 -11
  54. package/plugins/core/lib/storage/canonical-storage-mapping.js +133 -0
  55. package/plugins/core/lib/storage/storage-adapter.js +82 -4
  56. package/plugins/core/lib/storage/storage-mapping.js +274 -0
  57. package/plugins/core/lib/writing/many-to-many-manipulations.js +4 -2
  58. package/plugins/core/rest-api-anyapi-knex-plugin.js +531 -312
  59. package/plugins/core/rest-api-autofilter-plugin.js +414 -0
  60. package/plugins/core/rest-api-knex-plugin.js +271 -226
  61. package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +10 -5
  62. package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +12 -6
  63. package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +1 -0
  64. package/plugins/core/rest-api-plugin-methods/apply-query-filters.js +41 -0
  65. package/plugins/core/rest-api-plugin-methods/common.js +148 -92
  66. package/plugins/core/rest-api-plugin-methods/delete-relationship.js +11 -2
  67. package/plugins/core/rest-api-plugin-methods/delete.js +6 -1
  68. package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +6 -1
  69. package/plugins/core/rest-api-plugin-methods/get-related.js +7 -2
  70. package/plugins/core/rest-api-plugin-methods/get-relationship.js +7 -2
  71. package/plugins/core/rest-api-plugin-methods/get.js +29 -14
  72. package/plugins/core/rest-api-plugin-methods/patch-relationship.js +10 -3
  73. package/plugins/core/rest-api-plugin-methods/patch.js +56 -12
  74. package/plugins/core/rest-api-plugin-methods/post-relationship.js +11 -2
  75. package/plugins/core/rest-api-plugin-methods/post.js +21 -8
  76. package/plugins/core/rest-api-plugin-methods/put.js +73 -21
  77. package/plugins/core/rest-api-plugin-methods/query.js +15 -53
  78. package/plugins/core/rest-api-plugin-methods/release.js +0 -2
  79. package/plugins/core/rest-api-plugin.js +6 -0
  80. package/plugins/core/rest-api-positioning-plugin.js +2 -5
  81. package/plugins/core/rest-api-query-projections-plugin.js +130 -0
  82. package/plugins/core/socketio-plugin.js +1 -4
  83. package/plugins/storage/local-storage.js +1 -1
  84. package/plugins/storage/s3-storage.js +5 -2
  85. package/quickTest.js +1 -0
  86. package/scripts/run-docs.js +80 -84
  87. package/test-debug.js +1 -1
  88. package/tests/README.md +7 -0
  89. package/tests/anyapi-basic.test.js +3 -0
  90. package/tests/autofilter.test.js +463 -0
  91. package/tests/custom-id-mysql-returning-fallback.test.js +128 -0
  92. package/tests/custom-id-simplified-post.test.js +75 -0
  93. package/tests/custom-idproperty-relationships.test.js +33 -0
  94. package/tests/db-introspection.test.js +521 -0
  95. package/tests/db-table-operations.test.js +786 -0
  96. package/tests/fastify-plugin.test.js +156 -0
  97. package/tests/field-getters.test.js +1 -2
  98. package/tests/field-setters.test.js +0 -4
  99. package/tests/fixtures/api-configs.js +278 -176
  100. package/tests/helpers/fake-fastify.js +99 -0
  101. package/tests/http-connectors-parity.test.js +235 -0
  102. package/tests/id-normalization.test.js +444 -0
  103. package/tests/logical-id-write-validation.test.js +151 -0
  104. package/tests/pagination-cursor-multifield.test.js +11 -11
  105. package/tests/projected-fields.test.js +319 -0
  106. package/tests/relationships.test.js +3 -3
  107. package/tests/searchschema-knex-behavior.test.js +187 -0
  108. package/tests/searchschema-merge.test.js +21 -69
  109. package/tests/storage-mapping.test.js +259 -0
  110. package/audit/00-charter.md +0 -103
  111. package/audit/01-scope-map.md +0 -84
  112. package/audit/02-coverage-matrix.csv +0 -174
  113. package/audit/03-invariants.md +0 -123
  114. package/audit/04-standards-rubric.md +0 -56
  115. package/audit/05-competitor-rubric.md +0 -77
  116. package/audit/06-findings.md +0 -160
  117. package/audit/07-risk-register.csv +0 -10
  118. package/audit/08-remediation-roadmap.md +0 -177
  119. package/audit/09-signoff-check.md +0 -23
  120. package/audit/10-final-synthesis.md +0 -29
  121. package/audit/evidence/code/all-files-json-rest-api.txt +0 -168
  122. package/audit/evidence/code/all-files-json-rest-schema.txt +0 -12
  123. package/audit/evidence/code/boundary-leak-checks.txt +0 -72
  124. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__bulk-operations-plugin.js.txt +0 -480
  125. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__express-plugin.js.txt +0 -532
  126. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__lib__busboy-detector.js.txt +0 -175
  127. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__lib__formidable-detector.js.txt +0 -138
  128. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__lib__request-helpers.js.txt +0 -222
  129. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__file-handling-plugin.js.txt +0 -342
  130. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__dbTablesOperations.js.txt +0 -304
  131. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__fractional-positioning.js.txt +0 -188
  132. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__compile-schemas.js.txt +0 -336
  133. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__connectors-query-parser.js.txt +0 -165
  134. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__database-capabilities.js.txt +0 -265
  135. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__database-value-normalizers.js.txt +0 -369
  136. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__default-data-helpers.js.txt +0 -72
  137. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__field-utils.js.txt +0 -139
  138. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__knex-constants.js.txt +0 -45
  139. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__knex-field-helpers.js.txt +0 -396
  140. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__knex-json-api-transformers.js.txt +0 -162
  141. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__payload-validators.js.txt +0 -1314
  142. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__schema-helpers.js.txt +0 -488
  143. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__scope-validations.js.txt +0 -484
  144. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__simplified-helpers.js.txt +0 -857
  145. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-cross-table-search.js.txt +0 -565
  146. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-json-api-transformers-querying.js.txt +0 -485
  147. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-pagination-helpers.js.txt +0 -560
  148. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-process-includes.js.txt +0 -167
  149. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-query-helpers-base.js.txt +0 -109
  150. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-query-helpers.js.txt +0 -1064
  151. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-relationship-includes.js.txt +0 -1983
  152. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-window-queries.js.txt +0 -328
  153. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__url-helpers.js.txt +0 -119
  154. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__storage__storage-adapter.js.txt +0 -160
  155. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__writing__many-to-many-manipulations.js.txt +0 -300
  156. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__writing__relationship-processor.js.txt +0 -245
  157. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-access.js.txt +0 -459
  158. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-cors-plugin.js.txt +0 -237
  159. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-knex-plugin.js.txt +0 -1135
  160. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-multihome-plugin.js.txt +0 -314
  161. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__compile-resource-schemas.js.txt +0 -7
  162. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__register-relationship-routes.js.txt +0 -71
  163. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__register-scope-routes.js.txt +0 -102
  164. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__turn-scope-init-into-vars.js.txt +0 -49
  165. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__validate-include-configurations.js.txt +0 -39
  166. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__add-route.js.txt +0 -23
  167. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__check-permissions.js.txt +0 -13
  168. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__common.js.txt +0 -639
  169. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__delete-relationship.js.txt +0 -117
  170. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__delete.js.txt +0 -104
  171. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__enrich-attributes.js.txt +0 -199
  172. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__get-related.js.txt +0 -353
  173. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__get-relationship.js.txt +0 -61
  174. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__get.js.txt +0 -184
  175. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__patch-relationship.js.txt +0 -55
  176. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__patch.js.txt +0 -191
  177. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__post-relationship.js.txt +0 -110
  178. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__post.js.txt +0 -168
  179. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__put.js.txt +0 -253
  180. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__query.js.txt +0 -207
  181. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__release.js.txt +0 -12
  182. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin.js.txt +0 -165
  183. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-positioning-plugin.js.txt +0 -668
  184. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__socketio-plugin.js.txt +0 -621
  185. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__storage__local-storage.js.txt +0 -218
  186. package/audit/evidence/code/critical-pass1/json-rest-api__plugins__storage__s3-storage.js.txt +0 -124
  187. package/audit/evidence/code/critical-pass1/json-rest-schema__src__CorePlugin.js.txt +0 -269
  188. package/audit/evidence/code/critical-pass1/json-rest-schema__src__Schema.js.txt +0 -242
  189. package/audit/evidence/code/critical-pass1/json-rest-schema__src__index.js.txt +0 -77
  190. package/audit/evidence/code/critical-pass1-risk-keywords.txt +0 -238
  191. package/audit/evidence/code/critical-pass1-summary.csv +0 -67
  192. package/audit/evidence/code/critical-pass2-summary.csv +0 -67
  193. package/audit/evidence/code/early-silent-zones-no-test-token.txt +0 -57
  194. package/audit/evidence/code/error-model-signals.txt +0 -98
  195. package/audit/evidence/code/git-files-json-rest-api.txt +0 -171
  196. package/audit/evidence/code/git-files-json-rest-schema.txt +0 -27
  197. package/audit/evidence/code/hook-flow-signals.txt +0 -282
  198. package/audit/evidence/code/idproperty-signals.txt +0 -157
  199. package/audit/evidence/code/import-cycles-non-anyapi.txt +0 -3
  200. package/audit/evidence/code/import-hotspots-non-anyapi.txt +0 -96
  201. package/audit/evidence/code/imports-json-rest-api.txt +0 -354
  202. package/audit/evidence/code/imports-json-rest-schema.txt +0 -15
  203. package/audit/evidence/code/in-scope-files-json-rest-api.txt +0 -160
  204. package/audit/evidence/code/in-scope-files-json-rest-schema.txt +0 -13
  205. package/audit/evidence/code/non-anyapi-core-files.txt +0 -101
  206. package/audit/evidence/code/permission-signals.txt +0 -193
  207. package/audit/evidence/code/query-include-signals.txt +0 -687
  208. package/audit/evidence/code/transaction-signals.txt +0 -28
  209. package/audit/evidence/code/validation-signals.txt +0 -650
  210. package/audit/evidence/code/write-path-signals.txt +0 -61
  211. package/audit/evidence/docs/docs-claims-signals.txt +0 -1075
  212. package/audit/evidence/docs/schema-docs-claims-signals.txt +0 -179
  213. package/audit/evidence/external/corpus-freeze.md +0 -21
  214. package/audit/evidence/external/npm-competitor-metadata.txt +0 -70
  215. package/audit/evidence/external/npm-download-signals.txt +0 -23
  216. package/audit/evidence/external/npm-jsonapi-server.txt +0 -8
  217. package/audit/evidence/external/npm-modern-jsonapi-metadata.txt +0 -38
  218. package/audit/evidence/external/readme-fortune-signals.txt +0 -26
  219. package/audit/evidence/external/readme-fortune.md +0 -165
  220. package/audit/evidence/external/readme-json-api-serializer-signals.txt +0 -80
  221. package/audit/evidence/external/readme-json-api-serializer.md +0 -690
  222. package/audit/evidence/external/readme-jsonapi-serde-server-signals.txt +0 -0
  223. package/audit/evidence/external/readme-jsonapi-serde-server.md +0 -22
  224. package/audit/evidence/external/readme-jsonapi-serializer-signals.txt +0 -63
  225. package/audit/evidence/external/readme-jsonapi-serializer.md +0 -315
  226. package/audit/evidence/external/readme-jsonapi-server-signals.txt +0 -19
  227. package/audit/evidence/external/readme-jsonapi-server.md +0 -104
  228. package/audit/evidence/external/readme-nestjs-json-api-signals.txt +0 -4
  229. package/audit/evidence/external/readme-nestjs-json-api.md +0 -94
  230. package/audit/evidence/external/readme-yaser-json-api-nestjs-signals.txt +0 -47
  231. package/audit/evidence/external/readme-yaser-json-api-nestjs.md +0 -447
  232. package/audit/evidence/external/standard-jsonapi-snippets.txt +0 -84
  233. package/audit/evidence/external/standard-rfc-snippets.txt +0 -168
  234. package/audit/evidence/external/standards-sources.txt +0 -6
  235. package/audit/evidence/runtime/baseline-commits.txt +0 -2
  236. package/audit/evidence/runtime/db-adapter-assumptions.txt +0 -3
  237. package/audit/evidence/runtime/environment.txt +0 -4
  238. package/audit/evidence/runtime/invariant-runtime-mapping.md +0 -38
  239. package/audit/evidence/runtime/probe-patch-relationship-error.exitcode +0 -1
  240. package/audit/evidence/runtime/probe-patch-relationship-error.log +0 -76
  241. package/audit/evidence/runtime/probe-patch-relationship-error.mjs +0 -67
  242. package/audit/evidence/runtime/probe-patch-relationship-referenceerror.exitcode +0 -1
  243. package/audit/evidence/runtime/probe-patch-relationship-referenceerror.log +0 -62
  244. package/audit/evidence/runtime/probe-patch-relationship-referenceerror.mjs +0 -47
  245. package/audit/evidence/runtime/test-exitcodes.txt +0 -4
  246. package/audit/evidence/runtime/test-summary.md +0 -107
  247. package/audit/evidence/runtime/trace-anchors.txt +0 -61
  248. package/audit/evidence/tests/access-multitenancy-test-signals.txt +0 -125
  249. package/audit/evidence/tests/failing-tests-summary.txt +0 -25
  250. package/audit/evidence/tests/npm-test-json-rest-api.exitcode +0 -1
  251. package/audit/evidence/tests/npm-test-json-rest-api.log +0 -5885
  252. package/audit/evidence/tests/npm-test-json-rest-schema.exitcode +0 -1
  253. package/audit/evidence/tests/npm-test-json-rest-schema.log +0 -356
  254. package/audit/evidence/tests/query-include-test-signals.txt +0 -948
  255. package/audit/evidence/tests/relationship-test-signals.txt +0 -223
  256. package/audit/evidence/tests/skipped-tests.txt +0 -10
  257. package/audit/evidence/tests/test-suite-list-non-anyapi.txt +0 -30
  258. package/audit/evidence/tests/test-suite-list.txt +0 -32
  259. package/audit/subsystems/docs-drift.md +0 -49
  260. package/audit/subsystems/pass2-cross-review.md +0 -131
  261. package/audit/subsystems/plugins-access.md +0 -51
  262. package/audit/subsystems/plugins-bulk.md +0 -50
  263. package/audit/subsystems/plugins-cors.md +0 -48
  264. package/audit/subsystems/plugins-file.md +0 -53
  265. package/audit/subsystems/plugins-multihome.md +0 -50
  266. package/audit/subsystems/plugins-positioning.md +0 -54
  267. package/audit/subsystems/plugins-socketio.md +0 -50
  268. package/audit/subsystems/query-engine.md +0 -61
  269. package/audit/subsystems/relationships.md +0 -55
  270. package/audit/subsystems/rest-orchestration.md +0 -66
  271. package/audit/subsystems/schema-core.md +0 -64
  272. package/audit/subsystems/storage-knex.md +0 -57
  273. package/audit/subsystems/tests.md +0 -48
  274. package/audit/subsystems/transport-express.md +0 -55
  275. package/audit/traces/trace-read-get.md +0 -22
  276. package/audit/traces/trace-read-query.md +0 -25
  277. package/audit/traces/trace-relationship-endpoints.md +0 -31
  278. package/audit/traces/trace-write-delete.md +0 -17
  279. package/audit/traces/trace-write-patch.md +0 -26
  280. package/audit/traces/trace-write-post.md +0 -22
  281. package/audit/traces/trace-write-put.md +0 -23
  282. package/docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md +0 -707
  283. package/docs/GUIDE/GUIDE_X_Multihome.md +0 -666
  284. package/plugins/core/lib/querying-writing/payload-validators.js +0 -1314
  285. package/plugins/core/rest-api-access.js +0 -459
  286. package/plugins/core/rest-api-multihome-plugin.js +0 -314
  287. package/tests/multihome.test.js +0 -553
  288. package/tests/multihome.test.js.bak +0 -550
  289. package/tests/ownership-optout.test.js +0 -76
  290. package/tests/rest-api-access.test.js +0 -206
@@ -1,484 +0,0 @@
1
- 1 /**
2
- 2 * Scope configuration validators for relationship definitions
3
- 3 *
4
- 4 * @description
5
- 5 * These validators run at scope registration time to ensure:
6
- 6 * - Polymorphic relationships are properly configured
7
- 7 * - HasMany relationships specify required foreign keys
8
- 8 * - ManyToMany relationships have pivot table settings
9
- 9 * - Referenced scopes actually exist in the system
10
- 10 */
11
- 11
12
- 12 /**
13
- 13 * Validates all relationships in a scope configuration
14
- 14 *
15
- 15 * @param {Object} params - Validation parameters
16
- 16 * @param {Object} params.context - Event context with scopeName and scopeOptions
17
- 17 * @param {Object} params.scopes - All registered scopes for validation
18
- 18 * @throws {Error} If any relationship is misconfigured
19
- 19 *
20
- 20 * @example
21
- 21 * // Input: Valid polymorphic relationship
22
- 22 * validateRelationships({
23
- 23 * context: {
24
- 24 * scopeName: 'comments',
25
- 25 * scopeOptions: {
26
- 26 * schema: {
27
- 27 * commentable_type: { type: 'string' },
28
- 28 * commentable_id: { type: 'integer' }
29
- 29 * },
30
- 30 * relationships: {
31
- 31 * commentable: {
32
- 32 * belongsToPolymorphic: {
33
- 33 * types: ['posts', 'videos'], // Must exist
34
- 34 * typeField: 'commentable_type',
35
- 35 * idField: 'commentable_id'
36
- 36 * }
37
- 37 * }
38
- 38 * }
39
- 39 * }
40
- 40 * },
41
- 41 * scopes: { posts: {}, videos: {} } // Referenced types exist
42
- 42 * });
43
- 43 * // Output: No error (valid configuration)
44
- 44 *
45
- 45 * @example
46
- 46 * // Input: Missing required field
47
- 47 * validateRelaationships({
48
- 48 * context: {
49
- 49 * scopeName: 'attachments',
50
- 50 * scopeOptions: {
51
- 51 * relationships: {
52
- 52 * attachable: {
53
- 53 * belongsToPolymorphic: {
54
- 54 * types: ['documents'],
55
- 55 * typeField: 'attachable_type'
56
- 56 * // Missing: idField
57
- 57 * }
58
- 58 * }
59
- 59 * }
60
- 60 * }
61
- 61 * },
62
- 62 * scopes: { documents: {} }
63
- 63 * });
64
- 64 * // Throws: Error
65
- 65 * // "Invalid polymorphic relationship 'attachable' in scope 'attachments':
66
- 66 * // belongsToPolymorphic.idField must be specified"
67
- 67 *
68
- 68 * @example
69
- 69 * // Input: HasMany without foreignKey
70
- 70 * validateRelationships({
71
- 71 * context: {
72
- 72 * scopeName: 'users',
73
- 73 * scopeOptions: {
74
- 74 * relationships: {
75
- 75 * posts: {
76
- 76 * type: 'hasMany',
77
- 77 * target: 'posts'
78
- 78 * // Missing: foreignKey
79
- 79 * }
80
- 80 * }
81
- 81 * }
82
- 82 * },
83
- 83 * scopes: { posts: {} }
84
- 84 * });
85
- 85 * // Throws: Error
86
- 86 * // "Invalid hasMany relationship 'posts' in scope 'users':
87
- 87 * // hasMany relationship requires foreignKey to be specified"
88
- 88 *
89
- 89 * @example
90
- 90 * // Input: Complex activity feed with multiple polymorphic relationships
91
- 91 * validateRelationships({
92
- 92 * context: {
93
- 93 * scopeName: 'activities',
94
- 94 * scopeOptions: {
95
- 95 * schema: {
96
- 96 * trackable_type: { type: 'string' },
97
- 97 * trackable_id: { type: 'integer' },
98
- 98 * actor_type: { type: 'string' },
99
- 99 * actor_id: { type: 'integer' }
100
- 100 * },
101
- 101 * relationships: {
102
- 102 * trackable: { // What was changed
103
- 103 * belongsToPolymorphic: {
104
- 104 * types: ['posts', 'comments', 'users'],
105
- 105 * typeField: 'trackable_type',
106
- 106 * idField: 'trackable_id'
107
- 107 * }
108
- 108 * },
109
- 109 * actor: { // Who made the change
110
- 110 * belongsToPolymorphic: {
111
- 111 * types: ['users', 'api_clients'],
112
- 112 * typeField: 'actor_type',
113
- 113 * idField: 'actor_id'
114
- 114 * }
115
- 115 * }
116
- 116 * }
117
- 117 * }
118
- 118 * },
119
- 119 * scopes: { posts: {}, comments: {}, users: {}, api_clients: {} }
120
- 120 * });
121
- 121 * // Output: No error (both polymorphic relationships valid)
122
- 122 *
123
- 123 * @description
124
- 124 * Used by:
125
- 125 * - rest-api-plugin on 'scope:added' event
126
- 126 * - Runs automatically when scopes are registered
127
- 127 *
128
- 128 * Purpose:
129
- 129 * - Catches configuration errors at startup, not runtime
130
- 130 * - Validates polymorphic relationship structure
131
- 131 * - Ensures referenced scope types exist
132
- 132 * - Validates hasMany/manyToMany foreign keys
133
- 133 * - Provides clear error messages for debugging
134
- 134 *
135
- 135 * Data flow:
136
- 136 * 1. Extracts relationships from scope options
137
- 137 * 2. For each relationship, checks its type
138
- 138 * 3. Validates polymorphic: types, typeField, idField
139
- 139 * 4. Validates hasMany: foreignKey (unless via)
140
- 140 * 5. Validates manyToMany: through, foreignKey, otherKey
141
- 141 * 6. Throws descriptive error on first validation failure
142
- 142 */
143
- 143 export function validateRelationships ({ context, scopes }) {
144
- 144 const { scopeName, scopeOptions } = context
145
- 145 const relationships = scopeOptions.relationships || {}
146
- 146
147
- 147 for (const [relName, relDef] of Object.entries(relationships)) {
148
- 148 if (relDef.belongsToPolymorphic) {
149
- 149 const validation = validatePolymorphicRelationship(relDef, scopeName, scopes)
150
- 150 if (!validation.valid) {
151
- 151 throw new Error(
152
- 152 `Invalid polymorphic relationship '${relName}' in scope '${scopeName}': ${validation.error}`
153
- 153 )
154
- 154 }
155
- 155 }
156
- 156
157
- 157 // Validate based on relationship type
158
- 158 if (relDef.type === 'hasMany') {
159
- 159 const validation = validateHasManyRelationship(relDef, relName, scopeName)
160
- 160 if (!validation.valid) {
161
- 161 throw new Error(
162
- 162 `Invalid hasMany relationship '${relName}' in scope '${scopeName}': ${validation.error}`
163
- 163 )
164
- 164 }
165
- 165 }
166
- 166
167
- 167 if (relDef.type === 'hasOne') {
168
- 168 const validation = validateHasOneRelationship(relDef, relName, scopeName)
169
- 169 if (!validation.valid) {
170
- 170 throw new Error(
171
- 171 `Invalid hasOne relationship '${relName}' in scope '${scopeName}': ${validation.error}`
172
- 172 )
173
- 173 }
174
- 174 }
175
- 175
176
- 176 if (relDef.type === 'manyToMany') {
177
- 177 const validation = validateManyToManyRelationship(relDef, relName, scopeName)
178
- 178 if (!validation.valid) {
179
- 179 throw new Error(
180
- 180 `Invalid manyToMany relationship '${relName}' in scope '${scopeName}': ${validation.error}`
181
- 181 )
182
- 182 }
183
- 183 }
184
- 184 }
185
- 185 }
186
- 186
187
- 187 /**
188
- 188 * Validates a polymorphic relationship definition
189
- 189 *
190
- 190 * @param {Object} relDef - Relationship definition with belongsToPolymorphic
191
- 191 * @param {string} scopeName - Scope being registered (for error messages)
192
- 192 * @param {Object} scopes - All registered scopes for validation
193
- 193 * @returns {Object} Validation result {valid: boolean, error?: string}
194
- 194 *
195
- 195 * @example
196
- 196 * // Input: Valid polymorphic configuration
197
- 197 * const relDef = {
198
- 198 * belongsToPolymorphic: {
199
- 199 * types: ['articles', 'videos', 'products'],
200
- 200 * typeField: 'commentable_type',
201
- 201 * idField: 'commentable_id'
202
- 202 * }
203
- 203 * };
204
- 204 * validatePolymorphicRelationship(relDef, 'comments', scopes);
205
- 205 * // Output: { valid: true }
206
- 206 *
207
- 207 * @example
208
- 208 * // Input: Missing required types array
209
- 209 * const relDef = {
210
- 210 * belongsToPolymorphic: {
211
- 211 * typeField: 'commentable_type',
212
- 212 * idField: 'commentable_id'
213
- 213 * // Missing: types
214
- 214 * }
215
- 215 * };
216
- 216 * validatePolymorphicRelationship(relDef, 'comments', scopes);
217
- 217 * // Output: {
218
- 218 * // valid: false,
219
- 219 * // error: 'belongsToPolymorphic.types must be a non-empty array'
220
- 220 * // }
221
- 221 *
222
- 222 * @example
223
- 223 * // Input: References non-existent scope
224
- 224 * const relDef = {
225
- 225 * belongsToPolymorphic: {
226
- 226 * types: ['articles', 'unicorns'], // 'unicorns' doesn't exist
227
- 227 * typeField: 'attachable_type',
228
- 228 * idField: 'attachable_id'
229
- 229 * }
230
- 230 * };
231
- 231 * validatePolymorphicRelationship(relDef, 'attachments', scopes);
232
- 232 * // Output: {
233
- 233 * // valid: false,
234
- 234 * // error: "Polymorphic type 'unicorns' is not a registered scope"
235
- 235 * // }
236
- 236 *
237
- 237 * @private
238
- 238 */
239
- 239 const validatePolymorphicRelationship = (relDef, scopeName, scopes) => {
240
- 240 // Validation logic:
241
- 241 // 1. Check relDef.belongsToPolymorphic exists
242
- 242 // 2. Validate required properties: types, typeField, idField
243
- 243 // 3. Ensure types is non-empty array
244
- 244 // 4. Verify all types are registered scopes
245
- 245 // 5. Check that typeField and idField exist in the schema
246
- 246
247
- 247 const { belongsToPolymorphic } = relDef
248
- 248
249
- 249 if (!belongsToPolymorphic) {
250
- 250 return { valid: false, error: 'Missing belongsToPolymorphic definition' }
251
- 251 }
252
- 252
253
- 253 const { types, typeField, idField } = belongsToPolymorphic
254
- 254
255
- 255 if (!types || !Array.isArray(types) || types.length === 0) {
256
- 256 return {
257
- 257 valid: false,
258
- 258 error: 'belongsToPolymorphic.types must be a non-empty array'
259
- 259 }
260
- 260 }
261
- 261
262
- 262 if (!typeField || typeof typeField !== 'string') {
263
- 263 return {
264
- 264 valid: false,
265
- 265 error: 'belongsToPolymorphic.typeField must be specified'
266
- 266 }
267
- 267 }
268
- 268
269
- 269 if (!idField || typeof idField !== 'string') {
270
- 270 return {
271
- 271 valid: false,
272
- 272 error: 'belongsToPolymorphic.idField must be specified'
273
- 273 }
274
- 274 }
275
- 275
276
- 276 // Check that all types are valid scopes
277
- 277 for (const type of types) {
278
- 278 if (!scopes[type]) {
279
- 279 return {
280
- 280 valid: false,
281
- 281 error: `Polymorphic type '${type}' is not a registered scope`
282
- 282 }
283
- 283 }
284
- 284 }
285
- 285
286
- 286 return { valid: true }
287
- 287 }
288
- 288
289
- 289 /**
290
- 290 * Validates a hasMany relationship definition
291
- 291 *
292
- 292 * @param {Object} relDef - Relationship definition with hasMany
293
- 293 * @param {string} relName - Relationship name
294
- 294 * @param {string} scopeName - Scope being registered
295
- 295 * @returns {Object} Validation result {valid: boolean, error?: string}
296
- 296 *
297
- 297 * @example
298
- 298 * // Input: Valid hasMany configuration
299
- 299 * const relDef = {
300
- 300 * type: 'hasMany',
301
- 301 * target: 'posts',
302
- 302 * foreignKey: 'author_id' // Required!
303
- 303 * };
304
- 304 * validateHasManyRelationship(relDef, 'posts', 'users');
305
- 305 * // Output: { valid: true }
306
- 306 *
307
- 307 * @example
308
- 308 * // Input: Missing required foreignKey
309
- 309 * const relDef = {
310
- 310 * type: 'hasMany',
311
- 311 * target: 'posts'
312
- 312 * // Missing: foreignKey
313
- 313 * };
314
- 314 * validateHasManyRelationship(relDef, 'posts', 'users');
315
- 315 * // Output: {
316
- 316 * // valid: false,
317
- 317 * // error: 'hasMany relationship requires foreignKey to be specified...'
318
- 318 * // }
319
- 319 *
320
- 320 * @example
321
- 321 * // Input: Polymorphic hasMany with 'via' (doesn't need foreignKey)
322
- 322 * const relDef = {
323
- 323 * type: 'hasMany',
324
- 324 * target: 'comments',
325
- 325 * via: 'commentable' // Uses polymorphic relationship
326
- 326 * };
327
- 327 * validateHasManyRelationship(relDef, 'comments', 'posts');
328
- 328 * // Output: { valid: true }
329
- 329 *
330
- 330 * @private
331
- 331 */
332
- 332 const validateHasManyRelationship = (relDef, relName, scopeName) => {
333
- 333 // Validate target is specified
334
- 334 if (!relDef.target) {
335
- 335 return {
336
- 336 valid: false,
337
- 337 error: 'hasMany relationship requires \'target\' to be specified.'
338
- 338 }
339
- 339 }
340
- 340
341
- 341 // Polymorphic hasMany relationships using 'via' don't need foreignKey
342
- 342 // They use the polymorphic fields (typeField, idField) from the belongsToPolymorphic relationship
343
- 343 if (relDef.via) {
344
- 344 return { valid: true }
345
- 345 }
346
- 346
347
- 347 if (!relDef.foreignKey) {
348
- 348 return {
349
- 349 valid: false,
350
- 350 error: 'hasMany relationship requires foreignKey to be specified. Add foreignKey: \'<field_name>\' to the relationship definition.'
351
- 351 }
352
- 352 }
353
- 353
354
- 354 if (typeof relDef.foreignKey !== 'string') {
355
- 355 return {
356
- 356 valid: false,
357
- 357 error: `hasMany relationship foreignKey must be a string, got ${typeof relDef.foreignKey}`
358
- 358 }
359
- 359 }
360
- 360
361
- 361 return { valid: true }
362
- 362 }
363
- 363
364
- 364 /**
365
- 365 * Validates a hasOne relationship definition
366
- 366 *
367
- 367 * @param {Object} relDef - Relationship definition with hasOne
368
- 368 * @param {string} relName - Relationship name
369
- 369 * @param {string} scopeName - Scope being registered
370
- 370 * @returns {Object} Validation result {valid: boolean, error?: string}
371
- 371 *
372
- 372 * @example
373
- 373 * // Input: Valid hasOne configuration
374
- 374 * const relDef = {
375
- 375 * type: 'hasOne',
376
- 376 * target: 'profile',
377
- 377 * foreignKey: 'user_id' // Required!
378
- 378 * };
379
- 379 * validateHasOneRelationship(relDef, 'profile', 'users');
380
- 380 * // Output: { valid: true }
381
- 381 *
382
- 382 * @private
383
- 383 */
384
- 384 const validateHasOneRelationship = (relDef, relName, scopeName) => {
385
- 385 // Validate target is specified
386
- 386 if (!relDef.target) {
387
- 387 return {
388
- 388 valid: false,
389
- 389 error: 'hasOne relationship requires \'target\' to be specified.'
390
- 390 }
391
- 391 }
392
- 392
393
- 393 if (!relDef.foreignKey) {
394
- 394 return {
395
- 395 valid: false,
396
- 396 error: 'hasOne relationship requires foreignKey to be specified. Add foreignKey: \'<field_name>\' to the relationship definition.'
397
- 397 }
398
- 398 }
399
- 399
400
- 400 if (typeof relDef.foreignKey !== 'string') {
401
- 401 return {
402
- 402 valid: false,
403
- 403 error: `hasOne relationship foreignKey must be a string, got ${typeof relDef.foreignKey}`
404
- 404 }
405
- 405 }
406
- 406
407
- 407 return { valid: true }
408
- 408 }
409
- 409
410
- 410 /**
411
- 411 * Validates a manyToMany relationship definition
412
- 412 *
413
- 413 * @param {Object} relDef - Relationship definition with manyToMany
414
- 414 * @param {string} relName - Relationship name
415
- 415 * @param {string} scopeName - Scope being registered
416
- 416 * @returns {Object} Validation result {valid: boolean, error?: string}
417
- 417 *
418
- 418 * @example
419
- 419 * // Input: Valid manyToMany configuration
420
- 420 * const relDef = {
421
- 421 * type: 'manyToMany',
422
- 422 * through: 'article_tags', // Pivot table
423
- 423 * foreignKey: 'article_id', // This scope's FK
424
- 424 * otherKey: 'tag_id' // Other scope's FK
425
- 425 * };
426
- 426 * validateManyToManyRelationship(relDef, 'tags', 'articles');
427
- 427 * // Output: { valid: true }
428
- 428 *
429
- 429 * @example
430
- 430 * // Input: Missing required fields
431
- 431 * const relDef = {
432
- 432 * type: 'manyToMany',
433
- 433 * through: 'article_tags',
434
- 434 * foreignKey: 'article_id'
435
- 435 * // Missing: otherKey
436
- 436 * };
437
- 437 * validateManyToManyRelationship(relDef, 'tags', 'articles');
438
- 438 * // Output: {
439
- 439 * // valid: false,
440
- 440 * // error: 'manyToMany relationship requires otherKey to be specified...'
441
- 441 * // }
442
- 442 *
443
- 443 * @private
444
- 444 */
445
- 445 const validateManyToManyRelationship = (relDef, relName, scopeName) => {
446
- 446 const { through, foreignKey, otherKey } = relDef
447
- 447
448
- 448 if (!through) {
449
- 449 return {
450
- 450 valid: false,
451
- 451 error: 'manyToMany relationship requires \'through\' table to be specified'
452
- 452 }
453
- 453 }
454
- 454
455
- 455 if (!foreignKey) {
456
- 456 return {
457
- 457 valid: false,
458
- 458 error: 'manyToMany relationship requires foreignKey to be specified. Add foreignKey: \'<field_name>\' to the manyToMany configuration.'
459
- 459 }
460
- 460 }
461
- 461
462
- 462 if (!otherKey) {
463
- 463 return {
464
- 464 valid: false,
465
- 465 error: 'manyToMany relationship requires otherKey to be specified. Add otherKey: \'<field_name>\' to the manyToMany configuration.'
466
- 466 }
467
- 467 }
468
- 468
469
- 469 if (typeof foreignKey !== 'string') {
470
- 470 return {
471
- 471 valid: false,
472
- 472 error: `manyToMany relationship foreignKey must be a string, got ${typeof foreignKey}`
473
- 473 }
474
- 474 }
475
- 475
476
- 476 if (typeof otherKey !== 'string') {
477
- 477 return {
478
- 478 valid: false,
479
- 479 error: `manyToMany relationship otherKey must be a string, got ${typeof otherKey}`
480
- 480 }
481
- 481 }
482
- 482
483
- 483 return { valid: true }
484
- 484 }