json-rest-api 1.0.14 → 1.0.16
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/connectors_ideas/fastify.js +66 -68
- package/connectors_ideas/koa-plugin.js +50 -51
- package/eslint.config.js +11 -2
- package/examples/url-override-example.js +63 -63
- package/index.js +13 -13
- package/lib/enhanced-logger.js +51 -51
- package/lib/error-formatter.js +61 -61
- package/lib/rest-api-errors.js +28 -28
- package/package.json +1 -1
- package/plugins/core/bulk-operations-plugin.js +142 -145
- package/plugins/core/connectors/express-plugin.js +210 -217
- package/plugins/core/connectors/lib/busboy-detector.js +84 -84
- package/plugins/core/connectors/lib/formidable-detector.js +50 -50
- package/plugins/core/connectors/lib/request-helpers.js +74 -74
- package/plugins/core/file-handling-plugin.js +125 -125
- package/plugins/core/lib/anyapi/anyapi-registry.js +254 -254
- package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +287 -287
- package/plugins/core/lib/anyapi/schema-utils.js +101 -101
- package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +41 -41
- package/plugins/core/lib/dbTablesOperations.js +134 -135
- package/plugins/core/lib/fractional-positioning.js +74 -76
- package/plugins/core/lib/querying/knex-cross-table-search.js +320 -320
- package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +144 -144
- package/plugins/core/lib/querying/knex-pagination-helpers.js +164 -164
- package/plugins/core/lib/querying/knex-process-includes.js +50 -50
- package/plugins/core/lib/querying/knex-query-helpers-base.js +31 -31
- package/plugins/core/lib/querying/knex-query-helpers.js +451 -452
- package/plugins/core/lib/querying/knex-relationship-includes.js +1160 -1170
- package/plugins/core/lib/querying/knex-window-queries.js +89 -89
- package/plugins/core/lib/querying/url-helpers.js +35 -35
- package/plugins/core/lib/querying-writing/compile-schemas.js +99 -99
- package/plugins/core/lib/querying-writing/connectors-query-parser.js +31 -31
- package/plugins/core/lib/querying-writing/database-capabilities.js +94 -94
- package/plugins/core/lib/querying-writing/database-value-normalizers.js +76 -76
- package/plugins/core/lib/querying-writing/default-data-helpers.js +27 -27
- package/plugins/core/lib/querying-writing/field-utils.js +44 -42
- package/plugins/core/lib/querying-writing/knex-constants.js +15 -16
- package/plugins/core/lib/querying-writing/knex-field-helpers.js +117 -115
- package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +41 -41
- package/plugins/core/lib/querying-writing/payload-validators.js +275 -275
- package/plugins/core/lib/querying-writing/schema-helpers.js +129 -129
- package/plugins/core/lib/querying-writing/scope-validations.js +143 -146
- package/plugins/core/lib/querying-writing/simplified-helpers.js +133 -129
- package/plugins/core/lib/storage/storage-adapter.js +68 -68
- package/plugins/core/lib/writing/knex-json-api-transformers-writing.js +31 -31
- package/plugins/core/lib/writing/many-to-many-manipulations.js +81 -81
- package/plugins/core/lib/writing/relationship-processor.js +58 -58
- package/plugins/core/rest-api-access.js +11 -15
- package/plugins/core/rest-api-anyapi-knex-plugin.js +920 -920
- package/plugins/core/rest-api-cors-plugin.js +170 -171
- package/plugins/core/rest-api-knex-plugin.js +482 -493
- package/plugins/core/rest-api-multihome-plugin.js +247 -251
- package/plugins/core/rest-api-plugin-hooks/compile-resource-schemas.js +5 -5
- package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +20 -21
- package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +44 -44
- package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +23 -23
- package/plugins/core/rest-api-plugin-hooks/validate-include-configurations.js +15 -15
- package/plugins/core/rest-api-plugin-methods/add-route.js +9 -9
- package/plugins/core/rest-api-plugin-methods/check-permissions.js +5 -6
- package/plugins/core/rest-api-plugin-methods/common.js +295 -297
- package/plugins/core/rest-api-plugin-methods/delete-relationship.js +35 -37
- package/plugins/core/rest-api-plugin-methods/delete.js +57 -59
- package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +172 -171
- package/plugins/core/rest-api-plugin-methods/get-related.js +96 -96
- package/plugins/core/rest-api-plugin-methods/get-relationship.js +16 -18
- package/plugins/core/rest-api-plugin-methods/get.js +86 -86
- package/plugins/core/rest-api-plugin-methods/patch-relationship.js +16 -17
- package/plugins/core/rest-api-plugin-methods/patch.js +63 -64
- package/plugins/core/rest-api-plugin-methods/post-relationship.js +54 -55
- package/plugins/core/rest-api-plugin-methods/post.js +61 -62
- package/plugins/core/rest-api-plugin-methods/put.js +86 -87
- package/plugins/core/rest-api-plugin-methods/query.js +88 -88
- package/plugins/core/rest-api-plugin-methods/release.js +5 -6
- package/plugins/core/rest-api-plugin.js +76 -78
- package/plugins/core/rest-api-positioning-plugin.js +251 -252
- package/plugins/core/socketio-plugin.js +240 -236
- package/plugins/storage/local-storage.js +103 -103
- package/plugins/storage/s3-storage.js +41 -42
- package/quickTest.js +37 -37
- package/scripts/debug-anyapi-review-filter.mjs +18 -18
- package/scripts/inspect-anyapi-descriptor-country.mjs +10 -10
- package/scripts/inspect-anyapi-descriptor.mjs +10 -10
- package/scripts/run-docs.js +112 -113
- package/test-debug.js +28 -28
- package/tests/TEST_TEMPLATE.test.js +51 -51
- package/tests/anyapi-basic.test.js +42 -42
- package/tests/anyapi-cursor-pagination.test.js +48 -48
- package/tests/bulk-operations.test.js +208 -208
- package/tests/computed-fields.test.js +204 -204
- package/tests/cors.test.js +412 -413
- package/tests/curl.test.js +275 -276
- package/tests/custom-idproperty-relationships.test.js +266 -266
- package/tests/field-getters.test.js +132 -132
- package/tests/field-setters.test.js +110 -110
- package/tests/fixtures/api-configs.js +699 -699
- package/tests/helpers/storage-mode.js +32 -32
- package/tests/helpers/test-utils.js +76 -76
- package/tests/include-depth-validation.test.js +76 -76
- package/tests/includes.test.js +145 -145
- package/tests/multihome.test.js +175 -175
- package/tests/nested-includes.test.js +255 -255
- package/tests/pagination-cursor-multifield.test.js +164 -164
- package/tests/pagination-enhanced.test.js +225 -225
- package/tests/polymorphic-relationships.test.js +96 -96
- package/tests/polymorphic-simple.test.js +44 -44
- package/tests/positioning-advanced.test.js +226 -226
- package/tests/positioning-extended.test.js +399 -399
- package/tests/positioning-multifilter.test.js +204 -204
- package/tests/positioning.test.js +266 -266
- package/tests/queries.test.js +184 -184
- package/tests/query-limits.test.js +154 -155
- package/tests/relationship-endpoints.test.js +127 -127
- package/tests/relationships.test.js +178 -179
- package/tests/rest-api-access.test.js +86 -86
- package/tests/rest-api.test.js +103 -103
- package/tests/searchschema-merge.test.js +93 -93
- package/tests/socketio.test.js +326 -326
- package/tests/virtual-fields.test.js +164 -164
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { describe, it, before, after } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import knexLib from 'knex'
|
|
4
|
-
import { createBasicApi, createLimitedDepthApi } from './fixtures/api-configs.js'
|
|
5
|
-
import { cleanTables } from './helpers/test-utils.js'
|
|
1
|
+
import { describe, it, before, after } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import knexLib from 'knex'
|
|
4
|
+
import { createBasicApi, createLimitedDepthApi } from './fixtures/api-configs.js'
|
|
5
|
+
import { cleanTables } from './helpers/test-utils.js'
|
|
6
6
|
|
|
7
7
|
// Create Knex instance for tests
|
|
8
8
|
const knex = knexLib({
|
|
@@ -11,10 +11,10 @@ const knex = knexLib({
|
|
|
11
11
|
filename: ':memory:'
|
|
12
12
|
},
|
|
13
13
|
useNullAsDefault: true
|
|
14
|
-
})
|
|
14
|
+
})
|
|
15
15
|
|
|
16
16
|
describe('Include Depth Validation', () => {
|
|
17
|
-
let api
|
|
17
|
+
let api
|
|
18
18
|
|
|
19
19
|
before(async () => {
|
|
20
20
|
// Initialize API with custom includeDepthLimit
|
|
@@ -22,13 +22,13 @@ describe('Include Depth Validation', () => {
|
|
|
22
22
|
'rest-api': {
|
|
23
23
|
includeDepthLimit: 3 // Default is 3, but being explicit
|
|
24
24
|
}
|
|
25
|
-
})
|
|
25
|
+
})
|
|
26
26
|
|
|
27
27
|
// Set up test data with nested relationships
|
|
28
28
|
// Country -> Publisher -> Author -> Book
|
|
29
29
|
await cleanTables(knex, [
|
|
30
30
|
'basic_countries', 'basic_publishers', 'basic_authors', 'basic_books'
|
|
31
|
-
])
|
|
31
|
+
])
|
|
32
32
|
|
|
33
33
|
const country = await api.resources.countries.post({
|
|
34
34
|
inputRecord: {
|
|
@@ -37,7 +37,7 @@ describe('Include Depth Validation', () => {
|
|
|
37
37
|
attributes: { name: 'USA', code: 'US' }
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
})
|
|
40
|
+
})
|
|
41
41
|
|
|
42
42
|
const publisher = await api.resources.publishers.post({
|
|
43
43
|
inputRecord: {
|
|
@@ -49,7 +49,7 @@ describe('Include Depth Validation', () => {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
})
|
|
52
|
+
})
|
|
53
53
|
|
|
54
54
|
const author = await api.resources.authors.post({
|
|
55
55
|
inputRecord: {
|
|
@@ -61,7 +61,7 @@ describe('Include Depth Validation', () => {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
})
|
|
64
|
+
})
|
|
65
65
|
|
|
66
66
|
await api.resources.books.post({
|
|
67
67
|
inputRecord: {
|
|
@@ -74,137 +74,137 @@ describe('Include Depth Validation', () => {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
})
|
|
78
|
-
})
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
79
|
|
|
80
80
|
after(async () => {
|
|
81
|
-
await knex.destroy()
|
|
82
|
-
})
|
|
81
|
+
await knex.destroy()
|
|
82
|
+
})
|
|
83
83
|
|
|
84
84
|
describe('Query endpoint validation', () => {
|
|
85
85
|
it('should allow includes within depth limit', async () => {
|
|
86
86
|
// Depth 1
|
|
87
87
|
const depth1 = await api.resources.publishers.query({
|
|
88
88
|
queryParams: { include: ['country'] }
|
|
89
|
-
})
|
|
90
|
-
assert(depth1.data.length > 0, 'Should return publishers')
|
|
91
|
-
assert(depth1.included, 'Should have included resources')
|
|
89
|
+
})
|
|
90
|
+
assert(depth1.data.length > 0, 'Should return publishers')
|
|
91
|
+
assert(depth1.included, 'Should have included resources')
|
|
92
92
|
|
|
93
93
|
// Depth 2
|
|
94
94
|
const depth2 = await api.resources.authors.query({
|
|
95
95
|
queryParams: { include: ['publisher.country'] }
|
|
96
|
-
})
|
|
97
|
-
assert(depth2.data.length > 0, 'Should return authors')
|
|
96
|
+
})
|
|
97
|
+
assert(depth2.data.length > 0, 'Should return authors')
|
|
98
98
|
// The included array may or may not be present depending on whether relationships exist
|
|
99
99
|
|
|
100
100
|
// Depth 3 (at limit)
|
|
101
101
|
const depth3 = await api.resources.books.query({
|
|
102
102
|
queryParams: { include: ['publisher.country.publishers'] }
|
|
103
|
-
})
|
|
104
|
-
assert(depth3.data.length > 0, 'Should return books')
|
|
103
|
+
})
|
|
104
|
+
assert(depth3.data.length > 0, 'Should return books')
|
|
105
105
|
// Note: The included array might be present even if some relationships don't have data
|
|
106
|
-
})
|
|
106
|
+
})
|
|
107
107
|
|
|
108
108
|
it('should reject includes exceeding depth limit', async () => {
|
|
109
109
|
await assert.rejects(
|
|
110
110
|
async () => {
|
|
111
111
|
await api.resources.books.query({
|
|
112
112
|
queryParams: { include: ['publisher.country.publishers.books'] }
|
|
113
|
-
})
|
|
113
|
+
})
|
|
114
114
|
},
|
|
115
115
|
{
|
|
116
116
|
name: 'RestApiValidationError',
|
|
117
117
|
message: /Include path.*exceeds maximum depth of 3/
|
|
118
118
|
},
|
|
119
119
|
'Should reject depth 4'
|
|
120
|
-
)
|
|
120
|
+
)
|
|
121
121
|
|
|
122
122
|
await assert.rejects(
|
|
123
123
|
async () => {
|
|
124
124
|
await api.resources.books.query({
|
|
125
125
|
queryParams: { include: ['publisher.country.publishers.books.authors'] }
|
|
126
|
-
})
|
|
126
|
+
})
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
129
|
name: 'RestApiValidationError',
|
|
130
130
|
message: /Include path.*exceeds maximum depth of 3/
|
|
131
131
|
},
|
|
132
132
|
'Should reject depth 5'
|
|
133
|
-
)
|
|
134
|
-
})
|
|
133
|
+
)
|
|
134
|
+
})
|
|
135
135
|
|
|
136
136
|
it('should validate each include path independently', async () => {
|
|
137
137
|
await assert.rejects(
|
|
138
138
|
async () => {
|
|
139
139
|
await api.resources.books.query({
|
|
140
|
-
queryParams: {
|
|
140
|
+
queryParams: {
|
|
141
141
|
include: [
|
|
142
142
|
'publisher', // Valid (depth 1)
|
|
143
143
|
'publisher.country', // Valid (depth 2)
|
|
144
144
|
'publisher.country.publishers.books' // Invalid (depth 4)
|
|
145
|
-
]
|
|
145
|
+
]
|
|
146
146
|
}
|
|
147
|
-
})
|
|
147
|
+
})
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
name: 'RestApiValidationError',
|
|
151
151
|
message: /publisher\.country\.publishers\.books.*exceeds maximum depth of 3/
|
|
152
152
|
},
|
|
153
153
|
'Should reject when any path exceeds limit'
|
|
154
|
-
)
|
|
155
|
-
})
|
|
156
|
-
})
|
|
154
|
+
)
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
157
|
|
|
158
158
|
describe('Get endpoint validation', () => {
|
|
159
159
|
it('should allow includes within depth limit', async () => {
|
|
160
|
-
const books = await api.resources.books.query()
|
|
161
|
-
const bookId = books.data[0].id
|
|
160
|
+
const books = await api.resources.books.query()
|
|
161
|
+
const bookId = books.data[0].id
|
|
162
162
|
|
|
163
163
|
// Depth 1
|
|
164
164
|
const depth1 = await api.resources.books.get({
|
|
165
165
|
id: bookId,
|
|
166
166
|
queryParams: { include: ['publisher'] }
|
|
167
|
-
})
|
|
168
|
-
assert(depth1.data.id === bookId, 'Should return correct book')
|
|
169
|
-
assert(depth1.included, 'Should have included resources')
|
|
167
|
+
})
|
|
168
|
+
assert(depth1.data.id === bookId, 'Should return correct book')
|
|
169
|
+
assert(depth1.included, 'Should have included resources')
|
|
170
170
|
|
|
171
171
|
// Depth 3 (at limit)
|
|
172
172
|
const depth3 = await api.resources.books.get({
|
|
173
173
|
id: bookId,
|
|
174
174
|
queryParams: { include: ['publisher.country.publishers'] }
|
|
175
|
-
})
|
|
176
|
-
assert(depth3.data.id === bookId, 'Should return correct book')
|
|
177
|
-
})
|
|
175
|
+
})
|
|
176
|
+
assert(depth3.data.id === bookId, 'Should return correct book')
|
|
177
|
+
})
|
|
178
178
|
|
|
179
179
|
it('should reject includes exceeding depth limit', async () => {
|
|
180
|
-
const books = await api.resources.books.query()
|
|
181
|
-
const bookId = books.data[0].id
|
|
180
|
+
const books = await api.resources.books.query()
|
|
181
|
+
const bookId = books.data[0].id
|
|
182
182
|
|
|
183
183
|
await assert.rejects(
|
|
184
184
|
async () => {
|
|
185
185
|
await api.resources.books.get({
|
|
186
186
|
id: bookId,
|
|
187
187
|
queryParams: { include: ['publisher.country.publishers.books'] }
|
|
188
|
-
})
|
|
188
|
+
})
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
name: 'RestApiValidationError',
|
|
192
192
|
message: /Include path.*exceeds maximum depth of 3/
|
|
193
193
|
},
|
|
194
194
|
'Should reject depth 4 on GET'
|
|
195
|
-
)
|
|
196
|
-
})
|
|
197
|
-
})
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
198
|
|
|
199
199
|
describe('Custom depth limits', () => {
|
|
200
200
|
it('should respect custom includeDepthLimit configuration', async () => {
|
|
201
201
|
// Create API with depth limit of 2 and different table names
|
|
202
|
-
const limitedApi = await createLimitedDepthApi(knex)
|
|
202
|
+
const limitedApi = await createLimitedDepthApi(knex)
|
|
203
203
|
|
|
204
204
|
// Set up test data for limited API
|
|
205
205
|
await cleanTables(knex, [
|
|
206
206
|
'limited_countries', 'limited_publishers', 'limited_authors', 'limited_books', 'limited_book_authors'
|
|
207
|
-
])
|
|
207
|
+
])
|
|
208
208
|
|
|
209
209
|
const country = await limitedApi.resources.countries.post({
|
|
210
210
|
inputRecord: {
|
|
@@ -213,7 +213,7 @@ describe('Include Depth Validation', () => {
|
|
|
213
213
|
attributes: { name: 'Limited Country', code: 'LC' }
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
-
})
|
|
216
|
+
})
|
|
217
217
|
|
|
218
218
|
const publisher = await limitedApi.resources.publishers.post({
|
|
219
219
|
inputRecord: {
|
|
@@ -225,7 +225,7 @@ describe('Include Depth Validation', () => {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
-
})
|
|
228
|
+
})
|
|
229
229
|
|
|
230
230
|
const author = await limitedApi.resources.authors.post({
|
|
231
231
|
inputRecord: {
|
|
@@ -237,38 +237,38 @@ describe('Include Depth Validation', () => {
|
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
|
-
})
|
|
240
|
+
})
|
|
241
241
|
|
|
242
242
|
// Depth 2 should work
|
|
243
243
|
const depth2 = await limitedApi.resources.authors.query({
|
|
244
244
|
queryParams: { include: ['publisher.country'] }
|
|
245
|
-
})
|
|
246
|
-
assert(depth2.data.length > 0, 'Should return authors')
|
|
245
|
+
})
|
|
246
|
+
assert(depth2.data.length > 0, 'Should return authors')
|
|
247
247
|
|
|
248
248
|
// Depth 3 should fail
|
|
249
249
|
await assert.rejects(
|
|
250
250
|
async () => {
|
|
251
251
|
await limitedApi.resources.books.query({
|
|
252
252
|
queryParams: { include: ['publisher.country.publishers'] }
|
|
253
|
-
})
|
|
253
|
+
})
|
|
254
254
|
},
|
|
255
255
|
{
|
|
256
256
|
name: 'RestApiValidationError',
|
|
257
257
|
message: /Include path.*exceeds maximum depth of 2/
|
|
258
258
|
},
|
|
259
259
|
'Should reject depth 3 with custom limit of 2'
|
|
260
|
-
)
|
|
261
|
-
})
|
|
262
|
-
})
|
|
260
|
+
)
|
|
261
|
+
})
|
|
262
|
+
})
|
|
263
263
|
|
|
264
264
|
describe('Edge cases', () => {
|
|
265
265
|
it('should handle empty include arrays', async () => {
|
|
266
266
|
const result = await api.resources.books.query({
|
|
267
267
|
queryParams: { include: [] }
|
|
268
|
-
})
|
|
269
|
-
assert(result.data.length > 0, 'Should return books')
|
|
270
|
-
assert(!result.included, 'Should not have included resources')
|
|
271
|
-
})
|
|
268
|
+
})
|
|
269
|
+
assert(result.data.length > 0, 'Should return books')
|
|
270
|
+
assert(!result.included, 'Should not have included resources')
|
|
271
|
+
})
|
|
272
272
|
|
|
273
273
|
it('should handle single-level paths correctly', async () => {
|
|
274
274
|
const country = await api.resources.countries.post({
|
|
@@ -278,7 +278,7 @@ describe('Include Depth Validation', () => {
|
|
|
278
278
|
attributes: { name: 'Single Level Country', code: `S${Date.now().toString().slice(-2)}` }
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
-
})
|
|
281
|
+
})
|
|
282
282
|
|
|
283
283
|
const publisher = await api.resources.publishers.post({
|
|
284
284
|
inputRecord: {
|
|
@@ -290,7 +290,7 @@ describe('Include Depth Validation', () => {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
-
})
|
|
293
|
+
})
|
|
294
294
|
|
|
295
295
|
await api.resources.books.post({
|
|
296
296
|
inputRecord: {
|
|
@@ -303,14 +303,14 @@ describe('Include Depth Validation', () => {
|
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
|
-
})
|
|
306
|
+
})
|
|
307
307
|
|
|
308
308
|
const result = await api.resources.books.query({
|
|
309
309
|
queryParams: { include: ['publisher'] }
|
|
310
|
-
})
|
|
311
|
-
assert(result.data.length > 0, 'Should return books')
|
|
312
|
-
assert(result.included, 'Should have included resources')
|
|
313
|
-
})
|
|
310
|
+
})
|
|
311
|
+
assert(result.data.length > 0, 'Should return books')
|
|
312
|
+
assert(result.included, 'Should have included resources')
|
|
313
|
+
})
|
|
314
314
|
|
|
315
315
|
it('should count depth correctly with dots in path', async () => {
|
|
316
316
|
// "a.b.c" = depth 3
|
|
@@ -318,14 +318,14 @@ describe('Include Depth Validation', () => {
|
|
|
318
318
|
async () => {
|
|
319
319
|
await api.resources.books.query({
|
|
320
320
|
queryParams: { include: ['a.b.c.d'] }
|
|
321
|
-
})
|
|
321
|
+
})
|
|
322
322
|
},
|
|
323
323
|
{
|
|
324
324
|
name: 'RestApiValidationError',
|
|
325
325
|
message: /Include path 'a\.b\.c\.d' exceeds maximum depth of 3/
|
|
326
326
|
},
|
|
327
327
|
'Should count dots correctly'
|
|
328
|
-
)
|
|
329
|
-
})
|
|
330
|
-
})
|
|
331
|
-
})
|
|
328
|
+
)
|
|
329
|
+
})
|
|
330
|
+
})
|
|
331
|
+
})
|