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.
Files changed (117) hide show
  1. package/.claude/settings.local.json +9 -1
  2. package/AGENTS.md +34 -0
  3. package/CLAUDE.md +26 -1
  4. package/CRUSH.md +55 -0
  5. package/README.md +3 -3
  6. package/TODO.todo +8 -0
  7. package/docs/API.md +17 -18
  8. package/docs/COMPARISON.md +18 -13
  9. package/docs/GUIDE/GUIDE_1_Initial_Setup.md +17 -21
  10. package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +33 -2
  11. package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +61 -7
  12. package/docs/GUIDE/GUIDE_2_3_BelongsTo_Relationships.md +58 -61
  13. package/docs/GUIDE/GUIDE_2_4_HasMany_Records.md +37 -37
  14. package/docs/GUIDE/GUIDE_2_5_HasMany_Polymorphic.md +103 -87
  15. package/docs/GUIDE/GUIDE_2_6_Many_To_Many.md +37 -34
  16. package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +45 -42
  17. package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +3 -3
  18. package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +1 -1
  19. package/docs/GUIDE/GUIDE_3_Field_Transformations.md +5 -5
  20. package/docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md +498 -755
  21. package/docs/GUIDE/GUIDE_6_Positioning.md +1 -3
  22. package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +4 -5
  23. package/docs/GUIDE/GUIDE_X_Bulk_Operations.md +15 -6
  24. package/docs/GUIDE/GUIDE_X_Cors.md +2 -5
  25. package/docs/GUIDE/GUIDE_X_File_Uploads.md +2 -3
  26. package/docs/GUIDE/GUIDE_X_Multihome.md +1 -4
  27. package/docs/GUIDE/GUIDE_X_SocketIO.md +0 -2
  28. package/docs/GUIDE/GUIDE_X_URL_Management.md +317 -0
  29. package/docs/GUIDE/index.md +3 -0
  30. package/docs/QUICKSTART.md +12 -12
  31. package/docs/index.md +2 -2
  32. package/docs/mini-guides/file-uploads-complete.md +0 -1
  33. package/examples/url-override-example.js +137 -0
  34. package/index.js +7 -1
  35. package/package.json +7 -11
  36. package/plugins/core/bulk-operations-plugin.js +2 -0
  37. package/plugins/core/connectors/express-plugin.js +43 -24
  38. package/plugins/core/connectors/lib/request-helpers.js +2 -2
  39. package/plugins/core/lib/anyapi/anyapi-registry.js +821 -0
  40. package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +647 -0
  41. package/plugins/core/lib/anyapi/schema-utils.js +186 -0
  42. package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +113 -0
  43. package/plugins/core/lib/dbTablesOperations.js +305 -0
  44. package/plugins/core/lib/querying/knex-cross-table-search.js +64 -108
  45. package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +21 -27
  46. package/plugins/core/lib/querying/knex-pagination-helpers.js +36 -20
  47. package/plugins/core/lib/querying/knex-query-helpers-base.js +49 -14
  48. package/plugins/core/lib/querying/knex-query-helpers.js +378 -222
  49. package/plugins/core/lib/querying/knex-relationship-includes.js +262 -87
  50. package/plugins/core/lib/querying/url-helpers.js +119 -0
  51. package/plugins/core/lib/querying-writing/compile-schemas.js +36 -28
  52. package/plugins/core/lib/querying-writing/database-capabilities.js +10 -9
  53. package/plugins/core/lib/querying-writing/knex-field-helpers.js +9 -3
  54. package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +2 -2
  55. package/plugins/core/lib/querying-writing/payload-validators.js +10 -16
  56. package/plugins/core/lib/querying-writing/schema-helpers.js +52 -60
  57. package/plugins/core/lib/querying-writing/scope-validations.js +78 -22
  58. package/plugins/core/lib/querying-writing/simplified-helpers.js +208 -61
  59. package/plugins/core/lib/storage/storage-adapter.js +160 -0
  60. package/plugins/core/lib/writing/relationship-processor.js +4 -11
  61. package/plugins/core/rest-api-access.js +456 -0
  62. package/plugins/core/rest-api-anyapi-knex-plugin.js +2285 -0
  63. package/plugins/core/rest-api-knex-plugin.js +226 -87
  64. package/plugins/core/rest-api-multihome-plugin.js +89 -27
  65. package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +0 -1
  66. package/plugins/core/rest-api-plugin-methods/check-permissions.js +1 -5
  67. package/plugins/core/rest-api-plugin-methods/common.js +46 -10
  68. package/plugins/core/rest-api-plugin-methods/delete-relationship.js +31 -27
  69. package/plugins/core/rest-api-plugin-methods/delete.js +1 -4
  70. package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +13 -1
  71. package/plugins/core/rest-api-plugin-methods/get-related.js +114 -56
  72. package/plugins/core/rest-api-plugin-methods/get-relationship.js +4 -3
  73. package/plugins/core/rest-api-plugin-methods/get.js +2 -5
  74. package/plugins/core/rest-api-plugin-methods/patch.js +15 -16
  75. package/plugins/core/rest-api-plugin-methods/post-relationship.js +21 -14
  76. package/plugins/core/rest-api-plugin-methods/post.js +23 -11
  77. package/plugins/core/rest-api-plugin-methods/put.js +18 -21
  78. package/plugins/core/rest-api-plugin-methods/query.js +3 -4
  79. package/plugins/core/rest-api-plugin-methods/release.js +13 -0
  80. package/plugins/core/rest-api-plugin.js +3 -4
  81. package/plugins/core/rest-api-positioning-plugin.js +253 -76
  82. package/plugins/core/socketio-plugin.js +436 -502
  83. package/quickTest.js +2 -2
  84. package/scripts/debug-anyapi-review-filter.mjs +63 -0
  85. package/scripts/inspect-anyapi-descriptor-country.mjs +19 -0
  86. package/scripts/inspect-anyapi-descriptor.mjs +19 -0
  87. package/test-debug.js +59 -0
  88. package/tests/README.md +7 -1
  89. package/tests/anyapi-basic.test.js +102 -0
  90. package/tests/anyapi-cursor-pagination.test.js +144 -0
  91. package/tests/computed-fields.test.js +27 -12
  92. package/tests/cors.test.js +5 -6
  93. package/tests/curl.test.js +1 -1
  94. package/tests/custom-idproperty-relationships.test.js +37 -29
  95. package/tests/field-getters.test.js +25 -7
  96. package/tests/fixtures/api-configs.js +576 -150
  97. package/tests/helpers/storage-mode.js +65 -0
  98. package/tests/helpers/test-utils.js +85 -3
  99. package/tests/include-depth-validation.test.js +35 -1
  100. package/tests/nested-includes.test.js +130 -103
  101. package/tests/pagination-cursor-multifield.test.js +17 -13
  102. package/tests/pagination-enhanced.test.js +19 -24
  103. package/tests/polymorphic-simple.test.js +9 -9
  104. package/tests/positioning-advanced.test.js +19 -19
  105. package/tests/positioning-extended.test.js +25 -25
  106. package/tests/positioning-multifilter.test.js +62 -62
  107. package/tests/positioning.test.js +7 -7
  108. package/tests/queries.test.js +5 -5
  109. package/tests/query-limits.test.js +77 -92
  110. package/tests/rest-api-access.test.js +206 -0
  111. package/tests/searchschema-merge.test.js +182 -0
  112. package/tests/socketio.test.js +33 -14
  113. package/tests/virtual-fields.test.js +0 -1
  114. package/docs/DOCS_ALL.md +0 -21894
  115. package/plugins/core/jwt-auth-plugin.js +0 -897
  116. package/plugins/core/lib/jwt-auth-helpers.js +0 -130
  117. package/tests/jwt-auth.test.js +0 -692
