json-rest-api 1.0.24 → 1.0.26
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/README.md +2 -1
- package/docs/API.md +12 -9
- package/docs/GUIDE/GUIDE_1_Initial_Setup.md +5 -2
- package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +3 -3
- package/docs/GUIDE/GUIDE_3_Field_Transformations.md +2 -0
- package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +1 -1
- package/docs/GUIDE/GUIDE_X_Autofiltering.md +63 -0
- package/docs/GUIDE/GUIDE_X_File_Uploads.md +17 -12
- package/docs/GUIDE/GUIDE_X_Row_Policies.md +605 -0
- package/docs/GUIDE/GUIDE_X_SocketIO.md +15 -10
- package/docs/GUIDE/GUIDE_X_URL_Management.md +93 -254
- package/docs/GUIDE/GUIDE_X_Writing_Plugins.md +2 -0
- package/docs/GUIDE/index.md +4 -1
- package/fixing_plan.md +112 -0
- package/index.js +2 -0
- package/package.json +1 -1
- package/plugins/core/bulk-operations-plugin.js +5 -4
- package/plugins/core/connectors/express-plugin.js +6 -1
- package/plugins/core/connectors/fastify-plugin.js +5 -1
- package/plugins/core/connectors/lib/connector-core.js +17 -11
- package/plugins/core/connectors/lib/transport-route-schemas.js +12 -60
- package/plugins/core/file-handling-plugin.js +126 -96
- package/plugins/core/lib/anyapi/anyapi-registry.js +21 -3
- package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +36 -26
- package/plugins/core/lib/anyapi/schema-utils.js +1 -0
- package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +7 -1
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +20 -15
- package/plugins/core/lib/querying/knex-pagination-helpers.js +38 -84
- package/plugins/core/lib/querying/knex-relationship-includes.js +29 -28
- package/plugins/core/lib/querying/knex-window-queries.js +10 -77
- package/plugins/core/lib/querying/storage-adapter-utils.js +8 -8
- package/plugins/core/lib/querying/url-helpers.js +9 -21
- package/plugins/core/lib/querying-writing/connectors-query-parser.js +51 -0
- package/plugins/core/lib/querying-writing/database-capabilities.js +1 -1
- package/plugins/core/lib/querying-writing/database-value-normalizers.js +18 -9
- package/plugins/core/lib/querying-writing/knex-field-helpers.js +6 -1
- package/plugins/core/lib/querying-writing/relationship-contracts.js +56 -0
- package/plugins/core/lib/querying-writing/request-contracts.js +53 -4
- package/plugins/core/lib/querying-writing/return-record-settings.js +47 -0
- package/plugins/core/lib/querying-writing/schema-helpers.js +34 -41
- package/plugins/core/lib/storage/canonical-storage-mapping.js +2 -1
- package/plugins/core/lib/storage/storage-adapter.js +74 -13
- package/plugins/core/lib/writing/many-to-many-manipulations.js +4 -3
- package/plugins/core/lib/writing/relationship-processor.js +10 -1
- package/plugins/core/rest-api-anyapi-knex-plugin.js +210 -97
- package/plugins/core/rest-api-knex-plugin.js +70 -60
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +8 -2
- package/plugins/core/rest-api-plugin-methods/common.js +85 -63
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +23 -13
- package/plugins/core/rest-api-plugin-methods/delete.js +2 -6
- package/plugins/core/rest-api-plugin-methods/get-related.js +15 -13
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +1 -1
- package/plugins/core/rest-api-plugin-methods/patch-relationship.js +17 -6
- package/plugins/core/rest-api-plugin-methods/patch.js +3 -6
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +24 -14
- package/plugins/core/rest-api-plugin-methods/post.js +4 -7
- package/plugins/core/rest-api-plugin-methods/put.js +4 -7
- package/plugins/core/rest-api-plugin.js +6 -36
- package/plugins/core/rest-api-row-policy-plugin.js +157 -0
- package/plugins/storage/local-storage.js +44 -19
- package/plugins/storage/s3-storage.js +21 -55
- package/tests/README.md +1 -1
- package/tests/anyapi-cursor-pagination.test.js +7 -1
- package/tests/anyapi-custom-idproperty.test.js +163 -0
- package/tests/fastify-plugin.test.js +28 -0
- package/tests/field-setters.test.js +10 -10
- package/tests/file-handling.test.js +118 -0
- package/tests/fixtures/api-configs.js +383 -4
- package/tests/full-jsonapi-belongsto-linkage.test.js +150 -0
- package/tests/http-connectors-parity.test.js +165 -5
- package/tests/local-storage.test.js +96 -0
- package/tests/pagination-cursor-multifield.test.js +121 -0
- package/tests/pagination-enhanced.test.js +66 -15
- package/tests/post-commit-hooks.test.js +120 -0
- package/tests/public-exports.test.js +15 -0
- package/tests/put-create-parity.test.js +216 -0
- package/tests/relationship-endpoints.test.js +259 -0
- package/tests/return-record-settings.test.js +184 -0
- package/tests/row-policy.test.js +489 -0
- package/tests/s3-storage.test.js +38 -0
- package/tests/searchschema-merge.test.js +17 -0
- package/tests/socketio.test.js +62 -0
- package/tests/storage-mapping.test.js +1 -0
- package/tests/test-development-guide.md +5 -5
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cleanTables,
|
|
6
6
|
} from './helpers/test-utils.js'
|
|
7
7
|
import { createSearchSchemaMergeApi } from './fixtures/api-configs.js'
|
|
8
|
+
import { generateSearchSchemaFromSchema } from '../plugins/core/lib/querying-writing/schema-helpers.js'
|
|
8
9
|
|
|
9
10
|
// Create Knex instance for tests - always use SQLite in-memory
|
|
10
11
|
const knex = knexLib({
|
|
@@ -131,4 +132,20 @@ describe('SearchSchema Merge Behavior', () => {
|
|
|
131
132
|
'Should reject fields that are not defined in searchSchema'
|
|
132
133
|
)
|
|
133
134
|
})
|
|
135
|
+
|
|
136
|
+
it('should keep canonical belongsTo field keys searchable alongside relationship aliases', () => {
|
|
137
|
+
const searchSchema = generateSearchSchemaFromSchema({
|
|
138
|
+
petId: {
|
|
139
|
+
type: 'id',
|
|
140
|
+
belongsTo: 'pets',
|
|
141
|
+
as: 'pet',
|
|
142
|
+
search: true
|
|
143
|
+
}
|
|
144
|
+
}, null)
|
|
145
|
+
|
|
146
|
+
assert.ok(searchSchema.pet, 'relationship alias should stay searchable')
|
|
147
|
+
assert.equal(searchSchema.pet.actualField, 'petId')
|
|
148
|
+
assert.ok(searchSchema.petId, 'canonical field key should stay searchable for parent filters')
|
|
149
|
+
assert.equal(searchSchema.petId.actualField, 'petId')
|
|
150
|
+
})
|
|
134
151
|
})
|
package/tests/socketio.test.js
CHANGED
|
@@ -453,6 +453,68 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
453
453
|
socket.close()
|
|
454
454
|
}
|
|
455
455
|
})
|
|
456
|
+
|
|
457
|
+
it('should broadcast deferred patch notifications from relationship PATCH', async () => {
|
|
458
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key')
|
|
459
|
+
|
|
460
|
+
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
461
|
+
path: '/api/socket.io',
|
|
462
|
+
auth: { token }
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
try {
|
|
466
|
+
await new Promise((resolve, reject) => {
|
|
467
|
+
socket.on('connect', resolve)
|
|
468
|
+
socket.on('connect_error', reject)
|
|
469
|
+
setTimeout(() => reject(new Error('Connection timeout')), 5000)
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
const country = await api.resources.countries.post({
|
|
473
|
+
inputRecord: createJsonApiDocument('countries', {
|
|
474
|
+
name: 'Original Country',
|
|
475
|
+
code: 'OC'
|
|
476
|
+
}),
|
|
477
|
+
simplified: false
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
const nextCountry = await api.resources.countries.post({
|
|
481
|
+
inputRecord: createJsonApiDocument('countries', {
|
|
482
|
+
name: 'Next Country',
|
|
483
|
+
code: 'NC'
|
|
484
|
+
}),
|
|
485
|
+
simplified: false
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
const book = await api.resources.books.post({
|
|
489
|
+
inputRecord: createJsonApiDocument(
|
|
490
|
+
'books',
|
|
491
|
+
{ title: 'Relationship Patch Broadcast' },
|
|
492
|
+
{ country: createRelationship(resourceIdentifier('countries', country.data.id)) }
|
|
493
|
+
),
|
|
494
|
+
simplified: false
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
await new Promise((resolve) => {
|
|
498
|
+
socket.emit('subscribe', { resource: 'books' }, resolve)
|
|
499
|
+
})
|
|
500
|
+
|
|
501
|
+
const updatePromise = waitForSocketEvent(socket, 'subscription.update', 1000)
|
|
502
|
+
|
|
503
|
+
await api.resources.books.patchRelationship({
|
|
504
|
+
id: book.data.id,
|
|
505
|
+
relationshipName: 'country',
|
|
506
|
+
relationshipData: resourceIdentifier('countries', nextCountry.data.id)
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
const notification = await updatePromise
|
|
510
|
+
assert.equal(notification.type, 'resource.patchd')
|
|
511
|
+
assert.equal(notification.resource, 'books')
|
|
512
|
+
assert.equal(String(notification.id), String(book.data.id))
|
|
513
|
+
assert.equal(notification.action, 'patch')
|
|
514
|
+
} finally {
|
|
515
|
+
socket.close()
|
|
516
|
+
}
|
|
517
|
+
})
|
|
456
518
|
})
|
|
457
519
|
|
|
458
520
|
describe('Multiple Subscriptions', () => {
|
|
@@ -42,6 +42,7 @@ describe('Storage mapping', () => {
|
|
|
42
42
|
await api.use(RestApiPlugin, {
|
|
43
43
|
simplifiedApi: false,
|
|
44
44
|
simplifiedTransport: false,
|
|
45
|
+
sortableFields: ['id', 'displayName', 'loginCount', 'lastSeenAt', 'countryId', 'externalRef'],
|
|
45
46
|
returnRecordApi: {
|
|
46
47
|
post: 'full',
|
|
47
48
|
put: 'full',
|
|
@@ -64,9 +64,9 @@ Control what methods return:
|
|
|
64
64
|
```javascript
|
|
65
65
|
// In API configuration
|
|
66
66
|
returnFullRecord: {
|
|
67
|
-
post:
|
|
68
|
-
put:
|
|
69
|
-
patch:
|
|
67
|
+
post: 'full', // Return created record (needed to get ID)
|
|
68
|
+
put: 'no', // Don't return after replacement
|
|
69
|
+
patch: 'no' // Don't return after update
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// Override per call if needed
|
|
@@ -74,7 +74,7 @@ const result = await api.resources.books.put({
|
|
|
74
74
|
id: bookId,
|
|
75
75
|
inputRecord: putDoc,
|
|
76
76
|
simplified: false,
|
|
77
|
-
returnFullRecord:
|
|
77
|
+
returnFullRecord: 'no' // Override to not return
|
|
78
78
|
});
|
|
79
79
|
```
|
|
80
80
|
|
|
@@ -367,4 +367,4 @@ npm test -- tests/relationships.test.js
|
|
|
367
367
|
4. **validation.test.js** - Schema validation edge cases
|
|
368
368
|
5. **polymorphic.test.js** - Polymorphic relationship tests
|
|
369
369
|
|
|
370
|
-
Each should follow the patterns established in existing tests.
|
|
370
|
+
Each should follow the patterns established in existing tests.
|