json-rest-api 1.0.29 → 2.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.
- package/LICENSE +10 -670
- package/LICENSE-GPL-3.0 +674 -0
- package/LICENSE-MIT +21 -0
- package/README.md +39 -30
- package/docs/API.md +744 -1273
- package/docs/GUIDE/01-getting-started.md +338 -0
- package/docs/GUIDE/02-resources-and-relationships.md +33 -0
- package/docs/GUIDE/03-running-example.md +87 -0
- package/docs/GUIDE/04-creating-and-querying.md +181 -0
- package/docs/GUIDE/05-belongs-to.md +177 -0
- package/docs/GUIDE/06-has-many.md +184 -0
- package/docs/GUIDE/07-polymorphic-relationships.md +191 -0
- package/docs/GUIDE/08-many-to-many.md +184 -0
- package/docs/GUIDE/09-pagination-and-sorting.md +149 -0
- package/docs/GUIDE/10-put-and-patch.md +174 -0
- package/docs/GUIDE/11-relationship-endpoints.md +174 -0
- package/docs/GUIDE/12-field-transformations.md +287 -0
- package/docs/GUIDE/13-hooks-and-lifecycle.md +479 -0
- package/docs/GUIDE/14-custom-resource-methods.md +125 -0
- package/docs/GUIDE/15-query-projections.md +266 -0
- package/docs/GUIDE/{GUIDE_X_Autofiltering.md → 16-autofiltering.md} +77 -15
- package/docs/GUIDE/{GUIDE_X_Row_Policies.md → 17-row-policies.md} +137 -44
- package/docs/GUIDE/18-labels.md +86 -0
- package/docs/GUIDE/19-managed-transactions.md +179 -0
- package/docs/GUIDE/20-transaction-outcomes.md +207 -0
- package/docs/GUIDE/21-schema-and-migrations.md +634 -0
- package/docs/GUIDE/22-version-field-migrations.md +208 -0
- package/docs/GUIDE/23-fastify.md +179 -0
- package/docs/GUIDE/24-cors.md +172 -0
- package/docs/GUIDE/{GUIDE_X_URL_Management.md → 25-url-management.md} +7 -1
- package/docs/GUIDE/26-file-uploads.md +278 -0
- package/docs/GUIDE/27-bulk-operations.md +277 -0
- package/docs/GUIDE/28-socketio.md +325 -0
- package/docs/GUIDE/29-writing-plugins.md +278 -0
- package/docs/GUIDE/30-backend-capabilities.md +100 -0
- package/docs/GUIDE/31-positioning.md +181 -0
- package/docs/GUIDE/{GUIDE_Y_Appendices.md → 32-date-and-time.md} +74 -30
- package/docs/GUIDE/33-migrating-to-v2.md +3827 -0
- package/docs/GUIDE/index.md +51 -59
- package/docs/QUICKSTART.md +120 -287
- package/docs/architecture.md +75 -0
- package/docs/contributing.md +178 -0
- package/index.d.ts +36 -0
- package/index.js +1 -22
- package/lib/enhanced-logger.js +91 -85
- package/lib/error-context.js +445 -5
- package/lib/error-formatter.js +219 -59
- package/lib/knex-transaction.js +64 -0
- package/lib/logger-types.d.ts +22 -0
- package/lib/missing-package.js +4 -0
- package/lib/rest-api-errors.js +103 -8
- package/lib/runtime/json-rest-api.js +172 -0
- package/lib/transaction-types.d.ts +59 -0
- package/package.json +97 -27
- package/plugins/core/bulk-operations-plugin.js +191 -184
- package/plugins/core/connectors/express-plugin.js +148 -219
- package/plugins/core/connectors/fastify-plugin.js +125 -82
- package/plugins/core/connectors/lib/busboy-detector.js +74 -156
- package/plugins/core/connectors/lib/connector-core.js +144 -20
- package/plugins/core/connectors/lib/formidable-detector.js +63 -120
- package/plugins/core/connectors/lib/http-validators.js +77 -0
- package/plugins/core/connectors/lib/multipart-helpers.js +18 -0
- package/plugins/core/connectors/lib/request-helpers.js +10 -1
- package/plugins/core/connectors/lib/transport-http-helpers.js +89 -8
- package/plugins/core/connectors/lib/transport-route-schemas.js +7 -4
- package/plugins/core/file-handling-plugin.js +87 -177
- package/plugins/core/lib/anyapi/anyapi-registry.js +213 -164
- package/plugins/core/lib/anyapi/canonical-link-store.js +507 -0
- package/plugins/core/lib/anyapi/canonical-relationship-reader.js +598 -0
- package/plugins/core/lib/anyapi/schema-utils.js +25 -16
- package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +0 -64
- package/plugins/core/lib/dbIntrospection.js +228 -21
- package/plugins/core/lib/dbTablesOperations.js +409 -92
- package/plugins/core/lib/fractional-positioning.js +12 -48
- package/plugins/core/lib/querying/identifier-query.js +19 -0
- package/plugins/core/lib/querying/include-query-helpers.js +364 -0
- package/plugins/core/lib/querying/include-to-many.js +428 -0
- package/plugins/core/lib/querying/include-to-one.js +579 -0
- package/plugins/core/lib/querying/knex-cross-table-search.js +31 -307
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +99 -401
- package/plugins/core/lib/querying/knex-pagination-helpers.js +48 -317
- package/plugins/core/lib/querying/knex-process-includes.js +5 -110
- package/plugins/core/lib/querying/knex-query-helpers-base.js +21 -56
- package/plugins/core/lib/querying/knex-query-helpers.js +298 -448
- package/plugins/core/lib/querying/knex-relationship-includes.js +120 -2138
- package/plugins/core/lib/querying/knex-window-queries.js +62 -253
- package/plugins/core/lib/querying/query-builder-utils.js +44 -4
- package/plugins/core/lib/querying/query-constraint.d.ts +12 -0
- package/plugins/core/lib/querying/query-constraint.js +27 -0
- package/plugins/core/lib/querying/query-field-sort-helpers.js +134 -37
- package/plugins/core/lib/querying/relationship-identifiers.js +208 -0
- package/plugins/core/lib/querying/sort-helpers.js +13 -1
- package/plugins/core/lib/querying/storage-adapter-utils.js +13 -5
- package/plugins/core/lib/querying/url-helpers.js +11 -4
- package/plugins/core/lib/querying-writing/compile-schemas.js +148 -249
- package/plugins/core/lib/querying-writing/connectors-query-parser.js +33 -118
- package/plugins/core/lib/querying-writing/database-capabilities.js +149 -223
- package/plugins/core/lib/querying-writing/database-value-normalizers.js +179 -194
- package/plugins/core/lib/querying-writing/default-data-helpers.js +15 -45
- package/plugins/core/lib/querying-writing/field-selection-types.d.ts +43 -0
- package/plugins/core/lib/querying-writing/field-utils.js +113 -92
- package/plugins/core/lib/querying-writing/knex-constants.d.ts +18 -0
- package/plugins/core/lib/querying-writing/knex-constants.js +2 -26
- package/plugins/core/lib/querying-writing/knex-field-helpers.js +100 -290
- package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +31 -120
- package/plugins/core/lib/querying-writing/query-field-helpers.js +108 -32
- package/plugins/core/lib/querying-writing/query-field-types.d.ts +60 -0
- package/plugins/core/lib/querying-writing/relationship-contracts.js +33 -13
- package/plugins/core/lib/querying-writing/request-contracts.js +93 -38
- package/plugins/core/lib/querying-writing/resource-id-normalization.js +23 -5
- package/plugins/core/lib/querying-writing/response-options.js +35 -0
- package/plugins/core/lib/querying-writing/schema-helpers.js +203 -324
- package/plugins/core/lib/querying-writing/scope-validations.js +92 -290
- package/plugins/core/lib/querying-writing/simplified-helpers.js +113 -712
- package/plugins/core/lib/storage/canonical-data-helpers.js +683 -0
- package/plugins/core/lib/storage/canonical-storage-mapping.js +51 -20
- package/plugins/core/lib/storage/ordinary-data-helpers.js +710 -0
- package/plugins/core/lib/storage/storage-adapter.js +128 -62
- package/plugins/core/lib/storage/storage-mapping.js +78 -28
- package/plugins/core/lib/storage/storage-types.d.ts +502 -0
- package/plugins/core/lib/writing/many-to-many-manipulations.js +114 -284
- package/plugins/core/lib/writing/relationship-processor.js +94 -158
- package/plugins/core/lib/writing/resource-version.js +172 -0
- package/plugins/core/lib/writing/reverse-relationship-manipulations.js +110 -0
- package/plugins/core/rest-api-anyapi-knex-plugin.js +116 -2485
- package/plugins/core/rest-api-autofilter-plugin.js +17 -19
- package/plugins/core/rest-api-cors-plugin.js +52 -205
- package/plugins/core/rest-api-knex-plugin.js +45 -1077
- package/plugins/core/rest-api-label-plugin.js +25 -38
- package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +5 -5
- package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +9 -6
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +7 -26
- package/plugins/core/rest-api-plugin-hooks/validate-include-configurations.js +20 -26
- package/plugins/core/rest-api-plugin-methods/add-route.js +4 -6
- package/plugins/core/rest-api-plugin-methods/apply-query-filters.js +42 -13
- package/plugins/core/rest-api-plugin-methods/check-permissions.js +11 -5
- package/plugins/core/rest-api-plugin-methods/common.js +291 -395
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +49 -47
- package/plugins/core/rest-api-plugin-methods/delete.js +31 -25
- package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +108 -148
- package/plugins/core/rest-api-plugin-methods/get-related.js +113 -305
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +25 -18
- package/plugins/core/rest-api-plugin-methods/get.js +36 -68
- package/plugins/core/rest-api-plugin-methods/lifecycle-types.d.ts +225 -0
- package/plugins/core/rest-api-plugin-methods/patch-relationship.js +28 -25
- package/plugins/core/rest-api-plugin-methods/patch.js +46 -99
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +49 -53
- package/plugins/core/rest-api-plugin-methods/post.js +51 -51
- package/plugins/core/rest-api-plugin-methods/put.js +69 -148
- package/plugins/core/rest-api-plugin-methods/query.js +37 -81
- package/plugins/core/rest-api-plugin-methods/release.js +2 -1
- package/plugins/core/rest-api-plugin.js +32 -46
- package/plugins/core/rest-api-positioning-plugin.js +183 -628
- package/plugins/core/rest-api-query-projections-plugin.js +19 -102
- package/plugins/core/rest-api-row-policy-plugin.js +3 -3
- package/plugins/core/socketio-plugin.js +364 -344
- package/plugins/storage/local-storage.js +40 -36
- package/types/autofilter.d.ts +57 -0
- package/types/bulk-methods.d.ts +63 -0
- package/types/errors.d.ts +118 -0
- package/types/fastify-options.d.ts +19 -0
- package/types/file-detectors.d.ts +33 -0
- package/types/file-storage.d.ts +48 -0
- package/types/hook-context.d.ts +180 -0
- package/types/plugin-options.d.ts +53 -0
- package/types/relationship-methods.d.ts +74 -0
- package/types/representations.d.ts +50 -0
- package/types/resource-methods.d.ts +95 -0
- package/types/resource-schema.d.ts +157 -0
- package/types/row-policy.d.ts +31 -0
- package/types/runtime.d.ts +132 -0
- package/types/transactions.d.ts +21 -0
- package/.claude/agents/library-guide-expert.md +0 -30
- package/.claude/agents/rest-api-internals-expert.md +0 -54
- package/.claude/settings.local.json +0 -70
- package/AGENTS.md +0 -34
- package/CLAUDE.md +0 -160
- package/CRUSH.md +0 -55
- package/JSKIT_BACKEND_MIGRATION_TRACKER.txt +0 -180
- package/SINGLE_VALIDATION_CONTRACT_TODO.txt +0 -172
- package/TODO.todo +0 -13
- package/connectors_ideas/fastify.js +0 -217
- package/connectors_ideas/koa-plugin.js +0 -112
- package/docs/.bundle/config +0 -2
- package/docs/COMPARISON.md +0 -433
- package/docs/GUIDE/GUIDE_1_Initial_Setup.md +0 -1057
- package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +0 -88
- package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +0 -808
- package/docs/GUIDE/GUIDE_2_3_BelongsTo_Relationships.md +0 -491
- package/docs/GUIDE/GUIDE_2_4_HasMany_Records.md +0 -398
- package/docs/GUIDE/GUIDE_2_5_HasMany_Polymorphic.md +0 -898
- package/docs/GUIDE/GUIDE_2_6_Many_To_Many.md +0 -712
- package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +0 -1247
- package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +0 -748
- package/docs/GUIDE/GUIDE_2_9_Relationships_Urls.md +0 -517
- package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +0 -66
- package/docs/GUIDE/GUIDE_3_Field_Transformations.md +0 -1252
- package/docs/GUIDE/GUIDE_5_Non-Db_Resources.md +0 -1107
- package/docs/GUIDE/GUIDE_6_Positioning.md +0 -692
- package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +0 -1491
- package/docs/GUIDE/GUIDE_X_Bulk_Operations.md +0 -732
- package/docs/GUIDE/GUIDE_X_Cors.md +0 -1957
- package/docs/GUIDE/GUIDE_X_Fastify.md +0 -78
- package/docs/GUIDE/GUIDE_X_File_Uploads.md +0 -729
- package/docs/GUIDE/GUIDE_X_Knex_Schema_And_Migrations.md +0 -370
- package/docs/GUIDE/GUIDE_X_Query_Projections.md +0 -159
- package/docs/GUIDE/GUIDE_X_SocketIO.md +0 -1040
- package/docs/GUIDE/GUIDE_X_Writing_Plugins.md +0 -201
- package/docs/Gemfile +0 -6
- package/docs/Gemfile.lock +0 -308
- package/docs/ONBOARDING.md +0 -315
- package/docs/_config.yml +0 -36
- package/docs/_layouts/default.html +0 -123
- package/docs/apple-touch-icon.svg +0 -4
- package/docs/assets/css/style.scss +0 -392
- package/docs/favicon.svg +0 -4
- package/docs/index.md +0 -164
- package/docs/mini-guides/file-uploads-complete.md +0 -161
- package/eslint.config.js +0 -13
- package/examples/url-override-example.js +0 -137
- package/fixing_plan.md +0 -112
- package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +0 -657
- package/plugins/core/lib/querying-writing/return-record-settings.js +0 -47
- package/plugins/core/lib/writing/knex-json-api-transformers-writing.js +0 -110
- package/plugins/storage/s3-storage.js +0 -93
- package/quickTest.js +0 -136
- package/scripts/debug-anyapi-review-filter.mjs +0 -63
- package/scripts/inspect-anyapi-descriptor-country.mjs +0 -19
- package/scripts/inspect-anyapi-descriptor.mjs +0 -19
- package/scripts/run-docs.js +0 -133
- package/test-debug.js +0 -59
- package/tests/README.md +0 -202
- package/tests/TEST_TEMPLATE.test.js +0 -178
- package/tests/anyapi-basic.test.js +0 -105
- package/tests/anyapi-cursor-pagination.test.js +0 -148
- package/tests/anyapi-custom-idproperty.test.js +0 -163
- package/tests/autofilter.test.js +0 -463
- package/tests/bulk-operations.test.js +0 -657
- package/tests/computed-fields.test.js +0 -586
- package/tests/cors.test.js +0 -834
- package/tests/curl.test.js +0 -467
- package/tests/custom-id-mysql-returning-fallback.test.js +0 -128
- package/tests/custom-id-simplified-post.test.js +0 -75
- package/tests/custom-idproperty-relationships.test.js +0 -932
- package/tests/db-introspection.test.js +0 -521
- package/tests/db-table-operations.test.js +0 -798
- package/tests/fastify-plugin.test.js +0 -184
- package/tests/field-getters.test.js +0 -370
- package/tests/field-setters.test.js +0 -306
- package/tests/file-handling.test.js +0 -155
- package/tests/fixtures/api-configs.js +0 -2566
- package/tests/full-jsonapi-belongsto-linkage.test.js +0 -150
- package/tests/helpers/fake-fastify.js +0 -99
- package/tests/helpers/storage-mode.js +0 -65
- package/tests/helpers/test-utils.js +0 -203
- package/tests/http-connectors-parity.test.js +0 -395
- package/tests/id-normalization.test.js +0 -444
- package/tests/include-depth-validation.test.js +0 -331
- package/tests/includes.test.js +0 -427
- package/tests/local-storage.test.js +0 -96
- package/tests/logical-id-write-validation.test.js +0 -151
- package/tests/nested-includes.test.js +0 -617
- package/tests/pagination-boundaries.test.js +0 -154
- package/tests/pagination-contract.test.js +0 -122
- package/tests/pagination-cursor-multifield.test.js +0 -641
- package/tests/pagination-enhanced.test.js +0 -563
- package/tests/polymorphic-relationships.test.js +0 -347
- package/tests/polymorphic-simple.test.js +0 -148
- package/tests/positioning-advanced.test.js +0 -692
- package/tests/positioning-extended.test.js +0 -915
- package/tests/positioning-multifilter.test.js +0 -699
- package/tests/positioning.test.js +0 -560
- package/tests/post-commit-hooks.test.js +0 -120
- package/tests/projected-fields.test.js +0 -319
- package/tests/public-exports.test.js +0 -15
- package/tests/put-create-parity.test.js +0 -216
- package/tests/queries.test.js +0 -521
- package/tests/query-limits.test.js +0 -584
- package/tests/relationship-endpoints.test.js +0 -620
- package/tests/relationship-include-storage-adapter.test.js +0 -56
- package/tests/relationships.test.js +0 -681
- package/tests/rest-api.test.js +0 -337
- package/tests/return-record-settings.test.js +0 -184
- package/tests/row-policy.test.js +0 -489
- package/tests/s3-storage.test.js +0 -38
- package/tests/searchschema-knex-behavior.test.js +0 -187
- package/tests/searchschema-merge.test.js +0 -151
- package/tests/socketio.test.js +0 -860
- package/tests/storage-mapping.test.js +0 -362
- package/tests/temporal-boundaries.test.js +0 -208
- package/tests/test-development-guide.md +0 -370
- package/tests/virtual-fields.test.js +0 -404
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Architecture"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Architecture
|
|
6
|
+
|
|
7
|
+
The library exposes resource methods directly and uses connectors to translate
|
|
8
|
+
HTTP requests into those same calls. Storage and transaction rules are shared
|
|
9
|
+
between direct calls and transports.
|
|
10
|
+
|
|
11
|
+
## Runtime
|
|
12
|
+
|
|
13
|
+
`lib/runtime/json-rest-api.js` contains the API object and its sequential hook list.
|
|
14
|
+
It registers ordinary resource methods, installs plugins and constructs the argument
|
|
15
|
+
object passed to existing operation handlers. There are no proxy-based resource
|
|
16
|
+
objects, generic scope aliases or automatic dispatcher logs.
|
|
17
|
+
|
|
18
|
+
A resource inherits shared methods; its vars and helpers inherit API defaults.
|
|
19
|
+
Local properties override those defaults. The internal operation argument names
|
|
20
|
+
`scope`, `scopes` and `scopeName` refer to resources. The public collection is
|
|
21
|
+
`api.resources`.
|
|
22
|
+
|
|
23
|
+
## Resource operations and schemas
|
|
24
|
+
|
|
25
|
+
`plugins/core/rest-api-plugin.js` installs CRUD, relationship and transaction methods.
|
|
26
|
+
The operation handlers live in `plugins/core/rest-api-plugin-methods/`. They validate
|
|
27
|
+
requests, run permission/lifecycle hooks and call storage helpers.
|
|
28
|
+
|
|
29
|
+
Writes select plain input with `data` or JSON:API input with `document`.
|
|
30
|
+
`request-contracts.js` validates that selection; plain conversion produces the
|
|
31
|
+
normalized `context.inputRecord` used by the existing write lifecycle. `format`
|
|
32
|
+
controls output only. Both input forms run through the same resource operation,
|
|
33
|
+
including response preparation before transaction completion. Connectors submit
|
|
34
|
+
documents through this same boundary.
|
|
35
|
+
|
|
36
|
+
Hooks deliberately share mutable operation context for caches, added information
|
|
37
|
+
and phase-specific field changes. The caller observes those mutations. See the
|
|
38
|
+
[hook contract](GUIDE/13-hooks-and-lifecycle.md) for wrapper hooks, nested calls,
|
|
39
|
+
writable values and library-owned bookkeeping. Independent calls use separate
|
|
40
|
+
contexts; this is not an immutable-context API.
|
|
41
|
+
|
|
42
|
+
`plugins/core/lib/querying-writing/compile-schemas.js` compiles resource declarations.
|
|
43
|
+
Its neighboring modules own response options, field selection, ID normalization and
|
|
44
|
+
representation conversion. The JSON schema package remains a separate dependency;
|
|
45
|
+
it is unrelated to the removed hooked-api runtime.
|
|
46
|
+
|
|
47
|
+
## Storage
|
|
48
|
+
|
|
49
|
+
`rest-api-knex-plugin.js` maps resources to ordinary tables.
|
|
50
|
+
`rest-api-anyapi-knex-plugin.js` maps them to canonical records and relationship links.
|
|
51
|
+
Both use native Knex queries and the common storage interfaces under
|
|
52
|
+
`plugins/core/lib/storage/`.
|
|
53
|
+
|
|
54
|
+
Canonical links and relationship reads have separate modules under `lib/anyapi/`
|
|
55
|
+
within the core plugin. Include traversal and to-one/to-many loaders live under
|
|
56
|
+
`plugins/core/lib/querying/`. Keep query ownership and visibility checks in those
|
|
57
|
+
modules rather than duplicating them in connectors.
|
|
58
|
+
|
|
59
|
+
## Transactions and errors
|
|
60
|
+
|
|
61
|
+
`lib/error-context.js` owns managed transactions, participating operations,
|
|
62
|
+
completion hooks and write outcomes. `lib/knex-transaction.js` handles connection
|
|
63
|
+
completion. Resource methods delegate to these modules.
|
|
64
|
+
|
|
65
|
+
`lib/rest-api-errors.js` defines the local error hierarchy. The runtime preserves
|
|
66
|
+
thrown values; operation-level code attaches transaction outcomes and secondary
|
|
67
|
+
cleanup diagnostics. See the [transaction contract](GUIDE/19-managed-transactions.md)
|
|
68
|
+
and [error outcomes](GUIDE/20-transaction-outcomes.md).
|
|
69
|
+
|
|
70
|
+
## Transports and files
|
|
71
|
+
|
|
72
|
+
Express and Fastify connectors share parsing, route and response helpers under
|
|
73
|
+
`plugins/core/connectors/lib/`. Socket.IO remains an optional integration.
|
|
74
|
+
File handling owns upload lifetime; storage plugins under `plugins/storage/` own
|
|
75
|
+
file bytes. Their effects participate in the documented completion-hook lifecycle.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Contributing"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Contributing
|
|
6
|
+
|
|
7
|
+
Use **Node 24** for development and verification. The library requires Node 24 or
|
|
8
|
+
newer; `.nvmrc` pins the version used by this repository and CI. Do not add a
|
|
9
|
+
second Node-version matrix without a concrete compatibility requirement.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
nvm install
|
|
15
|
+
nvm use
|
|
16
|
+
npm ci
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
SQLite fixtures need no external database or credentials. If the native SQLite
|
|
20
|
+
driver compiles from source, install Python 3, make and a C/C++ compiler.
|
|
21
|
+
Documentation uses Ruby 3.2 and Bundler 2.6.9. Install Bundler and run `npm run docs`;
|
|
22
|
+
the script installs missing gems into `docs/vendor/bundle` before building.
|
|
23
|
+
`npm run docs:dev -- --no-open` serves the site without opening a browser.
|
|
24
|
+
|
|
25
|
+
## Repository layout
|
|
26
|
+
|
|
27
|
+
| Path | Purpose |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| `index.js`, `index.d.ts` | Public exports |
|
|
30
|
+
| `lib/` | Runtime, errors, diagnostics and transaction ownership |
|
|
31
|
+
| `plugins/` | Resource operations, storage and optional integrations |
|
|
32
|
+
| `types/` | Public TypeScript contracts |
|
|
33
|
+
| `tests/fixtures/`, `tests/helpers/` | Resource factories and test infrastructure |
|
|
34
|
+
| `tests/*.test.js` | Library regression suites |
|
|
35
|
+
| `examples/` | Maintained runnable examples and data migration utilities |
|
|
36
|
+
| `scripts/` | Documentation, package and verification tools |
|
|
37
|
+
| `docs/GUIDE/` | User guides and the application migration guide |
|
|
38
|
+
| `old/` | Inactive history; excluded from packaging and automated discovery |
|
|
39
|
+
|
|
40
|
+
[Architecture](architecture.md) explains the main execution boundaries.
|
|
41
|
+
`tests/README.md` in a source checkout contains fixture conventions and the command matrix.
|
|
42
|
+
|
|
43
|
+
## Verification
|
|
44
|
+
|
|
45
|
+
Run focused suites for changed behavior. Reserve the comprehensive gate for
|
|
46
|
+
changes that need it and release preparation:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
npm run verify
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This runs checked JavaScript/types, packed public declarations and imports,
|
|
53
|
+
query budgets, both complete SQLite storage suites, Express 4 checks, lint and
|
|
54
|
+
the documentation build. A storage-specific test may be skipped in one mode
|
|
55
|
+
and executed in the other; inspect both results before calling it untested.
|
|
56
|
+
|
|
57
|
+
`npm run test:clean-package` installs the actual tarball in a fresh temporary
|
|
58
|
+
consumer and checks optional dependencies plus ordinary/canonical CRUD.
|
|
59
|
+
The `test:*guide`, `test:quickstart`, `test:api-reference` and `test:server-examples`
|
|
60
|
+
commands execute maintained documentation examples. Run those when their code changes.
|
|
61
|
+
`npm run test:migration-guide:package` executes the migration guide's selected
|
|
62
|
+
examples against an extracted tarball and reports its hash. It reuses local test
|
|
63
|
+
dependencies; the separate clean-package check verifies fresh installation.
|
|
64
|
+
|
|
65
|
+
Tests and package tools use temporary directories and dispose of their databases,
|
|
66
|
+
servers and sockets. They do not operate on application databases. Consumer checks
|
|
67
|
+
require an explicit path and command; library verification does not establish an
|
|
68
|
+
application migration.
|
|
69
|
+
|
|
70
|
+
## Resource stress checks
|
|
71
|
+
|
|
72
|
+
For smaller repeatable measurements, `node scripts/measure-write-lifecycles.js`
|
|
73
|
+
records SQL counts and checks child-hook order for bulk and reverse-relationship
|
|
74
|
+
writes. It supports both storage modes and the database runner.
|
|
75
|
+
`node scripts/measure-diagnostics.js` reports bounded logger formatting cost;
|
|
76
|
+
its local timings are observations, not pass/fail performance thresholds.
|
|
77
|
+
|
|
78
|
+
`npm run test:stress` runs a bounded workload in both SQLite storage modes,
|
|
79
|
+
separately from the full suite. It repeats authorized, paginated `tasks` and
|
|
80
|
+
`shared_tasks` relationship reads with polymorphic `subject` includes. The
|
|
81
|
+
fixture contains equal visible, policy-hidden and foreign-workspace groups;
|
|
82
|
+
every response must contain exactly the expected visible records and includes.
|
|
83
|
+
|
|
84
|
+
Four sequential write scenarios check owned and managed commit/rollback,
|
|
85
|
+
persisted values and exact completion-hook counts. SQL is attributed to each
|
|
86
|
+
operation with `AsyncLocalStorage`; fixed per-operation query ceilings and zero
|
|
87
|
+
runtime metadata lookups are enforced. SQL attribution failures fail the run.
|
|
88
|
+
|
|
89
|
+
To save one JSON report directly:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
node scripts/stress-resources.js > /tmp/json-rest-api-stress-knex.json
|
|
93
|
+
JSON_REST_API_STORAGE=anyapi node scripts/stress-resources.js > /tmp/json-rest-api-stress-anyapi.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Store reports outside the tracked source tree. The report includes configuration,
|
|
97
|
+
environment, per-scenario query counts, latency p50/p95/p99, throughput and memory
|
|
98
|
+
samples. Timing includes correctness checks; writes include a persisted-state
|
|
99
|
+
read. There are no machine-dependent latency or memory pass thresholds.
|
|
100
|
+
|
|
101
|
+
| Environment variable | Default | Allowed values |
|
|
102
|
+
| --- | ---: | --- |
|
|
103
|
+
| `JSON_REST_API_STRESS_ROWS` | 100 | 1–1000 per visibility group |
|
|
104
|
+
| `JSON_REST_API_STRESS_READS` | 200 | 2–100000 per batch |
|
|
105
|
+
| `JSON_REST_API_STRESS_WRITES` | 32 | 4–20000 per batch, alternating four scenarios |
|
|
106
|
+
| `JSON_REST_API_STRESS_CONCURRENCY` | 4 | 1–32 overlapping read operations |
|
|
107
|
+
| `JSON_REST_API_STRESS_BATCHES` | 1 | 1–100 repetitions against the same fixture |
|
|
108
|
+
| `JSON_REST_API_STRESS_PAGE_SIZE` | 20 | 1–100 |
|
|
109
|
+
|
|
110
|
+
Totals across batches are capped at 100000 reads and 20000 writes. Defaults seed
|
|
111
|
+
300 linked tasks plus a project and a task used as a polymorphic subject.
|
|
112
|
+
Each independent operation receives fresh context. SQLite uses one in-memory
|
|
113
|
+
connection, so overlapping reads queue their SQL; this does not test concurrent
|
|
114
|
+
SQLite writers. Writes are sequential on every backend.
|
|
115
|
+
|
|
116
|
+
For a longer bounded run with explicit retained-heap sampling:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
JSON_REST_API_STRESS_BATCHES=10 node --expose-gc scripts/stress-resources.js > /tmp/json-rest-api-stress-soak.json
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Without `--expose-gc`, memory samples describe ordinary heap/RSS fluctuations.
|
|
123
|
+
With it, samples additionally record heap retained after requested garbage
|
|
124
|
+
collection. Both are observations; a bounded run cannot establish leak freedom.
|
|
125
|
+
The driver-aware fixture also supports native checks through the existing runner:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
node scripts/test-databases.js pg scripts/stress-resources.js
|
|
129
|
+
node scripts/test-databases.js mysql2 scripts/stress-resources.js
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Real databases and Redis
|
|
133
|
+
|
|
134
|
+
The database runner starts disposable servers and creates isolated test databases.
|
|
135
|
+
Supply PostgreSQL's `initdb`/`postgres` and MySQL's `mysqld`, then run:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
npm run test:databases:pg
|
|
139
|
+
npm run test:databases:mysql
|
|
140
|
+
npm run test:redis
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`JSON_REST_API_POSTGRES_BIN` selects the PostgreSQL executable directory; otherwise
|
|
144
|
+
the runner uses `pg_config --bindir`. `JSON_REST_API_MYSQL_BIN` selects the MySQL
|
|
145
|
+
executable; otherwise it uses `mysqld` on PATH. MariaDB does not replace this MySQL
|
|
146
|
+
check. `JSON_REST_API_REDIS_BIN` selects Redis; otherwise the runner uses PATH.
|
|
147
|
+
|
|
148
|
+
For an affected subset, pass test paths directly:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
node scripts/test-databases.js pg tests/conformance-managed-transactions.test.js
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The runner checks both storage modes by default. Select one explicitly when
|
|
155
|
+
rechecking a backend-specific failure:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
JSON_REST_API_RUNNER_STORAGE=anyapi npm run test:databases:pg
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
A complete backend/storage selection has a 30-minute limit; explicitly selected
|
|
162
|
+
test files retain a 15-minute limit. Both limits terminate the owned process group
|
|
163
|
+
and dispose of the database. They do not retry tests or relax assertions.
|
|
164
|
+
|
|
165
|
+
See [backend capabilities](GUIDE/30-backend-capabilities.md) for supported semantics.
|
|
166
|
+
The CI workflow documents its disposable binary setup and database matrix.
|
|
167
|
+
|
|
168
|
+
## Releases
|
|
169
|
+
|
|
170
|
+
1. Review the public API and update the [migration guide](GUIDE/33-migrating-to-v2.md).
|
|
171
|
+
2. Use a new major version for breaking changes. Keep the manifest and lock aligned.
|
|
172
|
+
3. Run the agreed verification scope and inspect failures, cancellations and skips.
|
|
173
|
+
4. Inspect the tarball contents and confirm that `old/`, tests, local configuration
|
|
174
|
+
and development dependencies are absent from the installed runtime package.
|
|
175
|
+
5. Commit the release changes. Publishing and tagging are explicit maintainer actions.
|
|
176
|
+
|
|
177
|
+
Keep secrets in ignored local configuration. Record release evidence in the release
|
|
178
|
+
or pull request; do not add another execution ledger or TODO document to the active tree.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export * from './types/errors.js'
|
|
2
|
+
export * from './types/file-storage.js'
|
|
3
|
+
export type * from './types/representations.js'
|
|
4
|
+
export type * from './types/resource-methods.js'
|
|
5
|
+
export type * from './types/relationship-methods.js'
|
|
6
|
+
export type * from './types/bulk-methods.js'
|
|
7
|
+
export type { ManagedTransaction, ManagedTransactionParam, TransactionMethods } from './types/transactions.js'
|
|
8
|
+
export type * from './types/plugin-options.js'
|
|
9
|
+
export type * from './types/file-detectors.js'
|
|
10
|
+
export type * from './types/fastify-options.js'
|
|
11
|
+
export type * from './types/row-policy.js'
|
|
12
|
+
export type * from './types/autofilter.js'
|
|
13
|
+
|
|
14
|
+
export { JsonRestApi } from './types/runtime.js'
|
|
15
|
+
export type * from './types/runtime.js'
|
|
16
|
+
export type * from './types/resource-schema.js'
|
|
17
|
+
export type * from './types/hook-context.js'
|
|
18
|
+
import type { LibraryPlugin } from './types/runtime.js'
|
|
19
|
+
|
|
20
|
+
export const RestApiPlugin: LibraryPlugin<'rest-api'>
|
|
21
|
+
export const AutoFilterPlugin: LibraryPlugin<'autofilter'>
|
|
22
|
+
export const RowPolicyPlugin: LibraryPlugin<'row-policy'>
|
|
23
|
+
export const QueryProjectionsPlugin: LibraryPlugin<'query-projections'>
|
|
24
|
+
export const FileHandlingPlugin: LibraryPlugin<'file-handling'>
|
|
25
|
+
export const CorsPlugin: LibraryPlugin<'rest-api-cors'>
|
|
26
|
+
export const LabelPlugin: LibraryPlugin<'rest-api-label'>
|
|
27
|
+
export const SocketIOPlugin: LibraryPlugin<'socketio'>
|
|
28
|
+
export const RestApiKnexPlugin: LibraryPlugin<'rest-api-knex'>
|
|
29
|
+
export const RestApiAnyapiKnexPlugin: LibraryPlugin<'rest-api-anyapi-knex'>
|
|
30
|
+
export const ExpressPlugin: LibraryPlugin<'express'>
|
|
31
|
+
export const FastifyPlugin: LibraryPlugin<'fastify'>
|
|
32
|
+
|
|
33
|
+
export function getUrlPrefix(
|
|
34
|
+
context?: { urlPrefixOverride?: string; urlPrefix?: string } | null,
|
|
35
|
+
scope?: { vars?: { transport?: { publicBaseUrl?: string; mountPath?: string } } } | null
|
|
36
|
+
): string
|
package/index.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* JSON REST API - REST API plugin for hooked-api with JSON:API compliance
|
|
3
|
-
*
|
|
4
|
-
* This package provides:
|
|
5
|
-
* - REST API plugin that adds query, get, post, put, patch, delete methods to scopes
|
|
6
|
-
* - Connector plugins for various HTTP frameworks (Express, etc.)
|
|
7
|
-
* - JSON:API compliant request/response handling
|
|
8
|
-
* - Comprehensive error handling and validation
|
|
9
|
-
*/
|
|
1
|
+
export { JsonRestApi } from './lib/runtime/json-rest-api.js'
|
|
10
2
|
|
|
11
3
|
// Core plugins
|
|
12
4
|
export { RestApiPlugin } from './plugins/core/rest-api-plugin.js'
|
|
@@ -25,23 +17,10 @@ export { RestApiAnyapiKnexPlugin } from './plugins/core/rest-api-anyapi-knex-plu
|
|
|
25
17
|
// Connector plugins
|
|
26
18
|
export { ExpressPlugin } from './plugins/core/connectors/express-plugin.js'
|
|
27
19
|
export { FastifyPlugin } from './plugins/core/connectors/fastify-plugin.js'
|
|
28
|
-
// Future: export { KoaPlugin } from './plugins/core/connectors/koa-plugin.js';
|
|
29
20
|
|
|
30
21
|
// Storage plugins for file handling
|
|
31
22
|
export { LocalStorage } from './plugins/storage/local-storage.js'
|
|
32
|
-
export { S3Storage } from './plugins/storage/s3-storage.js'
|
|
33
23
|
|
|
34
|
-
// Error classes for consumers who need them
|
|
35
|
-
export {
|
|
36
|
-
RestApiFieldsetError,
|
|
37
|
-
RestApiTemporalDataError,
|
|
38
|
-
RestApiValidationError,
|
|
39
|
-
RestApiResourceError,
|
|
40
|
-
RestApiPayloadError
|
|
41
|
-
} from './lib/rest-api-errors.js'
|
|
42
|
-
|
|
43
|
-
// Re-export everything for backward compatibility
|
|
44
24
|
export * from './lib/rest-api-errors.js'
|
|
45
25
|
|
|
46
|
-
// URL helper function for generating API URL prefix
|
|
47
26
|
export { getUrlPrefix } from './plugins/core/lib/querying/url-helpers.js'
|
package/lib/enhanced-logger.js
CHANGED
|
@@ -1,124 +1,130 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Wraps any logger to provide comprehensive error logging
|
|
4
|
-
*/
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @import { DiagnosticLogger, DiagnosticOptions, EnhancedDiagnosticLogger, DiagnosticWriter } from './logger-types.js' */
|
|
5
3
|
|
|
6
|
-
import {
|
|
4
|
+
import { isErrorObject } from './error-context.js'
|
|
5
|
+
import { formatDiagnosticValue, formatError, formatErrorSummary, readDiagnosticProperty } from './error-formatter.js'
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
|
-
*
|
|
10
|
-
* @
|
|
11
|
-
* @param {
|
|
12
|
-
* @param {
|
|
13
|
-
* @
|
|
14
|
-
|
|
8
|
+
* @template {DiagnosticLogger} Logger
|
|
9
|
+
* @overload
|
|
10
|
+
* @param {Logger & { error: DiagnosticWriter }} baseLogger
|
|
11
|
+
* @param {DiagnosticOptions} [options]
|
|
12
|
+
* @returns {EnhancedDiagnosticLogger & { error: DiagnosticWriter }}
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @template {DiagnosticLogger} Logger
|
|
16
|
+
* @overload
|
|
17
|
+
* @param {Logger} baseLogger
|
|
18
|
+
* @param {DiagnosticOptions} [options]
|
|
19
|
+
* @returns {EnhancedDiagnosticLogger}
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Bound diagnostic previews and apply compiled field visibility to supplied levels.
|
|
23
|
+
* @param {DiagnosticLogger} baseLogger
|
|
24
|
+
* @param {DiagnosticOptions} [options]
|
|
25
|
+
* @returns {EnhancedDiagnosticLogger}
|
|
15
26
|
*/
|
|
16
27
|
export function createEnhancedLogger (baseLogger, options = {}) {
|
|
17
28
|
const {
|
|
18
29
|
logFullErrors = true,
|
|
19
|
-
includeStack = true
|
|
30
|
+
includeStack = true,
|
|
31
|
+
redactFields = [],
|
|
32
|
+
schemaInfo
|
|
20
33
|
} = options
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
const hiddenFields = Object.entries(schemaInfo?.outputFields || {})
|
|
35
|
+
.filter(([, definition]) => definition.hidden === true || definition.normallyHidden === true)
|
|
36
|
+
.map(([field]) => field)
|
|
37
|
+
const diagnosticOptions = { includeStack, redactFields: [...redactFields, ...hiddenFields] }
|
|
38
|
+
const formatLoggedError = logFullErrors ? formatError : formatErrorSummary
|
|
39
|
+
|
|
40
|
+
/** @param {unknown} arg */
|
|
41
|
+
function formatArgument (arg) {
|
|
42
|
+
try {
|
|
43
|
+
if (isErrorObject(arg)) return formatLoggedError(arg, diagnosticOptions)
|
|
44
|
+
if (!arg || typeof arg !== 'object' || diagnosticOptions.redactFields.includes('error')) return arg
|
|
45
|
+
|
|
46
|
+
/** @type {unknown} */
|
|
47
|
+
const nestedError = Object.getOwnPropertyDescriptor(arg, 'error')?.value
|
|
48
|
+
if (!isErrorObject(nestedError)) return arg
|
|
49
|
+
/** @type {object} */
|
|
50
|
+
const metadata = Object(formatDiagnosticValue(arg, diagnosticOptions))
|
|
51
|
+
if (!Object.hasOwn(metadata, 'error')) return metadata
|
|
52
|
+
return {
|
|
53
|
+
...metadata,
|
|
54
|
+
error: formatLoggedError(nestedError, diagnosticOptions)
|
|
42
55
|
}
|
|
43
|
-
|
|
56
|
+
} catch {
|
|
57
|
+
// The final shared formatter contains values that cannot even be classified.
|
|
44
58
|
return arg
|
|
45
|
-
}
|
|
59
|
+
}
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
// Create wrapper methods for each log level
|
|
63
|
+
/** @type {DiagnosticLogger & Record<string, unknown>} */
|
|
49
64
|
const enhancedLogger = {}
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
const logLevels = ['debug', 'info', 'warn', 'error', 'trace', 'fatal', 'log']
|
|
66
|
+
const logLevels = /** @type {const} */ (['debug', 'info', 'warn', 'error', 'trace', 'fatal', 'log'])
|
|
53
67
|
|
|
54
68
|
for (const level of logLevels) {
|
|
55
|
-
if (typeof baseLogger[level]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
for (const errorArg of errors) {
|
|
64
|
-
const error = errorArg instanceof Error ? errorArg : errorArg.error
|
|
65
|
-
if (error.details?.violations && Array.isArray(error.details.violations) && error.details.violations.length > 0) {
|
|
66
|
-
// Log violations in a readable format
|
|
67
|
-
baseLogger[level]('Validation error details:', {
|
|
68
|
-
message: error.message,
|
|
69
|
-
violations: error.details.violations.map(v => ({
|
|
70
|
-
field: v.field,
|
|
71
|
-
rule: v.rule,
|
|
72
|
-
message: v.message
|
|
73
|
-
}))
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return baseLogger[level](...processedArgs)
|
|
80
|
-
}
|
|
69
|
+
if (typeof baseLogger[level] !== 'function') continue
|
|
70
|
+
// Capture before enhanceLogger replaces methods on the same object.
|
|
71
|
+
const write = baseLogger[level].bind(baseLogger)
|
|
72
|
+
enhancedLogger[level] = function (...args) {
|
|
73
|
+
const processedArgs = args.slice(0, 50).map(formatArgument)
|
|
74
|
+
if (args.length > 50) processedArgs.push('[Truncated]')
|
|
75
|
+
const formatted = formatDiagnosticValue(processedArgs, diagnosticOptions)
|
|
76
|
+
return write(...(Array.isArray(formatted) ? formatted : [formatted]))
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
79
|
|
|
84
80
|
// Preserve any other properties/methods from the base logger
|
|
85
81
|
for (const key in baseLogger) {
|
|
86
82
|
if (!(key in enhancedLogger)) {
|
|
87
|
-
enhancedLogger[key] = baseLogger
|
|
83
|
+
enhancedLogger[key] = Reflect.get(baseLogger, key)
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const errorData = formatError(error,
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
/** @type {EnhancedDiagnosticLogger['logError']} */
|
|
88
|
+
const logError = function (message, error, additionalData = {}) {
|
|
89
|
+
const errorData = formatError(error, diagnosticOptions)
|
|
90
|
+
/** @type {object} */
|
|
91
|
+
const metadata = Object(formatDiagnosticValue(additionalData, diagnosticOptions))
|
|
92
|
+
return this.error(message, {
|
|
93
|
+
...metadata,
|
|
96
94
|
error: errorData,
|
|
97
|
-
errorSummary: formatErrorSummary(error)
|
|
95
|
+
errorSummary: formatErrorSummary(error, diagnosticOptions)
|
|
98
96
|
})
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
99
|
+
/** @type {EnhancedDiagnosticLogger['logValidationError']} */
|
|
100
|
+
const logValidationError = function (message, error, additionalData = {}) {
|
|
101
|
+
const details = diagnosticOptions.redactFields.includes('details') ? undefined : readDiagnosticProperty(error, 'details')
|
|
102
|
+
const violations = diagnosticOptions.redactFields.includes('violations') ? undefined : readDiagnosticProperty(details, 'violations')
|
|
103
|
+
if (!Array.isArray(violations)) return this.logError(message, error, additionalData)
|
|
104
|
+
const formatted = formatError(error, { ...diagnosticOptions, includeStack: false })
|
|
105
|
+
const formattedDetails = readDiagnosticProperty(formatted, 'details')
|
|
106
|
+
/** @type {object} */
|
|
107
|
+
const metadata = Object(formatDiagnosticValue(additionalData, diagnosticOptions))
|
|
108
|
+
return this.error(message, {
|
|
109
|
+
...metadata,
|
|
110
|
+
message: readDiagnosticProperty(formatted, 'message'),
|
|
111
|
+
code: readDiagnosticProperty(formatted, 'code'),
|
|
112
|
+
violations: readDiagnosticProperty(formattedDetails, 'violations'),
|
|
113
|
+
fields: readDiagnosticProperty(formattedDetails, 'fields') || [],
|
|
114
|
+
fullError: formatted
|
|
115
|
+
})
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
return enhancedLogger
|
|
118
|
+
return Object.assign(enhancedLogger, { logError, logValidationError })
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
/**
|
|
120
122
|
* Middleware to enhance an existing logger instance
|
|
121
123
|
* Can be used to patch global loggers
|
|
124
|
+
* @template {DiagnosticLogger} Logger
|
|
125
|
+
* @param {Logger} logger
|
|
126
|
+
* @param {DiagnosticOptions} [options]
|
|
127
|
+
* @returns {Logger}
|
|
122
128
|
*/
|
|
123
129
|
export function enhanceLogger (logger, options = {}) {
|
|
124
130
|
const enhanced = createEnhancedLogger(logger, options)
|
|
@@ -126,7 +132,7 @@ export function enhanceLogger (logger, options = {}) {
|
|
|
126
132
|
// Replace methods on the original logger
|
|
127
133
|
for (const key in enhanced) {
|
|
128
134
|
if (typeof enhanced[key] === 'function') {
|
|
129
|
-
logger[key]
|
|
135
|
+
Object.assign(logger, { [key]: enhanced[key] })
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
138
|
|