@@ -24,7 +24,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
24
24
  // Install positioning plugin with default configuration
25
25
  await api.use(PositioningPlugin, {
26
26
  field: 'position',
27
- filters: ['project_id', 'status'], // Default filters for most tests
27
+ filters: ['project', 'status'], // Default filters for most tests
28
28
  defaultPosition: 'last'
29
29
  });
30
30
  });
@@ -54,53 +54,53 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
54
54
  // Project 1, Active
55
55
  const p1Active1 = await api.resources.items.post({
56
56
  name: 'P1 Active 1',
57
- project_id: project1.id,
57
+ project: project1.id,
58
58
  status: 'active'
59
59
  });
60
60
 
61
61
  const p1Active2 = await api.resources.items.post({
62
62
  name: 'P1 Active 2',
63
- project_id: project1.id,
63
+ project: project1.id,
64
64
  status: 'active'
65
65
  });
66
66
 
67
67
  // Project 1, Archived
68
68
  const p1Archived1 = await api.resources.items.post({
69
69
  name: 'P1 Archived 1',
70
- project_id: project1.id,
70
+ project: project1.id,
71
71
  status: 'archived'
72
72
  });
73
73
 
74
74
  const p1Archived2 = await api.resources.items.post({
75
75
  name: 'P1 Archived 2',
76
- project_id: project1.id,
76
+ project: project1.id,
77
77
  status: 'archived'
78
78
  });
