json-rest-api 1.0.10 → 1.0.13
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/settings.local.json +9 -1
- package/AGENTS.md +34 -0
- package/CLAUDE.md +26 -1
- package/CRUSH.md +55 -0
- package/README.md +3 -3
- package/TODO.todo +8 -0
- package/docs/API.md +17 -18
- package/docs/COMPARISON.md +18 -13
- package/docs/GUIDE/GUIDE_1_Initial_Setup.md +17 -21
- package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +33 -2
- package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +61 -7
- package/docs/GUIDE/GUIDE_2_3_BelongsTo_Relationships.md +58 -61
- package/docs/GUIDE/GUIDE_2_4_HasMany_Records.md +37 -37
- package/docs/GUIDE/GUIDE_2_5_HasMany_Polymorphic.md +103 -87
- package/docs/GUIDE/GUIDE_2_6_Many_To_Many.md +37 -34
- package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +45 -42
- package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +3 -3
- package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +1 -1
- package/docs/GUIDE/GUIDE_3_Field_Transformations.md +5 -5
- package/docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md +498 -755
- package/docs/GUIDE/GUIDE_6_Positioning.md +1 -3
- package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +4 -5
- package/docs/GUIDE/GUIDE_X_Bulk_Operations.md +15 -6
- package/docs/GUIDE/GUIDE_X_Cors.md +2 -5
- package/docs/GUIDE/GUIDE_X_File_Uploads.md +2 -3
- package/docs/GUIDE/GUIDE_X_Multihome.md +1 -4
- package/docs/GUIDE/GUIDE_X_SocketIO.md +0 -2
- package/docs/GUIDE/GUIDE_X_URL_Management.md +317 -0
- package/docs/GUIDE/index.md +3 -0
- package/docs/QUICKSTART.md +12 -12
- package/docs/index.md +2 -2
- package/docs/mini-guides/file-uploads-complete.md +0 -1
- package/examples/url-override-example.js +137 -0
- package/index.js +7 -1
- package/package.json +7 -11
- package/plugins/core/bulk-operations-plugin.js +2 -0
- package/plugins/core/connectors/express-plugin.js +43 -24
- package/plugins/core/connectors/lib/request-helpers.js +2 -2
- package/plugins/core/lib/anyapi/anyapi-registry.js +821 -0
- package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +647 -0
- package/plugins/core/lib/anyapi/schema-utils.js +186 -0
- package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +113 -0
- package/plugins/core/lib/dbTablesOperations.js +305 -0
- package/plugins/core/lib/querying/knex-cross-table-search.js +64 -108
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +21 -27
- package/plugins/core/lib/querying/knex-pagination-helpers.js +36 -20
- package/plugins/core/lib/querying/knex-query-helpers-base.js +49 -14
- package/plugins/core/lib/querying/knex-query-helpers.js +378 -222
- package/plugins/core/lib/querying/knex-relationship-includes.js +262 -87
- package/plugins/core/lib/querying/url-helpers.js +119 -0
- package/plugins/core/lib/querying-writing/compile-schemas.js +36 -28
- package/plugins/core/lib/querying-writing/database-capabilities.js +10 -9
- package/plugins/core/lib/querying-writing/knex-field-helpers.js +9 -3
- package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +2 -2
- package/plugins/core/lib/querying-writing/payload-validators.js +10 -16
- package/plugins/core/lib/querying-writing/schema-helpers.js +52 -60
- package/plugins/core/lib/querying-writing/scope-validations.js +78 -22
- package/plugins/core/lib/querying-writing/simplified-helpers.js +208 -61
- package/plugins/core/lib/storage/storage-adapter.js +160 -0
- package/plugins/core/lib/writing/relationship-processor.js +4 -11
- package/plugins/core/rest-api-access.js +456 -0
- package/plugins/core/rest-api-anyapi-knex-plugin.js +2285 -0
- package/plugins/core/rest-api-knex-plugin.js +226 -87
- package/plugins/core/rest-api-multihome-plugin.js +89 -27
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +0 -1
- package/plugins/core/rest-api-plugin-methods/check-permissions.js +1 -5
- package/plugins/core/rest-api-plugin-methods/common.js +46 -10
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +31 -27
- package/plugins/core/rest-api-plugin-methods/delete.js +1 -4
- package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +13 -1
- package/plugins/core/rest-api-plugin-methods/get-related.js +114 -56
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +4 -3
- package/plugins/core/rest-api-plugin-methods/get.js +2 -5
- package/plugins/core/rest-api-plugin-methods/patch.js +15 -16
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +21 -14
- package/plugins/core/rest-api-plugin-methods/post.js +23 -11
- package/plugins/core/rest-api-plugin-methods/put.js +18 -21
- package/plugins/core/rest-api-plugin-methods/query.js +3 -4
- package/plugins/core/rest-api-plugin-methods/release.js +13 -0
- package/plugins/core/rest-api-plugin.js +3 -4
- package/plugins/core/rest-api-positioning-plugin.js +253 -76
- package/plugins/core/socketio-plugin.js +436 -502
- package/quickTest.js +2 -2
- package/scripts/debug-anyapi-review-filter.mjs +63 -0
- package/scripts/inspect-anyapi-descriptor-country.mjs +19 -0
- package/scripts/inspect-anyapi-descriptor.mjs +19 -0
- package/test-debug.js +59 -0
- package/tests/README.md +7 -1
- package/tests/anyapi-basic.test.js +102 -0
- package/tests/anyapi-cursor-pagination.test.js +144 -0
- package/tests/computed-fields.test.js +27 -12
- package/tests/cors.test.js +5 -6
- package/tests/curl.test.js +1 -1
- package/tests/custom-idproperty-relationships.test.js +37 -29
- package/tests/field-getters.test.js +25 -7
- package/tests/fixtures/api-configs.js +576 -150
- package/tests/helpers/storage-mode.js +65 -0
- package/tests/helpers/test-utils.js +85 -3
- package/tests/include-depth-validation.test.js +35 -1
- package/tests/nested-includes.test.js +130 -103
- package/tests/pagination-cursor-multifield.test.js +17 -13
- package/tests/pagination-enhanced.test.js +19 -24
- package/tests/polymorphic-simple.test.js +9 -9
- package/tests/positioning-advanced.test.js +19 -19
- package/tests/positioning-extended.test.js +25 -25
- package/tests/positioning-multifilter.test.js +62 -62
- package/tests/positioning.test.js +7 -7
- package/tests/queries.test.js +5 -5
- package/tests/query-limits.test.js +77 -92
- package/tests/rest-api-access.test.js +206 -0
- package/tests/searchschema-merge.test.js +182 -0
- package/tests/socketio.test.js +33 -14
- package/tests/virtual-fields.test.js +0 -1
- package/docs/DOCS_ALL.md +0 -21894
- package/plugins/core/jwt-auth-plugin.js +0 -897
- package/plugins/core/lib/jwt-auth-helpers.js +0 -130
- package/tests/jwt-auth.test.js +0 -692
package/tests/socketio.test.js
CHANGED
|
@@ -2,7 +2,7 @@ import { describe, it, before, after, beforeEach } from 'node:test';
|
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import knexLib from 'knex';
|
|
4
4
|
import { io as ioClient } from 'socket.io-client';
|
|
5
|
-
import
|
|
5
|
+
import { SignJWT } from 'jose';
|
|
6
6
|
import {
|
|
7
7
|
validateJsonApiStructure,
|
|
8
8
|
cleanTables,
|
|
@@ -13,6 +13,25 @@ import {
|
|
|
13
13
|
} from './helpers/test-utils.js';
|
|
14
14
|
import { createWebSocketApi } from './fixtures/api-configs.js';
|
|
15
15
|
|
|
16
|
+
// Create JWT token using jose
|
|
17
|
+
async function createToken(payload = {}, secret = 'test-secret-key') {
|
|
18
|
+
const encoder = new TextEncoder();
|
|
19
|
+
const key = encoder.encode(secret);
|
|
20
|
+
|
|
21
|
+
const jwt = new SignJWT({
|
|
22
|
+
sub: '123',
|
|
23
|
+
email: 'test@example.com',
|
|
24
|
+
roles: ['user'],
|
|
25
|
+
...payload,
|
|
26
|
+
jti: `test-${Date.now()}`
|
|
27
|
+
})
|
|
28
|
+
.setProtectedHeader({ alg: 'HS256' })
|
|
29
|
+
.setIssuedAt()
|
|
30
|
+
.setExpirationTime('1h');
|
|
31
|
+
|
|
32
|
+
return await jwt.sign(key);
|
|
33
|
+
}
|
|
34
|
+
|
|
16
35
|
// Create Knex instance for tests
|
|
17
36
|
const knex = knexLib({
|
|
18
37
|
client: 'better-sqlite3',
|
|
@@ -106,7 +125,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
106
125
|
describe('Basic Subscription and Notifications', () => {
|
|
107
126
|
it('should receive minimal notifications for subscribed resources', async () => {
|
|
108
127
|
// Generate a real JWT token for testing
|
|
109
|
-
const token =
|
|
128
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
110
129
|
|
|
111
130
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
112
131
|
path: '/api/socket.io',
|
|
@@ -170,7 +189,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
170
189
|
|
|
171
190
|
it('should not receive notifications for non-matching filters', async () => {
|
|
172
191
|
// Generate a real JWT token for testing
|
|
173
|
-
const token =
|
|
192
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
174
193
|
|
|
175
194
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
176
195
|
path: '/api/socket.io',
|
|
@@ -234,7 +253,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
234
253
|
describe('Filter Validation', () => {
|
|
235
254
|
it('should validate filters against searchSchema', async () => {
|
|
236
255
|
// Generate a real JWT token for testing
|
|
237
|
-
const token =
|
|
256
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
238
257
|
|
|
239
258
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
240
259
|
path: '/api/socket.io',
|
|
@@ -265,7 +284,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
265
284
|
|
|
266
285
|
it('should reject function filters without filterRecord', async () => {
|
|
267
286
|
// Generate a real JWT token for testing
|
|
268
|
-
const token =
|
|
287
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
269
288
|
|
|
270
289
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
271
290
|
path: '/api/socket.io',
|
|
@@ -294,7 +313,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
294
313
|
const response = await new Promise((resolve) => {
|
|
295
314
|
socket.emit('subscribe', {
|
|
296
315
|
resource: 'books',
|
|
297
|
-
filters: {
|
|
316
|
+
filters: { country: countryResult.data.id }
|
|
298
317
|
}, resolve);
|
|
299
318
|
});
|
|
300
319
|
|
|
@@ -318,7 +337,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
318
337
|
// This test verifies that broadcasts don't happen when operations fail
|
|
319
338
|
// The library should rollback transactions and not send notifications
|
|
320
339
|
|
|
321
|
-
const token =
|
|
340
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
322
341
|
|
|
323
342
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
324
343
|
path: '/api/socket.io',
|
|
@@ -375,7 +394,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
375
394
|
// The library handles transactions internally and uses afterCommit hook
|
|
376
395
|
// to ensure broadcasts happen only after successful commit
|
|
377
396
|
|
|
378
|
-
const token =
|
|
397
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
379
398
|
|
|
380
399
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
381
400
|
path: '/api/socket.io',
|
|
@@ -439,7 +458,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
439
458
|
describe('Multiple Subscriptions', () => {
|
|
440
459
|
it('should handle multiple subscriptions from same client', async () => {
|
|
441
460
|
// Generate a real JWT token for testing
|
|
442
|
-
const token =
|
|
461
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
443
462
|
|
|
444
463
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
445
464
|
path: '/api/socket.io',
|
|
@@ -498,7 +517,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
498
517
|
|
|
499
518
|
it('should unsubscribe correctly', async () => {
|
|
500
519
|
// Generate a real JWT token for testing
|
|
501
|
-
const token =
|
|
520
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
502
521
|
|
|
503
522
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
504
523
|
path: '/api/socket.io',
|
|
@@ -557,7 +576,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
557
576
|
describe('Update and Delete Notifications', () => {
|
|
558
577
|
it('should receive notifications for updates', async () => {
|
|
559
578
|
// Generate a real JWT token for testing
|
|
560
|
-
const token =
|
|
579
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
561
580
|
|
|
562
581
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
563
582
|
path: '/api/socket.io',
|
|
@@ -627,7 +646,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
627
646
|
|
|
628
647
|
it('should receive notifications for deletes', async () => {
|
|
629
648
|
// Generate a real JWT token for testing
|
|
630
|
-
const token =
|
|
649
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
631
650
|
|
|
632
651
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
633
652
|
path: '/api/socket.io',
|
|
@@ -687,7 +706,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
687
706
|
describe('Relationship Filters', () => {
|
|
688
707
|
it('should filter by relationship fields', async () => {
|
|
689
708
|
// Generate a real JWT token for testing
|
|
690
|
-
const token =
|
|
709
|
+
const token = await createToken({ userId: 'test-user', role: 'user' }, 'test-secret-key');
|
|
691
710
|
|
|
692
711
|
const socket = ioClient(`http://localhost:${server.address().port}`, {
|
|
693
712
|
path: '/api/socket.io',
|
|
@@ -721,7 +740,7 @@ describe('WebSocket/Socket.IO Plugin', () => {
|
|
|
721
740
|
await new Promise((resolve) => {
|
|
722
741
|
socket.emit('subscribe', {
|
|
723
742
|
resource: 'books',
|
|
724
|
-
filters: {
|
|
743
|
+
filters: { publisher: publisherResult.data.id }
|
|
725
744
|
}, resolve);
|
|
726
745
|
});
|
|
727
746
|
|