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.
- package/CLAUDE.md +1 -2
- package/JSKIT_BACKEND_MIGRATION_TRACKER.txt +180 -0
- package/README.md +22 -1
- package/SINGLE_VALIDATION_CONTRACT_TODO.txt +172 -0
- package/docs/API.md +196 -38
- package/docs/COMPARISON.md +2 -2
- package/docs/GUIDE/GUIDE_1_Initial_Setup.md +111 -5
- package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +5 -1
- package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +3 -1
- package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +12 -60
- package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +2 -2
- package/docs/GUIDE/GUIDE_3_Field_Transformations.md +5 -1
- package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +2 -0
- package/docs/GUIDE/GUIDE_X_Autofiltering.md +355 -0
- package/docs/GUIDE/GUIDE_X_Fastify.md +78 -0
- package/docs/GUIDE/GUIDE_X_Knex_Schema_And_Migrations.md +370 -0
- package/docs/GUIDE/GUIDE_X_Query_Projections.md +159 -0
- package/docs/GUIDE/GUIDE_X_Writing_Plugins.md +199 -0
- package/docs/GUIDE/index.md +18 -9
- package/docs/QUICKSTART.md +5 -1
- package/docs/index.md +1 -1
- package/index.js +3 -2
- package/lib/enhanced-logger.js +1 -1
- package/package.json +6 -2
- package/plugins/core/bulk-operations-plugin.js +26 -34
- package/plugins/core/connectors/express-plugin.js +97 -190
- package/plugins/core/connectors/fastify-plugin.js +206 -0
- package/plugins/core/connectors/lib/busboy-detector.js +4 -4
- package/plugins/core/connectors/lib/connector-core.js +195 -0
- package/plugins/core/connectors/lib/transport-http-helpers.js +122 -0
- package/plugins/core/connectors/lib/transport-route-schemas.js +92 -0
- package/plugins/core/lib/anyapi/schema-utils.js +43 -4
- package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +4 -1
- package/plugins/core/lib/dbIntrospection.js +1078 -0
- package/plugins/core/lib/dbTablesOperations.js +1111 -160
- package/plugins/core/lib/querying/knex-cross-table-search.js +0 -7
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +5 -3
- package/plugins/core/lib/querying/knex-process-includes.js +3 -4
- package/plugins/core/lib/querying/knex-query-helpers.js +21 -76
- package/plugins/core/lib/querying/knex-relationship-includes.js +468 -215
- package/plugins/core/lib/querying/query-builder-utils.js +19 -0
- package/plugins/core/lib/querying/query-field-sort-helpers.js +135 -0
- package/plugins/core/lib/querying/sort-helpers.js +33 -0
- package/plugins/core/lib/querying/storage-adapter-utils.js +51 -0
- package/plugins/core/lib/querying/url-helpers.js +8 -2
- package/plugins/core/lib/querying-writing/compile-schemas.js +20 -5
- package/plugins/core/lib/querying-writing/knex-field-helpers.js +83 -14
- package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +13 -12
- package/plugins/core/lib/querying-writing/query-field-helpers.js +88 -0
- package/plugins/core/lib/querying-writing/request-contracts.js +590 -0
- package/plugins/core/lib/querying-writing/resource-id-normalization.js +131 -0
- package/plugins/core/lib/querying-writing/schema-helpers.js +0 -2
- package/plugins/core/lib/querying-writing/simplified-helpers.js +4 -11
- package/plugins/core/lib/storage/canonical-storage-mapping.js +133 -0
- package/plugins/core/lib/storage/storage-adapter.js +82 -4
- package/plugins/core/lib/storage/storage-mapping.js +274 -0
- package/plugins/core/lib/writing/many-to-many-manipulations.js +4 -2
- package/plugins/core/rest-api-anyapi-knex-plugin.js +531 -312
- package/plugins/core/rest-api-autofilter-plugin.js +414 -0
- package/plugins/core/rest-api-knex-plugin.js +271 -226
- package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +10 -5
- package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +12 -6
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +1 -0
- package/plugins/core/rest-api-plugin-methods/apply-query-filters.js +41 -0
- package/plugins/core/rest-api-plugin-methods/common.js +148 -92
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +11 -2
- package/plugins/core/rest-api-plugin-methods/delete.js +6 -1
- package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +6 -1
- package/plugins/core/rest-api-plugin-methods/get-related.js +7 -2
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +7 -2
- package/plugins/core/rest-api-plugin-methods/get.js +29 -14
- package/plugins/core/rest-api-plugin-methods/patch-relationship.js +10 -3
- package/plugins/core/rest-api-plugin-methods/patch.js +56 -12
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +11 -2
- package/plugins/core/rest-api-plugin-methods/post.js +21 -8
- package/plugins/core/rest-api-plugin-methods/put.js +73 -21
- package/plugins/core/rest-api-plugin-methods/query.js +15 -53
- package/plugins/core/rest-api-plugin-methods/release.js +0 -2
- package/plugins/core/rest-api-plugin.js +6 -0
- package/plugins/core/rest-api-positioning-plugin.js +2 -5
- package/plugins/core/rest-api-query-projections-plugin.js +130 -0
- package/plugins/core/socketio-plugin.js +1 -4
- package/plugins/storage/local-storage.js +1 -1
- package/plugins/storage/s3-storage.js +5 -2
- package/quickTest.js +1 -0
- package/scripts/run-docs.js +80 -84
- package/test-debug.js +1 -1
- package/tests/README.md +7 -0
- package/tests/anyapi-basic.test.js +3 -0
- package/tests/autofilter.test.js +463 -0
- package/tests/custom-id-mysql-returning-fallback.test.js +128 -0
- package/tests/custom-id-simplified-post.test.js +75 -0
- package/tests/custom-idproperty-relationships.test.js +33 -0
- package/tests/db-introspection.test.js +521 -0
- package/tests/db-table-operations.test.js +786 -0
- package/tests/fastify-plugin.test.js +156 -0
- package/tests/field-getters.test.js +1 -2
- package/tests/field-setters.test.js +0 -4
- package/tests/fixtures/api-configs.js +278 -176
- package/tests/helpers/fake-fastify.js +99 -0
- package/tests/http-connectors-parity.test.js +235 -0
- package/tests/id-normalization.test.js +444 -0
- package/tests/logical-id-write-validation.test.js +151 -0
- package/tests/pagination-cursor-multifield.test.js +11 -11
- package/tests/projected-fields.test.js +319 -0
- package/tests/relationships.test.js +3 -3
- package/tests/searchschema-knex-behavior.test.js +187 -0
- package/tests/searchschema-merge.test.js +21 -69
- package/tests/storage-mapping.test.js +259 -0
- package/audit/00-charter.md +0 -103
- package/audit/01-scope-map.md +0 -84
- package/audit/02-coverage-matrix.csv +0 -174
- package/audit/03-invariants.md +0 -123
- package/audit/04-standards-rubric.md +0 -56
- package/audit/05-competitor-rubric.md +0 -77
- package/audit/06-findings.md +0 -160
- package/audit/07-risk-register.csv +0 -10
- package/audit/08-remediation-roadmap.md +0 -177
- package/audit/09-signoff-check.md +0 -23
- package/audit/10-final-synthesis.md +0 -29
- package/audit/evidence/code/all-files-json-rest-api.txt +0 -168
- package/audit/evidence/code/all-files-json-rest-schema.txt +0 -12
- package/audit/evidence/code/boundary-leak-checks.txt +0 -72
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__bulk-operations-plugin.js.txt +0 -480
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__express-plugin.js.txt +0 -532
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__lib__busboy-detector.js.txt +0 -175
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__lib__formidable-detector.js.txt +0 -138
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__connectors__lib__request-helpers.js.txt +0 -222
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__file-handling-plugin.js.txt +0 -342
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__dbTablesOperations.js.txt +0 -304
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__fractional-positioning.js.txt +0 -188
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__compile-schemas.js.txt +0 -336
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__connectors-query-parser.js.txt +0 -165
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__database-capabilities.js.txt +0 -265
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__database-value-normalizers.js.txt +0 -369
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__default-data-helpers.js.txt +0 -72
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__field-utils.js.txt +0 -139
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__knex-constants.js.txt +0 -45
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__knex-field-helpers.js.txt +0 -396
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__knex-json-api-transformers.js.txt +0 -162
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__payload-validators.js.txt +0 -1314
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__schema-helpers.js.txt +0 -488
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__scope-validations.js.txt +0 -484
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying-writing__simplified-helpers.js.txt +0 -857
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-cross-table-search.js.txt +0 -565
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-json-api-transformers-querying.js.txt +0 -485
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-pagination-helpers.js.txt +0 -560
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-process-includes.js.txt +0 -167
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-query-helpers-base.js.txt +0 -109
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-query-helpers.js.txt +0 -1064
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-relationship-includes.js.txt +0 -1983
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__knex-window-queries.js.txt +0 -328
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__querying__url-helpers.js.txt +0 -119
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__storage__storage-adapter.js.txt +0 -160
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__writing__many-to-many-manipulations.js.txt +0 -300
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__lib__writing__relationship-processor.js.txt +0 -245
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-access.js.txt +0 -459
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-cors-plugin.js.txt +0 -237
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-knex-plugin.js.txt +0 -1135
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-multihome-plugin.js.txt +0 -314
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__compile-resource-schemas.js.txt +0 -7
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__register-relationship-routes.js.txt +0 -71
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__register-scope-routes.js.txt +0 -102
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__turn-scope-init-into-vars.js.txt +0 -49
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-hooks__validate-include-configurations.js.txt +0 -39
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__add-route.js.txt +0 -23
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__check-permissions.js.txt +0 -13
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__common.js.txt +0 -639
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__delete-relationship.js.txt +0 -117
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__delete.js.txt +0 -104
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__enrich-attributes.js.txt +0 -199
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__get-related.js.txt +0 -353
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__get-relationship.js.txt +0 -61
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__get.js.txt +0 -184
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__patch-relationship.js.txt +0 -55
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__patch.js.txt +0 -191
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__post-relationship.js.txt +0 -110
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__post.js.txt +0 -168
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__put.js.txt +0 -253
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__query.js.txt +0 -207
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin-methods__release.js.txt +0 -12
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-plugin.js.txt +0 -165
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__rest-api-positioning-plugin.js.txt +0 -668
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__core__socketio-plugin.js.txt +0 -621
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__storage__local-storage.js.txt +0 -218
- package/audit/evidence/code/critical-pass1/json-rest-api__plugins__storage__s3-storage.js.txt +0 -124
- package/audit/evidence/code/critical-pass1/json-rest-schema__src__CorePlugin.js.txt +0 -269
- package/audit/evidence/code/critical-pass1/json-rest-schema__src__Schema.js.txt +0 -242
- package/audit/evidence/code/critical-pass1/json-rest-schema__src__index.js.txt +0 -77
- package/audit/evidence/code/critical-pass1-risk-keywords.txt +0 -238
- package/audit/evidence/code/critical-pass1-summary.csv +0 -67
- package/audit/evidence/code/critical-pass2-summary.csv +0 -67
- package/audit/evidence/code/early-silent-zones-no-test-token.txt +0 -57
- package/audit/evidence/code/error-model-signals.txt +0 -98
- package/audit/evidence/code/git-files-json-rest-api.txt +0 -171
- package/audit/evidence/code/git-files-json-rest-schema.txt +0 -27
- package/audit/evidence/code/hook-flow-signals.txt +0 -282
- package/audit/evidence/code/idproperty-signals.txt +0 -157
- package/audit/evidence/code/import-cycles-non-anyapi.txt +0 -3
- package/audit/evidence/code/import-hotspots-non-anyapi.txt +0 -96
- package/audit/evidence/code/imports-json-rest-api.txt +0 -354
- package/audit/evidence/code/imports-json-rest-schema.txt +0 -15
- package/audit/evidence/code/in-scope-files-json-rest-api.txt +0 -160
- package/audit/evidence/code/in-scope-files-json-rest-schema.txt +0 -13
- package/audit/evidence/code/non-anyapi-core-files.txt +0 -101
- package/audit/evidence/code/permission-signals.txt +0 -193
- package/audit/evidence/code/query-include-signals.txt +0 -687
- package/audit/evidence/code/transaction-signals.txt +0 -28
- package/audit/evidence/code/validation-signals.txt +0 -650
- package/audit/evidence/code/write-path-signals.txt +0 -61
- package/audit/evidence/docs/docs-claims-signals.txt +0 -1075
- package/audit/evidence/docs/schema-docs-claims-signals.txt +0 -179
- package/audit/evidence/external/corpus-freeze.md +0 -21
- package/audit/evidence/external/npm-competitor-metadata.txt +0 -70
- package/audit/evidence/external/npm-download-signals.txt +0 -23
- package/audit/evidence/external/npm-jsonapi-server.txt +0 -8
- package/audit/evidence/external/npm-modern-jsonapi-metadata.txt +0 -38
- package/audit/evidence/external/readme-fortune-signals.txt +0 -26
- package/audit/evidence/external/readme-fortune.md +0 -165
- package/audit/evidence/external/readme-json-api-serializer-signals.txt +0 -80
- package/audit/evidence/external/readme-json-api-serializer.md +0 -690
- package/audit/evidence/external/readme-jsonapi-serde-server-signals.txt +0 -0
- package/audit/evidence/external/readme-jsonapi-serde-server.md +0 -22
- package/audit/evidence/external/readme-jsonapi-serializer-signals.txt +0 -63
- package/audit/evidence/external/readme-jsonapi-serializer.md +0 -315
- package/audit/evidence/external/readme-jsonapi-server-signals.txt +0 -19
- package/audit/evidence/external/readme-jsonapi-server.md +0 -104
- package/audit/evidence/external/readme-nestjs-json-api-signals.txt +0 -4
- package/audit/evidence/external/readme-nestjs-json-api.md +0 -94
- package/audit/evidence/external/readme-yaser-json-api-nestjs-signals.txt +0 -47
- package/audit/evidence/external/readme-yaser-json-api-nestjs.md +0 -447
- package/audit/evidence/external/standard-jsonapi-snippets.txt +0 -84
- package/audit/evidence/external/standard-rfc-snippets.txt +0 -168
- package/audit/evidence/external/standards-sources.txt +0 -6
- package/audit/evidence/runtime/baseline-commits.txt +0 -2
- package/audit/evidence/runtime/db-adapter-assumptions.txt +0 -3
- package/audit/evidence/runtime/environment.txt +0 -4
- package/audit/evidence/runtime/invariant-runtime-mapping.md +0 -38
- package/audit/evidence/runtime/probe-patch-relationship-error.exitcode +0 -1
- package/audit/evidence/runtime/probe-patch-relationship-error.log +0 -76
- package/audit/evidence/runtime/probe-patch-relationship-error.mjs +0 -67
- package/audit/evidence/runtime/probe-patch-relationship-referenceerror.exitcode +0 -1
- package/audit/evidence/runtime/probe-patch-relationship-referenceerror.log +0 -62
- package/audit/evidence/runtime/probe-patch-relationship-referenceerror.mjs +0 -47
- package/audit/evidence/runtime/test-exitcodes.txt +0 -4
- package/audit/evidence/runtime/test-summary.md +0 -107
- package/audit/evidence/runtime/trace-anchors.txt +0 -61
- package/audit/evidence/tests/access-multitenancy-test-signals.txt +0 -125
- package/audit/evidence/tests/failing-tests-summary.txt +0 -25
- package/audit/evidence/tests/npm-test-json-rest-api.exitcode +0 -1
- package/audit/evidence/tests/npm-test-json-rest-api.log +0 -5885
- package/audit/evidence/tests/npm-test-json-rest-schema.exitcode +0 -1
- package/audit/evidence/tests/npm-test-json-rest-schema.log +0 -356
- package/audit/evidence/tests/query-include-test-signals.txt +0 -948
- package/audit/evidence/tests/relationship-test-signals.txt +0 -223
- package/audit/evidence/tests/skipped-tests.txt +0 -10
- package/audit/evidence/tests/test-suite-list-non-anyapi.txt +0 -30
- package/audit/evidence/tests/test-suite-list.txt +0 -32
- package/audit/subsystems/docs-drift.md +0 -49
- package/audit/subsystems/pass2-cross-review.md +0 -131
- package/audit/subsystems/plugins-access.md +0 -51
- package/audit/subsystems/plugins-bulk.md +0 -50
- package/audit/subsystems/plugins-cors.md +0 -48
- package/audit/subsystems/plugins-file.md +0 -53
- package/audit/subsystems/plugins-multihome.md +0 -50
- package/audit/subsystems/plugins-positioning.md +0 -54
- package/audit/subsystems/plugins-socketio.md +0 -50
- package/audit/subsystems/query-engine.md +0 -61
- package/audit/subsystems/relationships.md +0 -55
- package/audit/subsystems/rest-orchestration.md +0 -66
- package/audit/subsystems/schema-core.md +0 -64
- package/audit/subsystems/storage-knex.md +0 -57
- package/audit/subsystems/tests.md +0 -48
- package/audit/subsystems/transport-express.md +0 -55
- package/audit/traces/trace-read-get.md +0 -22
- package/audit/traces/trace-read-query.md +0 -25
- package/audit/traces/trace-relationship-endpoints.md +0 -31
- package/audit/traces/trace-write-delete.md +0 -17
- package/audit/traces/trace-write-patch.md +0 -26
- package/audit/traces/trace-write-post.md +0 -22
- package/audit/traces/trace-write-put.md +0 -23
- package/docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md +0 -707
- package/docs/GUIDE/GUIDE_X_Multihome.md +0 -666
- package/plugins/core/lib/querying-writing/payload-validators.js +0 -1314
- package/plugins/core/rest-api-access.js +0 -459
- package/plugins/core/rest-api-multihome-plugin.js +0 -314
- package/tests/multihome.test.js +0 -553
- package/tests/multihome.test.js.bak +0 -550
- package/tests/ownership-optout.test.js +0 -76
- package/tests/rest-api-access.test.js +0 -206
package/docs/GUIDE/index.md
CHANGED
|
@@ -15,16 +15,13 @@ Welcome to the comprehensive guide for JSON REST API. This guide will walk you t
|
|
|
15
15
|
3. **[Field Transformations](GUIDE_3_Field_Transformations.md)**
|
|
16
16
|
Transform data with virtual fields, getters, setters, computed fields, and visibility control.
|
|
17
17
|
|
|
18
|
-
4. **[
|
|
19
|
-
Implement security with authentication strategies and fine-grained permissions.
|
|
20
|
-
|
|
21
|
-
5. **[Non-Database Resources](GUIDE_5_Non-Db_Resources.md)**
|
|
18
|
+
4. **[Non-Database Resources](GUIDE_5_Non-Db_Resources.md)**
|
|
22
19
|
Connect your API to alternative data sources beyond traditional databases.
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
5. **[Positioning](GUIDE_6_Positioning.md)**
|
|
25
22
|
Implement drag-and-drop functionality with automatic position management.
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
6. **[Hooks, Data Management, and Plugins](GUIDE_7_Hooks_Data_Management_And_Plugins.md)**
|
|
28
25
|
Master the hook system for data validation, transformation, and business logic.
|
|
29
26
|
|
|
30
27
|
|
|
@@ -39,8 +36,20 @@ Welcome to the comprehensive guide for JSON REST API. This guide will walk you t
|
|
|
39
36
|
- **[CORS Configuration](GUIDE_X_Cors.md)**
|
|
40
37
|
Set up Cross-Origin Resource Sharing for browser-based applications.
|
|
41
38
|
|
|
42
|
-
- **[
|
|
43
|
-
|
|
39
|
+
- **[Autofiltering](GUIDE_X_Autofiltering.md)**
|
|
40
|
+
Scope datasets automatically using configured context values, without baking in auth semantics.
|
|
41
|
+
|
|
42
|
+
- **[Knex Schema and Migrations](GUIDE_X_Knex_Schema_And_Migrations.md)**
|
|
43
|
+
Create tables, inspect live table snapshots, and generate create or additive diff migrations from table-backed resource scopes.
|
|
44
|
+
|
|
45
|
+
- **[Query Projections](GUIDE_X_Query_Projections.md)**
|
|
46
|
+
Use the optional query-projections plugin to add SQL-backed, output-only derived fields that can participate in sorting and cursor pagination.
|
|
47
|
+
|
|
48
|
+
- **[Writing Plugins](GUIDE_X_Writing_Plugins.md)**
|
|
49
|
+
Build plugins against the supported extension surface, including hooks, scope methods, and query-only read fields.
|
|
50
|
+
|
|
51
|
+
- **[Fastify Integration](GUIDE_X_Fastify.md)**
|
|
52
|
+
Register REST routes on Fastify and reject malformed write payloads at the transport layer using exported resource schemas.
|
|
44
53
|
|
|
45
54
|
- **[Socket.IO Integration](GUIDE_X_SocketIO.md)**
|
|
46
55
|
Add real-time capabilities to your API with WebSocket support.
|
|
@@ -61,4 +70,4 @@ Before starting this guide, you should have:
|
|
|
61
70
|
|
|
62
71
|
---
|
|
63
72
|
|
|
64
|
-
Ready to get started? Head to [Chapter 1: Initial Setup](GUIDE_1_Initial_Setup.md) →
|
|
73
|
+
Ready to get started? Head to [Chapter 1: Initial Setup](GUIDE_1_Initial_Setup.md) →
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -103,6 +103,10 @@ await api.addResource('authors', {
|
|
|
103
103
|
await api.resources.authors.createKnexTable();
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
`searchSchema` defines the public filter names your API accepts. Those keys do not need to match database columns or even resource field names. Keep the quickstart mental model simple: `searchSchema` is the resource's public filter contract. For advanced mapping, multi-field search, and custom backend filtering, see [Manipulating and Searching Tables](GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md).
|
|
107
|
+
|
|
108
|
+
If you want to inspect the physical table shape or generate Knex migrations directly from your resource definitions, see [Knex Schema and Migrations](GUIDE/GUIDE_X_Knex_Schema_And_Migrations.md).
|
|
109
|
+
|
|
106
110
|
## Run the program
|
|
107
111
|
|
|
108
112
|
```bash
|
|
@@ -332,7 +336,7 @@ You've successfully set up a basic JSON REST API! This quickstart covered the es
|
|
|
332
336
|
|
|
333
337
|
Check out the [full guide](./GUIDE) to learn about:
|
|
334
338
|
- Advanced relationships (many-to-many, polymorphic)
|
|
335
|
-
-
|
|
339
|
+
- Permission hooks, request auth context, and autofiltering
|
|
336
340
|
- Hooks and middleware
|
|
337
341
|
- Custom validation
|
|
338
342
|
- Pagination strategies
|
package/docs/index.md
CHANGED
|
@@ -27,7 +27,7 @@ JSON REST API is a lightweight, plugin-based framework that makes building REST
|
|
|
27
27
|
|
|
28
28
|
<div class="feature-card">
|
|
29
29
|
<h3>🔌 Plugin Architecture</h3>
|
|
30
|
-
<p>Extend your API with
|
|
30
|
+
<p>Extend your API with focused plugins for transports, dataset scoping, query fields, CORS, and more.</p>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
33
|
<div class="feature-card">
|
package/index.js
CHANGED
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
// Core plugins
|
|
12
12
|
export { RestApiPlugin } from './plugins/core/rest-api-plugin.js'
|
|
13
|
+
export { AutoFilterPlugin } from './plugins/core/rest-api-autofilter-plugin.js'
|
|
14
|
+
export { QueryProjectionsPlugin } from './plugins/core/rest-api-query-projections-plugin.js'
|
|
13
15
|
export { FileHandlingPlugin } from './plugins/core/file-handling-plugin.js'
|
|
14
16
|
export { CorsPlugin } from './plugins/core/rest-api-cors-plugin.js'
|
|
15
|
-
export { AccessPlugin } from './plugins/core/rest-api-access.js'
|
|
16
17
|
export { LabelPlugin } from './plugins/core/rest-api-label-plugin.js'
|
|
17
18
|
|
|
18
19
|
// Database plugins
|
|
@@ -21,7 +22,7 @@ export { RestApiAnyapiKnexPlugin } from './plugins/core/rest-api-anyapi-knex-plu
|
|
|
21
22
|
|
|
22
23
|
// Connector plugins
|
|
23
24
|
export { ExpressPlugin } from './plugins/core/connectors/express-plugin.js'
|
|
24
|
-
|
|
25
|
+
export { FastifyPlugin } from './plugins/core/connectors/fastify-plugin.js'
|
|
25
26
|
// Future: export { KoaPlugin } from './plugins/core/connectors/koa-plugin.js';
|
|
26
27
|
|
|
27
28
|
// Storage plugins for file handling
|
package/lib/enhanced-logger.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Wraps any logger to provide comprehensive error logging
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { formatError, formatErrorSummary
|
|
6
|
+
import { formatError, formatErrorSummary } from './error-formatter.js'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates an enhanced logger that automatically formats errors
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-rest-api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node --test tests/*.test.js",
|
|
8
8
|
"test:anyapi": "JSON_REST_API_STORAGE=anyapi node --test tests/*.test.js",
|
|
9
|
+
"test:id-contracts": "node --test tests/id-normalization.test.js tests/logical-id-write-validation.test.js tests/custom-id-simplified-post.test.js",
|
|
10
|
+
"test:id-contracts:anyapi": "JSON_REST_API_STORAGE=anyapi node --test tests/id-normalization.test.js",
|
|
9
11
|
"docs": "node scripts/run-docs.js",
|
|
12
|
+
"docs:dev": "node scripts/run-docs.js --serve",
|
|
13
|
+
"verify": "npm run test:id-contracts && npm run test:id-contracts:anyapi && npm run docs",
|
|
10
14
|
"sloc": "sloc --exclude \"(_site|node_modules|\\.git|vendor|docs)\" .",
|
|
11
15
|
"slod": "cd docs;echo 'DOC LINES:'; cat `find . -iname \\*md | grep -v _site | grep -v vendor` | wc",
|
|
12
16
|
"lint": "eslint .",
|
|
@@ -25,7 +29,7 @@
|
|
|
25
29
|
"description": "REST API plugin for hooked-api with JSON:API compliance",
|
|
26
30
|
"dependencies": {
|
|
27
31
|
"hooked-api": "^1.0.24",
|
|
28
|
-
"json-rest-schema": "^1.0.
|
|
32
|
+
"json-rest-schema": "^1.0.14",
|
|
29
33
|
"semver": "^7.7.2"
|
|
30
34
|
},
|
|
31
35
|
"peerDependencies": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RestApiValidationError
|
|
1
|
+
import { RestApiValidationError } from '../../lib/rest-api-errors.js'
|
|
2
2
|
|
|
3
3
|
export const BulkOperationsPlugin = {
|
|
4
4
|
name: 'bulk-operations',
|
|
@@ -353,41 +353,33 @@ export const BulkOperationsPlugin = {
|
|
|
353
353
|
// Create route handlers
|
|
354
354
|
const createBulkRouteHandler = (method) => {
|
|
355
355
|
return async ({ context, body, query }) => {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
atomic
|
|
380
|
-
}
|
|
356
|
+
// Parse query params for atomic mode override
|
|
357
|
+
const atomic = query?.atomic !== undefined
|
|
358
|
+
? query.atomic === 'true'
|
|
359
|
+
: defaultAtomic
|
|
360
|
+
|
|
361
|
+
let params
|
|
362
|
+
if (method === 'bulkPost') {
|
|
363
|
+
// For bulk create, expect array in data field (JSON:API style)
|
|
364
|
+
params = {
|
|
365
|
+
inputRecords: body?.data || body,
|
|
366
|
+
atomic
|
|
367
|
+
}
|
|
368
|
+
} else if (method === 'bulkPatch') {
|
|
369
|
+
// For bulk update, expect operations array
|
|
370
|
+
params = {
|
|
371
|
+
operations: body?.operations || body,
|
|
372
|
+
atomic
|
|
373
|
+
}
|
|
374
|
+
} else if (method === 'bulkDelete') {
|
|
375
|
+
// For bulk delete, expect IDs array
|
|
376
|
+
params = {
|
|
377
|
+
ids: body?.data || body?.ids || body,
|
|
378
|
+
atomic
|
|
381
379
|
}
|
|
382
|
-
|
|
383
|
-
// Call the scope method
|
|
384
|
-
const result = await api.scopes[scopeName][method](params)
|
|
385
|
-
|
|
386
|
-
return result
|
|
387
|
-
} catch (error) {
|
|
388
|
-
// Let transport plugin handle error mapping
|
|
389
|
-
throw error
|
|
390
380
|
}
|
|
381
|
+
|
|
382
|
+
return await api.scopes[scopeName][method](params)
|
|
391
383
|
}
|
|
392
384
|
}
|
|
393
385
|
|
|
@@ -15,9 +15,22 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { requirePackage } from 'hooked-api'
|
|
18
|
-
import { parseJsonApiQuery } from '../lib/querying-writing/connectors-query-parser.js'
|
|
19
18
|
import { createContext } from './lib/request-helpers.js'
|
|
20
19
|
import { createEnhancedLogger } from '../../../lib/enhanced-logger.js'
|
|
20
|
+
import {
|
|
21
|
+
isWriteMethod,
|
|
22
|
+
isAllowedWriteContentType,
|
|
23
|
+
getUnsupportedMediaTypeErrorBody
|
|
24
|
+
} from './lib/transport-http-helpers.js'
|
|
25
|
+
import {
|
|
26
|
+
extractQueryString,
|
|
27
|
+
buildTransportRequestData,
|
|
28
|
+
createConnectorContext,
|
|
29
|
+
runTransportRequestLifecycle,
|
|
30
|
+
buildTransportRejectionBody,
|
|
31
|
+
executeConnectorRoute,
|
|
32
|
+
handleConnectorError
|
|
33
|
+
} from './lib/connector-core.js'
|
|
21
34
|
|
|
22
35
|
export const ExpressPlugin = {
|
|
23
36
|
name: 'express',
|
|
@@ -115,58 +128,39 @@ export const ExpressPlugin = {
|
|
|
115
128
|
|
|
116
129
|
// Add transport hook middleware
|
|
117
130
|
router.use(async (req, res, next) => {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
response: {
|
|
141
|
-
headers: {},
|
|
142
|
-
status: null
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Add transport data to context
|
|
147
|
-
context.transport = transportData
|
|
148
|
-
|
|
149
|
-
// Run transport hooks - don't check return value for consistency with other hooks
|
|
150
|
-
// Hooks communicate via context flags (rejection, handled) not return values
|
|
151
|
-
await runHooks('transport:request', context)
|
|
131
|
+
const requestData = buildTransportRequestData({
|
|
132
|
+
method: req.method,
|
|
133
|
+
url: req.url,
|
|
134
|
+
path: req.path,
|
|
135
|
+
headers: req.headers,
|
|
136
|
+
body: req.body,
|
|
137
|
+
params: req.params,
|
|
138
|
+
query: req.query
|
|
139
|
+
})
|
|
140
|
+
const { context, transportData } = createConnectorContext({
|
|
141
|
+
request: req,
|
|
142
|
+
reply: res,
|
|
143
|
+
source: 'express',
|
|
144
|
+
mountPath: basePath,
|
|
145
|
+
requestData,
|
|
146
|
+
createContext,
|
|
147
|
+
urlPrefixOverride: req.urlPrefixOverride
|
|
148
|
+
})
|
|
149
|
+
const { rejected, handled } = await runTransportRequestLifecycle({
|
|
150
|
+
context,
|
|
151
|
+
runHooks
|
|
152
|
+
})
|
|
152
153
|
|
|
153
|
-
|
|
154
|
-
if (context.rejection) {
|
|
155
|
-
// Apply response headers from hooks
|
|
154
|
+
if (rejected) {
|
|
156
155
|
if (transportData.response.headers) {
|
|
157
156
|
res.set(transportData.response.headers)
|
|
158
157
|
}
|
|
159
|
-
return res.status(context.rejection.status || 500).json(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
title: context.rejection.title || 'Request Rejected',
|
|
163
|
-
detail: context.rejection.message
|
|
164
|
-
}]
|
|
165
|
-
})
|
|
158
|
+
return res.status(context.rejection.status || 500).json(
|
|
159
|
+
buildTransportRejectionBody(context)
|
|
160
|
+
)
|
|
166
161
|
}
|
|
167
162
|
|
|
168
|
-
|
|
169
|
-
if (context.handled) {
|
|
163
|
+
if (handled) {
|
|
170
164
|
return
|
|
171
165
|
}
|
|
172
166
|
|
|
@@ -179,18 +173,13 @@ export const ExpressPlugin = {
|
|
|
179
173
|
// Content type validation middleware
|
|
180
174
|
if (strictContentType) {
|
|
181
175
|
router.use((req, res, next) => {
|
|
182
|
-
if (
|
|
176
|
+
if (isWriteMethod(req.method)) {
|
|
183
177
|
const contentType = req.get('Content-Type')
|
|
184
178
|
|
|
185
|
-
if (contentType
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
status: '415',
|
|
190
|
-
title: 'Unsupported Media Type',
|
|
191
|
-
detail: 'Content-Type must be application/vnd.api+json or application/json'
|
|
192
|
-
}]
|
|
193
|
-
})
|
|
179
|
+
if (!isAllowedWriteContentType(contentType, { allowMultipart: true })) {
|
|
180
|
+
return res.status(415).json(
|
|
181
|
+
getUnsupportedMediaTypeErrorBody({ allowMultipart: true })
|
|
182
|
+
)
|
|
194
183
|
}
|
|
195
184
|
}
|
|
196
185
|
next()
|
|
@@ -207,77 +196,16 @@ export const ExpressPlugin = {
|
|
|
207
196
|
url: req.url
|
|
208
197
|
})
|
|
209
198
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}]
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Map error codes to HTTP status
|
|
220
|
-
if (error.code === 'REST_API_VALIDATION') {
|
|
221
|
-
status = 422
|
|
222
|
-
errorResponse.errors = [{
|
|
223
|
-
status: '422',
|
|
224
|
-
title: 'Validation Error',
|
|
225
|
-
detail: error.message,
|
|
226
|
-
source: error.details
|
|
227
|
-
}]
|
|
228
|
-
if (error.details?.violations) {
|
|
229
|
-
errorResponse.errors = error.details.violations.map(v => ({
|
|
230
|
-
status: '422',
|
|
231
|
-
title: 'Validation Error',
|
|
232
|
-
detail: v.message,
|
|
233
|
-
source: { pointer: v.field }
|
|
234
|
-
}))
|
|
235
|
-
}
|
|
236
|
-
} else if (error.code === 'REST_API_RESOURCE') {
|
|
237
|
-
switch (error.subtype) {
|
|
238
|
-
case 'not_found':
|
|
239
|
-
status = 404
|
|
240
|
-
errorResponse.errors[0].status = '404'
|
|
241
|
-
errorResponse.errors[0].title = 'Not Found'
|
|
242
|
-
break
|
|
243
|
-
case 'conflict':
|
|
244
|
-
status = 409
|
|
245
|
-
errorResponse.errors[0].status = '409'
|
|
246
|
-
errorResponse.errors[0].title = 'Conflict'
|
|
247
|
-
break
|
|
248
|
-
case 'forbidden':
|
|
249
|
-
status = 403
|
|
250
|
-
errorResponse.errors[0].status = '403'
|
|
251
|
-
errorResponse.errors[0].title = 'Forbidden'
|
|
252
|
-
break
|
|
253
|
-
default:
|
|
254
|
-
status = 400
|
|
255
|
-
errorResponse.errors[0].status = '400'
|
|
256
|
-
errorResponse.errors[0].title = 'Bad Request'
|
|
257
|
-
}
|
|
258
|
-
} else if (error.code === 'REST_API_PAYLOAD') {
|
|
259
|
-
status = 400
|
|
260
|
-
errorResponse.errors = [{
|
|
261
|
-
status: '400',
|
|
262
|
-
title: 'Bad Request',
|
|
263
|
-
detail: error.message,
|
|
264
|
-
source: { pointer: error.path }
|
|
265
|
-
}]
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Run transport:response hook for errors
|
|
269
|
-
if (req.transportData && req.context) {
|
|
270
|
-
req.transportData.response.status = status
|
|
271
|
-
req.transportData.response.body = errorResponse
|
|
272
|
-
req.context.transport = req.transportData
|
|
273
|
-
await runHooks('transport:response', req.context)
|
|
199
|
+
const { status, body: errorResponse, headers } = await handleConnectorError({
|
|
200
|
+
error,
|
|
201
|
+
context: req.context,
|
|
202
|
+
transportData: req.transportData,
|
|
203
|
+
runHooks
|
|
204
|
+
})
|
|
274
205
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
res.set(req.transportData.response.headers)
|
|
278
|
-
}
|
|
206
|
+
if (headers) {
|
|
207
|
+
res.set(headers)
|
|
279
208
|
}
|
|
280
|
-
|
|
281
209
|
res.status(status).json(errorResponse)
|
|
282
210
|
}
|
|
283
211
|
|
|
@@ -285,7 +213,7 @@ export const ExpressPlugin = {
|
|
|
285
213
|
* Listen to addRoute hook to create Express routes
|
|
286
214
|
*/
|
|
287
215
|
addHook('addRoute', 'expressRouteCreator', {}, async ({ context }) => {
|
|
288
|
-
const { method, path, handler } = context
|
|
216
|
+
const { method, path, handler, routeMeta } = context
|
|
289
217
|
|
|
290
218
|
// Apply any global before middleware
|
|
291
219
|
const beforeMiddleware = expressOptions.middleware?.beforeAll || []
|
|
@@ -294,78 +222,62 @@ export const ExpressPlugin = {
|
|
|
294
222
|
// Extract the handler logic into a shared function to keep it DRY (Don't Repeat Yourself).
|
|
295
223
|
const expressHandler = async (req, res) => {
|
|
296
224
|
try {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
225
|
+
let context = req.context
|
|
226
|
+
let transportData = req.transportData
|
|
227
|
+
|
|
228
|
+
if (!context || !transportData) {
|
|
229
|
+
const requestData = buildTransportRequestData({
|
|
230
|
+
method: req.method,
|
|
231
|
+
url: req.url,
|
|
232
|
+
path: req.path,
|
|
233
|
+
headers: req.headers,
|
|
234
|
+
body: req.body,
|
|
235
|
+
params: req.params,
|
|
236
|
+
query: req.query
|
|
237
|
+
})
|
|
238
|
+
const setup = createConnectorContext({
|
|
239
|
+
request: req,
|
|
240
|
+
reply: res,
|
|
241
|
+
source: 'express',
|
|
242
|
+
mountPath: basePath,
|
|
243
|
+
requestData,
|
|
244
|
+
createContext,
|
|
245
|
+
urlPrefixOverride: req.urlPrefixOverride
|
|
246
|
+
})
|
|
247
|
+
context = setup.context
|
|
248
|
+
transportData = setup.transportData
|
|
249
|
+
req.context = context
|
|
250
|
+
req.transportData = transportData
|
|
251
|
+
}
|
|
300
252
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
253
|
+
const outcome = await executeConnectorRoute({
|
|
254
|
+
method: req.method,
|
|
255
|
+
handler,
|
|
256
|
+
queryString: extractQueryString(req.url),
|
|
304
257
|
headers: req.headers,
|
|
305
258
|
params: req.params,
|
|
306
259
|
body: req.body,
|
|
307
|
-
context
|
|
260
|
+
context,
|
|
261
|
+
transportData,
|
|
262
|
+
routeMeta,
|
|
263
|
+
helpers,
|
|
264
|
+
mountPath: basePath,
|
|
265
|
+
runHooks
|
|
308
266
|
})
|
|
309
|
-
|
|
310
|
-
// Prepare response status
|
|
311
|
-
let responseStatus = 200
|
|
312
|
-
if (result && typeof result.statusCode === 'number') {
|
|
313
|
-
responseStatus = result.statusCode
|
|
314
|
-
} else if (req.method === 'POST' && result) {
|
|
315
|
-
// POST with content returns 201 Created
|
|
316
|
-
responseStatus = 201
|
|
317
|
-
} else if (req.method === 'POST' && !result) {
|
|
318
|
-
// POST without content returns 204 No Content
|
|
319
|
-
responseStatus = 204
|
|
320
|
-
} else if (req.method === 'DELETE') {
|
|
321
|
-
// DELETE always returns 204 No Content
|
|
322
|
-
responseStatus = 204
|
|
323
|
-
} else if ((req.method === 'PUT' || req.method === 'PATCH') && !result) {
|
|
324
|
-
// PUT/PATCH return 204 when no content is returned
|
|
325
|
-
responseStatus = 204
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// Apply headers from the handler result
|
|
329
|
-
if (result && result.headers) {
|
|
330
|
-
res.set(result.headers)
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Update transport data for response (if transport data exists)
|
|
334
|
-
if (req.transportData) {
|
|
335
|
-
req.transportData.response.status = responseStatus
|
|
336
|
-
req.transportData.response.body = result
|
|
337
|
-
context.transport = req.transportData
|
|
338
|
-
await runHooks('transport:response', context)
|
|
339
|
-
if (req.transportData.response.headers) {
|
|
340
|
-
res.set(req.transportData.response.headers)
|
|
341
|
-
}
|
|
342
|
-
}
|
|
267
|
+
res.set(outcome.headers)
|
|
343
268
|
|
|
344
269
|
// Set content type
|
|
345
270
|
res.set('Content-Type', 'application/vnd.api+json')
|
|
346
271
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
// Extract scopeName from the path (e.g., /api/countries -> countries)
|
|
350
|
-
const pathParts = path.split('/')
|
|
351
|
-
const scopeName = pathParts[pathParts.length - 1]
|
|
352
|
-
|
|
353
|
-
// Set Location header for any successful POST (201 or 204)
|
|
354
|
-
if (helpers.getLocation) {
|
|
355
|
-
const location = helpers.getLocation({ scopeName, id: context.id })
|
|
356
|
-
const baseUrl = context.urlPrefix || basePath
|
|
357
|
-
res.set('Location', `${baseUrl}${location}`)
|
|
358
|
-
}
|
|
272
|
+
if (outcome.location) {
|
|
273
|
+
res.set('Location', outcome.location)
|
|
359
274
|
}
|
|
360
275
|
|
|
361
276
|
// Handle response based on status
|
|
362
|
-
if (
|
|
277
|
+
if (outcome.status === 204) {
|
|
363
278
|
res.sendStatus(204)
|
|
364
279
|
} else {
|
|
365
|
-
|
|
366
|
-
// This happens when handler returns { statusCode, body, headers }
|
|
367
|
-
const responseBody = result && result.body !== undefined ? result.body : result
|
|
368
|
-
res.status(responseStatus).json(responseBody)
|
|
280
|
+
res.status(outcome.status).json(outcome.body)
|
|
369
281
|
}
|
|
370
282
|
} catch (error) {
|
|
371
283
|
handleError(error, req, res)
|
|
@@ -424,11 +336,6 @@ export const ExpressPlugin = {
|
|
|
424
336
|
router[method.toLowerCase()](path, ...beforeMiddleware, expressHandler)
|
|
425
337
|
|
|
426
338
|
// Debug logging for route registration
|
|
427
|
-
|
|
428
|
-
// Check if the route was actually added
|
|
429
|
-
if (router.stack) {
|
|
430
|
-
const lastRoute = router.stack[router.stack.length - 1]
|
|
431
|
-
}
|
|
432
339
|
}
|
|
433
340
|
} catch (routeError) {
|
|
434
341
|
log.error('[EXPRESS DEBUG] Error creating route:', {
|