79
79
 
80
80
  // Project 2, Active
81
81
  const p2Active1 = await api.resources.items.post({
82
82
  name: 'P2 Active 1',
83
- project_id: project2.id,
83
+ project: project2.id,
84
84
  status: 'active'
85
85
  });
86
86
 
87
87
  const p2Active2 = await api.resources.items.post({
88
88
  name: 'P2 Active 2',
89
- project_id: project2.id,
89
+ project: project2.id,
90
90
  status: 'active'
91
91
  });
92
92
 
93
93
  // Project 2, Archived
94
94
  const p2Archived1 = await api.resources.items.post({
95
95
  name: 'P2 Archived 1',
96
- project_id: project2.id,
96
+ project: project2.id,
97
97
  status: 'archived'
98
98
  });
99
99
 
100
100
  // Query each combination
101
101
  const { data: p1ActiveItems } = await api.resources.items.query({
102
102
  queryParams: {
103
- filters: { project_id: project1.id, status: 'active' },
103
+ filters: { project: project1.id, status: 'active' },
104
104
  sort: ['position']
105
105
  }
106
106
  });
@@ -111,7 +111,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
111
111
 
112
112
  const { data: p1ArchivedItems } = await api.resources.items.query({
113
113
  queryParams: {
114
- filters: { project_id: project1.id, status: 'archived' },
114
+ filters: { project: project1.id, status: 'archived' },
115
115
  sort: ['position']
116
116
  }
117
117
  });
@@ -122,7 +122,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
122
122
 
123
123
  const { data: p2ActiveItems } = await api.resources.items.query({
124
124
  queryParams: {
125
- filters: { project_id: project2.id, status: 'active' },
125
+ filters: { project: project2.id, status: 'active' },
126
126
  sort: ['position']
127
127
  }
128
128
  });
@@ -147,32 +147,32 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
147
147
  // Create items with various null combinations
148
148
  const item1 = await api.resources.items.post({
149
149
  name: 'Item 1',
150
- project_id: project.id,
150
+ project: project.id,
151
151
  status: 'active'
152
152
  });
153
153
 
154
154
  const item2 = await api.resources.items.post({
155
155
  name: 'Item 2',
156
- project_id: project.id,
156
+ project: project.id,
157
157
  status: null // Null status
158
158
  });
159
159
 
160
160
  const item3 = await api.resources.items.post({
161
161
  name: 'Item 3',
162
- project_id: null, // Null project
162
+ project: null, // Null project
163
163
  status: 'active'
164
164
  });
165
165
 
166
166
  const item4 = await api.resources.items.post({
167
167
  name: 'Item 4',
168
- project_id: null,
168
+ project: null,
169
169
  status: null // Both null
170
170
  });
171
171
 
172
172
  // Query different combinations
173
173
  const { data: projectActiveItems } = await api.resources.items.query({
174
174
  queryParams: {
175
- filters: { project_id: project.id, status: 'active' },
175
+ filters: { project: project.id, status: 'active' },
176
176
  sort: ['position']
177
177
  }
178
178
  });
@@ -181,7 +181,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
181
181
 
182
182
  const { data: projectNullStatusItems } = await api.resources.items.query({
183
183
  queryParams: {
184
- filters: { project_id: project.id, status: null },
184
+ filters: { project: project.id, status: null },
185
185
  sort: ['position']
186
186
  }
187
187
  });
@@ -190,7 +190,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
190
190
 
191
191
  const { data: nullProjectActiveItems } = await api.resources.items.query({
192
192
  queryParams: {
193
- filters: { project_id: null, status: 'active' },
193
+ filters: { project: null, status: 'active' },
194
194
  sort: ['position']
195
195
  }
196
196
  });
@@ -199,7 +199,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
199
199
 
200
200
  const { data: bothNullItems } = await api.resources.items.query({
201
201
  queryParams: {
202
- filters: { project_id: null, status: null },
202
+ filters: { project: null, status: null },
203
203
  sort: ['position']
204
204
  }
205
205
  });
@@ -215,26 +215,26 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
215
215
  // Create initial items
216
216
  const item1 = await api.resources.items.post({
217
217
  name: 'Item 1',
218
- project_id: project.id,
218
+ project: project.id,
219
219
  status: 'active'
220
220
  });
221
221
 
222
222
  const item2 = await api.resources.items.post({
223
223
  name: 'Item 2',
224
- project_id: project.id,
224
+ project: project.id,
225
225
  status: 'active'
226
226
  });
227
227
 
228
228
  const item3 = await api.resources.items.post({
229
229
  name: 'Item 3',
230
- project_id: project.id,
230
+ project: project.id,
231
231
  status: 'active'
232
232
  });
233
233
 
234
234
  // Create item in different filter group with beforeId from first group
235
235
  const item4 = await api.resources.items.post({
236
236
  name: 'Item 4',
237
- project_id: project.id,
237
+ project: project.id,
238
238
  status: 'archived',
239
239
  beforeId: item2.id // This should be ignored since it's in a different filter group
240
240
  });
@@ -242,7 +242,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
242
242
  // Item 4 should be first in its filter group
243
243
  const { data: archivedItems } = await api.resources.items.query({
244
244
  queryParams: {
245
- filters: { project_id: project.id, status: 'archived' },
245
+ filters: { project: project.id, status: 'archived' },
246
246
  sort: ['position']
247
247
  }
248
248
  });
@@ -254,14 +254,14 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
254
254
  // Now position an item before another in the same filter group
255
255
  const item5 = await api.resources.items.post({
256
256
  name: 'Item 5',
257
- project_id: project.id,
257
+ project: project.id,
258
258
  status: 'active',
259
259
  beforeId: item2.id
260
260
  });
261
261
 
262
262
  const { data: activeItems } = await api.resources.items.query({
263
263
  queryParams: {
264
- filters: { project_id: project.id, status: 'active' },
264
+ filters: { project: project.id, status: 'active' },
265
265
  sort: ['position']
266
266
  }
267
267
  });
@@ -281,40 +281,40 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
281
281
  // Create items in project 1
282
282
  const item1 = await api.resources.items.post({
283
283
  name: 'Item 1',
284
- project_id: project1.id,
284
+ project: project1.id,
285
285
  status: 'active'
286
286
  });
287
287
 
288
288
  const item2 = await api.resources.items.post({
289
289
  name: 'Item 2',
290
- project_id: project1.id,
290
+ project: project1.id,
291
291
  status: 'active'
292
292
  });
293
293
 
294
294
  const item3 = await api.resources.items.post({
295
295
  name: 'Item 3',
296
- project_id: project1.id,
296
+ project: project1.id,
297
297
  status: 'active'
298
298
  });
299
299
 
300
300
  // Create items in project 2
301
301
  const item4 = await api.resources.items.post({
302
302
  name: 'Item 4',
303
- project_id: project2.id,
303
+ project: project2.id,
304
304
  status: 'active'
305
305
  });
306
306
 
307
307
  // Move item2 to project 2, positioning it before item4
308
308
  await api.resources.items.patch({
309
309
  id: item2.id,
310
- project_id: project2.id,
310
+ project: project2.id,
311
311
  beforeId: item4.id
312
312
  });
313
313
 
314
314
  // Verify project 1 now has 2 items
315
315
  const { data: p1Items } = await api.resources.items.query({
316
316
  queryParams: {
317
- filters: { project_id: project1.id, status: 'active' },
317
+ filters: { project: project1.id, status: 'active' },
318
318
  sort: ['position']
319
319
  }
320
320
  });
@@ -326,7 +326,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
326
326
  // Verify project 2 has items in correct order
327
327
  const { data: p2Items } = await api.resources.items.query({
328
328
  queryParams: {
329
- filters: { project_id: project2.id, status: 'active' },
329
+ filters: { project: project2.id, status: 'active' },
330
330
  sort: ['position']
331
331
  }
332
332
  });
@@ -344,7 +344,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
344
344
  // Verify it's now in a different filter group
345
345
  const { data: p1ActiveItems } = await api.resources.items.query({
346
346
  queryParams: {
347
- filters: { project_id: project1.id, status: 'active' },
347
+ filters: { project: project1.id, status: 'active' },
348
348
  sort: ['position']
349
349
  }
350
350
  });
@@ -354,7 +354,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
354
354
 
355
355
  const { data: p1ArchivedItems } = await api.resources.items.query({
356
356
  queryParams: {
357
- filters: { project_id: project1.id, status: 'archived' },
357
+ filters: { project: project1.id, status: 'archived' },
358
358
  sort: ['position']
359
359
  }
360
360
  });
@@ -379,7 +379,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
379
379
 
380
380
  await multiApi.use(PositioningPlugin, {
381
381
  field: 'position',
382
- filters: ['project_id', 'status', 'priority'],
382
+ filters: ['project', 'status', 'priority'],
383
383
  defaultPosition: 'last'
384
384
  });
385
385
 
@@ -394,7 +394,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
394
394
  for (const priority of priorities) {
395
395
  const item = await multiApi.resources.items.post({
396
396
  name: `Item ${status}-${priority}`,
397
- project_id: project.id,
397
+ project: project.id,
398
398
  status,
399
399
  priority
400
400
  });
@@ -408,7 +408,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
408
408
  const { data: filtered } = await multiApi.resources.items.query({
409
409
  queryParams: {
410
410
  filters: {
411
- project_id: project.id,
411
+ project: project.id,
412
412
  status: status,
413
413
  priority: priority
414
414
  },
@@ -427,7 +427,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
427
427
  for (let i = 2; i <= 5; i++) {
428
428
  const item = await multiApi.resources.items.post({
429
429
  name: `Item active-high ${i}`,
430
- project_id: project.id,
430
+ project: project.id,
431
431
  status: 'active',
432
432
  priority: 'high'
433
433
  });
@@ -438,7 +438,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
438
438
  const { data: activeHighItems } = await multiApi.resources.items.query({
439
439
  queryParams: {
440
440
  filters: {
441
- project_id: project.id,
441
+ project: project.id,
442
442
  status: 'active',
443
443
  priority: 'high'
444
444
  },
@@ -463,25 +463,25 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
463
463
  // Create items
464
464
  await api.resources.items.post({
465
465
  name: 'P1 Active 1',
466
- project_id: project1.id,
466
+ project: project1.id,
467
467
  status: 'active'
468
468
  });
469
469
 
470
470
  await api.resources.items.post({
471
471
  name: 'P1 Active 2',
472
- project_id: project1.id,
472
+ project: project1.id,
473
473
  status: 'active'
474
474
  });
475
475
 
476
476
  await api.resources.items.post({
477
477
  name: 'P1 Archived',
478
- project_id: project1.id,
478
+ project: project1.id,
479
479
  status: 'archived'
480
480
  });
481
481
 
482
482
  await api.resources.items.post({
483
483
  name: 'P2 Active',
484
- project_id: project2.id,
484
+ project: project2.id,
485
485
  status: 'active'
486
486
  });
487
487
 
@@ -517,7 +517,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
517
517
  for (let i = 1; i <= 10; i++) {
518
518
  const item = await api.resources.items.post({
519
519
  name: `Item ${i}`,
520
- project_id: project1.id,
520
+ project: project1.id,
521
521
  status: 'active'
522
522
  });
523
523
  items.push(item);
@@ -531,13 +531,13 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
531
531
  api.resources.items.patch({ id: items[2].id, status: 'archived' }),
532
532
 
533
533
  // Move to project 2
534
- api.resources.items.patch({ id: items[3].id, project_id: project2.id }),
535
- api.resources.items.patch({ id: items[4].id, project_id: project2.id }),
534
+ api.resources.items.patch({ id: items[3].id, project: project2.id }),
535
+ api.resources.items.patch({ id: items[4].id, project: project2.id }),
536
536
 
537
537
  // Move to project 2 and archived
538
538
  api.resources.items.patch({
539
539
  id: items[5].id,
540
- project_id: project2.id,
540
+ project: project2.id,
541
541
  status: 'archived'
542
542
  })
543
543
  ];
@@ -547,7 +547,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
547
547
  // Verify distributions
548
548
  const { data: p1Active } = await api.resources.items.query({
549
549
  queryParams: {
550
- filters: { project_id: project1.id, status: 'active' },
550
+ filters: { project: project1.id, status: 'active' },
551
551
  sort: ['position']
552
552
  }
553
553
  });
@@ -555,7 +555,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
555
555
 
556
556
  const { data: p1Archived } = await api.resources.items.query({
557
557
  queryParams: {
558
- filters: { project_id: project1.id, status: 'archived' },
558
+ filters: { project: project1.id, status: 'archived' },
559
559
  sort: ['position']
560
560
  }
561
561
  });
@@ -563,7 +563,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
563
563
 
564
564
  const { data: p2Active } = await api.resources.items.query({
565
565
  queryParams: {
566
- filters: { project_id: project2.id, status: 'active' },
566
+ filters: { project: project2.id, status: 'active' },
567
567
  sort: ['position']
568
568
  }
569
569
  });
@@ -571,7 +571,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
571
571
 
572
572
  const { data: p2Archived } = await api.resources.items.query({
573
573
  queryParams: {
574
- filters: { project_id: project2.id, status: 'archived' },
574
+ filters: { project: project2.id, status: 'archived' },
575
575
  sort: ['position']
576
576
  }
577
577
  });
@@ -602,26 +602,26 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
602
602
  // Create items with various empty/null combinations
603
603
  const item1 = await api.resources.items.post({
604
604
  name: 'Item 1',
605
- project_id: project.id,
605
+ project: project.id,
606
606
  status: '' // Empty string
607
607
  });
608
608
 
609
609
  const item2 = await api.resources.items.post({
610
610
  name: 'Item 2',
611
- project_id: project.id,
611
+ project: project.id,
612
612
  status: null // Null
613
613
  });
614
614
 
615
615
  const item3 = await api.resources.items.post({
616
616
  name: 'Item 3',
617
- project_id: project.id,
617
+ project: project.id,
618
618
  status: 'active'
619
619
  });
620
620
 
621
621
  // Query with empty string filter
622
622
  const { data: emptyStatusItems } = await api.resources.items.query({
623
623
  queryParams: {
624
- filters: { project_id: project.id, status: '' },
624
+ filters: { project: project.id, status: '' },
625
625
  sort: ['position']
626
626
  }
627
627
  });
@@ -632,7 +632,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
632
632
  // Query with null filter
633
633
  const { data: nullStatusItems } = await api.resources.items.query({
634
634
  queryParams: {
635
- filters: { project_id: project.id, status: null },
635
+ filters: { project: project.id, status: null },
636
636
  sort: ['position']
637
637
  }
638
638
  });
@@ -654,26 +654,26 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
654
654
  // Create items with numeric-like status values
655
655
  const item1 = await api.resources.items.post({
656
656
  name: 'Item 1',
657
- project_id: project.id,
657
+ project: project.id,
658
658
  status: '1'
659
659
  });
660
660
 
661
661
  const item2 = await api.resources.items.post({
662
662
  name: 'Item 2',
663
- project_id: project.id,
663
+ project: project.id,
664
664
  status: '01' // Different string representation
665
665
  });
666
666
 
667
667
  const item3 = await api.resources.items.post({
668
668
  name: 'Item 3',
669
- project_id: project.id,
669
+ project: project.id,
670
670
  status: '1'
671
671
  });
672
672
 
673
673
  // Query with string '1'
674
674
  const { data: status1Items } = await api.resources.items.query({
675
675
  queryParams: {
676
- filters: { project_id: project.id, status: '1' },
676
+ filters: { project: project.id, status: '1' },
677
677
  sort: ['position']
678
678
  }
679
679
  });
@@ -686,7 +686,7 @@ describe('Multi-Filter Positioning Tests', { timeout: 30000 }, () => {
686
686
  // Query with string '01'
687
687
  const { data: status01Items } = await api.resources.items.query({
688
688
  queryParams: {
689
- filters: { project_id: project.id, status: '01' },
689
+ filters: { project: project.id, status: '01' },
690
690
  sort: ['position']
691
691
  }
692
692
  });
@@ -26,7 +26,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
26
26
  // Install positioning plugin with default configuration
27
27
  await api.use(PositioningPlugin, {
28
28
  field: 'position',
29
- filters: ['category_id'], // Tasks will be grouped by category
29
+ filters: ['category'], // Tasks will be grouped by category
30
30
  defaultPosition: 'last',
31
31
  autoIndex: true
32
32
  });
@@ -225,7 +225,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
225
225
  // Get fresh data
226
226
  const { data: allTasks } = await api.resources.tasks.query({
227
227
  queryParams: {
228
- filters: { category_id: category.id },
228
+ filters: { category: category.id },
229
229
  sort: ['position']
230
230
  }
231
231
  });
@@ -312,7 +312,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
312
312
 
313
313
  await customApi.use(PositioningPlugin, {
314
314
  field: 'sort_order', // Different field name
315
- filters: ['project_id'],
315
+ filters: ['project'],
316
316
  defaultPosition: 'last'
317
317
  });
318
318
 
@@ -339,7 +339,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
339
339
 
340
340
  await multiFilterApi.use(PositioningPlugin, {
341
341
  field: 'position',
342
- filters: ['project_id', 'status'], // Multiple filters
342
+ filters: ['project', 'status'], // Multiple filters
343
343
  defaultPosition: 'last'
344
344
  });
345
345
 
@@ -381,7 +381,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
381
381
 
382
382
  await firstApi.use(PositioningPlugin, {
383
383
  field: 'position',
384
- filters: ['category_id'],
384
+ filters: ['category'],
385
385
  defaultPosition: 'first' // Items go to beginning by default
386
386
  });
387
387
 
@@ -531,7 +531,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
531
531
  // Query with position sort
532
532
  const { data: sorted } = await api.resources.tasks.query({
533
533
  queryParams: {
534
- filters: { category_id: category.id },
534
+ filters: { category: category.id },
535
535
  sort: ['position']
536
536
  }
537
537
  });
@@ -546,7 +546,7 @@ describe('Positioning Plugin Tests', { timeout: 30000 }, () => {
546
546
  // Query with reverse position sort
547
547
  const { data: reverseSorted } = await api.resources.tasks.query({
548
548
  queryParams: {
549
- filters: { category_id: category.id },
549
+ filters: { category: category.id },
550
550
  sort: ['-position']
551
551
  }
552
552
  });
@@ -125,7 +125,7 @@ describe('Query Operations', () => {
125
125
  it('should filter by simple field', async () => {
126
126
  const result = await basicApi.resources.books.query({
127
127
  queryParams: {
128
- filters: { country_id: testData.countries[0].id }
128
+ filters: { country: testData.countries[0].id }
129
129
  },
130
130
  simplified: false
131
131
  });
@@ -147,8 +147,8 @@ describe('Query Operations', () => {
147
147
  const result = await basicApi.resources.books.query({
148
148
  queryParams: {
149
149
  filters: {
150
- country_id: testData.countries[0].id,
151
- publisher_id: testData.publishers[0].id
150
+ country: testData.countries[0].id,
151
+ publisher: testData.publishers[0].id
152
152
  }
153
153
  },
154
154
  simplified: false
@@ -162,7 +162,7 @@ describe('Query Operations', () => {
162
162
  it('should return empty array when no matches', async () => {
163
163
  const result = await basicApi.resources.books.query({
164
164
  queryParams: {
165
- filters: { country_id: 99999 }
165
+ filters: { country: 99999 }
166
166
  },
167
167
  simplified: false
168
168
  });
@@ -285,7 +285,7 @@ describe('Query Operations', () => {
285
285
  // Sort by country_id ascending, then title descending
286
286
  const result = await basicApi.resources.books.query({
287
287
  queryParams: {
288
- sort: ['country_id', '-title']
288
+ sort: ['country', '-title']
289
289
  },
290
290
  simplified: false
291
291
  });