json-rest-api 1.0.13 → 1.0.15

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 (118) hide show
  1. package/connectors_ideas/fastify.js +66 -68
  2. package/connectors_ideas/koa-plugin.js +50 -51
  3. package/eslint.config.js +13 -0
  4. package/examples/url-override-example.js +63 -63
  5. package/index.js +13 -13
  6. package/lib/enhanced-logger.js +51 -51
  7. package/lib/error-formatter.js +61 -61
  8. package/lib/rest-api-errors.js +28 -28
  9. package/package.json +9 -5
  10. package/plugins/core/bulk-operations-plugin.js +142 -145
  11. package/plugins/core/connectors/express-plugin.js +210 -217
  12. package/plugins/core/connectors/lib/busboy-detector.js +84 -84
  13. package/plugins/core/connectors/lib/formidable-detector.js +50 -50
  14. package/plugins/core/connectors/lib/request-helpers.js +74 -74
  15. package/plugins/core/file-handling-plugin.js +125 -125
  16. package/plugins/core/lib/anyapi/anyapi-registry.js +254 -254
  17. package/plugins/core/lib/anyapi/query/anyapi-query-adapter.js +287 -287
  18. package/plugins/core/lib/anyapi/schema-utils.js +101 -101
  19. package/plugins/core/lib/anyapi/utils/descriptor-helpers.js +41 -41
  20. package/plugins/core/lib/dbTablesOperations.js +134 -135
  21. package/plugins/core/lib/fractional-positioning.js +74 -76
  22. package/plugins/core/lib/querying/knex-cross-table-search.js +320 -320
  23. package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +144 -144
  24. package/plugins/core/lib/querying/knex-pagination-helpers.js +164 -164
  25. package/plugins/core/lib/querying/knex-process-includes.js +50 -50
  26. package/plugins/core/lib/querying/knex-query-helpers-base.js +31 -31
  27. package/plugins/core/lib/querying/knex-query-helpers.js +451 -452
  28. package/plugins/core/lib/querying/knex-relationship-includes.js +1160 -1170
  29. package/plugins/core/lib/querying/knex-window-queries.js +89 -89
  30. package/plugins/core/lib/querying/url-helpers.js +35 -35
  31. package/plugins/core/lib/querying-writing/compile-schemas.js +97 -98
  32. package/plugins/core/lib/querying-writing/connectors-query-parser.js +31 -31
  33. package/plugins/core/lib/querying-writing/database-capabilities.js +94 -94
  34. package/plugins/core/lib/querying-writing/database-value-normalizers.js +76 -76
  35. package/plugins/core/lib/querying-writing/default-data-helpers.js +27 -27
  36. package/plugins/core/lib/querying-writing/field-utils.js +44 -42
  37. package/plugins/core/lib/querying-writing/knex-constants.js +15 -16
  38. package/plugins/core/lib/querying-writing/knex-field-helpers.js +117 -115
  39. package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +41 -41
  40. package/plugins/core/lib/querying-writing/payload-validators.js +275 -275
  41. package/plugins/core/lib/querying-writing/schema-helpers.js +129 -129
  42. package/plugins/core/lib/querying-writing/scope-validations.js +143 -146
  43. package/plugins/core/lib/querying-writing/simplified-helpers.js +133 -129
  44. package/plugins/core/lib/storage/storage-adapter.js +68 -68
  45. package/plugins/core/lib/writing/knex-json-api-transformers-writing.js +31 -31
  46. package/plugins/core/lib/writing/many-to-many-manipulations.js +81 -81
  47. package/plugins/core/lib/writing/relationship-processor.js +58 -58
  48. package/plugins/core/rest-api-access.js +8 -8
  49. package/plugins/core/rest-api-anyapi-knex-plugin.js +920 -920
  50. package/plugins/core/rest-api-cors-plugin.js +170 -171
  51. package/plugins/core/rest-api-knex-plugin.js +482 -493
  52. package/plugins/core/rest-api-multihome-plugin.js +247 -251
  53. package/plugins/core/rest-api-plugin-hooks/compile-resource-schemas.js +5 -5
  54. package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +20 -21
  55. package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +44 -44
  56. package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +23 -23
  57. package/plugins/core/rest-api-plugin-hooks/validate-include-configurations.js +15 -15
  58. package/plugins/core/rest-api-plugin-methods/add-route.js +9 -9
  59. package/plugins/core/rest-api-plugin-methods/check-permissions.js +5 -6
  60. package/plugins/core/rest-api-plugin-methods/common.js +295 -297
  61. package/plugins/core/rest-api-plugin-methods/delete-relationship.js +35 -37
  62. package/plugins/core/rest-api-plugin-methods/delete.js +57 -59
  63. package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +172 -171
  64. package/plugins/core/rest-api-plugin-methods/get-related.js +96 -96
  65. package/plugins/core/rest-api-plugin-methods/get-relationship.js +16 -18
  66. package/plugins/core/rest-api-plugin-methods/get.js +86 -86
  67. package/plugins/core/rest-api-plugin-methods/patch-relationship.js +16 -17
  68. package/plugins/core/rest-api-plugin-methods/patch.js +63 -64
  69. package/plugins/core/rest-api-plugin-methods/post-relationship.js +54 -55
  70. package/plugins/core/rest-api-plugin-methods/post.js +61 -62
  71. package/plugins/core/rest-api-plugin-methods/put.js +86 -87
  72. package/plugins/core/rest-api-plugin-methods/query.js +88 -88
  73. package/plugins/core/rest-api-plugin-methods/release.js +5 -6
  74. package/plugins/core/rest-api-plugin.js +76 -78
  75. package/plugins/core/rest-api-positioning-plugin.js +251 -252
  76. package/plugins/core/socketio-plugin.js +240 -236
  77. package/plugins/storage/local-storage.js +103 -103
  78. package/plugins/storage/s3-storage.js +41 -42
  79. package/quickTest.js +37 -37
  80. package/scripts/debug-anyapi-review-filter.mjs +18 -18
  81. package/scripts/inspect-anyapi-descriptor-country.mjs +10 -10
  82. package/scripts/inspect-anyapi-descriptor.mjs +10 -10
  83. package/scripts/run-docs.js +112 -113
  84. package/test-debug.js +28 -28
  85. package/tests/TEST_TEMPLATE.test.js +51 -51
  86. package/tests/anyapi-basic.test.js +42 -42
  87. package/tests/anyapi-cursor-pagination.test.js +48 -48
  88. package/tests/bulk-operations.test.js +208 -208
  89. package/tests/computed-fields.test.js +204 -204
  90. package/tests/cors.test.js +412 -413
  91. package/tests/curl.test.js +275 -276
  92. package/tests/custom-idproperty-relationships.test.js +266 -266
  93. package/tests/field-getters.test.js +132 -132
  94. package/tests/field-setters.test.js +110 -110
  95. package/tests/fixtures/api-configs.js +699 -699
  96. package/tests/helpers/storage-mode.js +32 -32
  97. package/tests/helpers/test-utils.js +76 -76
  98. package/tests/include-depth-validation.test.js +76 -76
  99. package/tests/includes.test.js +145 -145
  100. package/tests/multihome.test.js +175 -175
  101. package/tests/nested-includes.test.js +255 -255
  102. package/tests/pagination-cursor-multifield.test.js +164 -164
  103. package/tests/pagination-enhanced.test.js +225 -225
  104. package/tests/polymorphic-relationships.test.js +96 -96
  105. package/tests/polymorphic-simple.test.js +44 -44
  106. package/tests/positioning-advanced.test.js +226 -226
  107. package/tests/positioning-extended.test.js +399 -399
  108. package/tests/positioning-multifilter.test.js +204 -204
  109. package/tests/positioning.test.js +266 -266
  110. package/tests/queries.test.js +184 -184
  111. package/tests/query-limits.test.js +154 -155
  112. package/tests/relationship-endpoints.test.js +127 -127
  113. package/tests/relationships.test.js +178 -179
  114. package/tests/rest-api-access.test.js +86 -86
  115. package/tests/rest-api.test.js +103 -103
  116. package/tests/searchschema-merge.test.js +93 -93
  117. package/tests/socketio.test.js +326 -326
  118. package/tests/virtual-fields.test.js +164 -164
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Scope configuration validators for relationship definitions
3
- *
3
+ *
4
4
  * @description
5
5
  * These validators run at scope registration time to ensure:
6
6
  * - Polymorphic relationships are properly configured
@@ -9,15 +9,14 @@
9
9
  * - Referenced scopes actually exist in the system
10
10
  */
11
11
 
12
-
13
12
  /**
14
13
  * Validates all relationships in a scope configuration
15
- *
14
+ *
16
15
  * @param {Object} params - Validation parameters
17
16
  * @param {Object} params.context - Event context with scopeName and scopeOptions
18
17
  * @param {Object} params.scopes - All registered scopes for validation
19
18
  * @throws {Error} If any relationship is misconfigured
20
- *
19
+ *
21
20
  * @example
22
21
  * // Input: Valid polymorphic relationship
23
22
  * validateRelationships({
@@ -42,7 +41,7 @@
42
41
  * scopes: { posts: {}, videos: {} } // Referenced types exist
43
42
  * });
44
43
  * // Output: No error (valid configuration)
45
- *
44
+ *
46
45
  * @example
47
46
  * // Input: Missing required field
48
47
  * validateRelaationships({
@@ -63,9 +62,9 @@
63
62
  * scopes: { documents: {} }
64
63
  * });
65
64
  * // Throws: Error
66
- * // "Invalid polymorphic relationship 'attachable' in scope 'attachments':
65
+ * // "Invalid polymorphic relationship 'attachable' in scope 'attachments':
67
66
  * // belongsToPolymorphic.idField must be specified"
68
- *
67
+ *
69
68
  * @example
70
69
  * // Input: HasMany without foreignKey
71
70
  * validateRelationships({
@@ -86,7 +85,7 @@
86
85
  * // Throws: Error
87
86
  * // "Invalid hasMany relationship 'posts' in scope 'users':
88
87
  * // hasMany relationship requires foreignKey to be specified"
89
- *
88
+ *
90
89
  * @example
91
90
  * // Input: Complex activity feed with multiple polymorphic relationships
92
91
  * validateRelationships({
@@ -120,19 +119,19 @@
120
119
  * scopes: { posts: {}, comments: {}, users: {}, api_clients: {} }
121
120
  * });
122
121
  * // Output: No error (both polymorphic relationships valid)
123
- *
122
+ *
124
123
  * @description
125
124
  * Used by:
126
125
  * - rest-api-plugin on 'scope:added' event
127
126
  * - Runs automatically when scopes are registered
128
- *
127
+ *
129
128
  * Purpose:
130
129
  * - Catches configuration errors at startup, not runtime
131
130
  * - Validates polymorphic relationship structure
132
131
  * - Ensures referenced scope types exist
133
132
  * - Validates hasMany/manyToMany foreign keys
134
133
  * - Provides clear error messages for debugging
135
- *
134
+ *
136
135
  * Data flow:
137
136
  * 1. Extracts relationships from scope options
138
137
  * 2. For each relationship, checks its type
@@ -141,59 +140,58 @@
141
140
  * 5. Validates manyToMany: through, foreignKey, otherKey
142
141
  * 6. Throws descriptive error on first validation failure
143
142
  */
144
- export function validateRelationships({ context, scopes }) {
145
- const { scopeName, scopeOptions } = context;
146
- const relationships = scopeOptions.relationships || {};
147
-
143
+ export function validateRelationships ({ context, scopes }) {
144
+ const { scopeName, scopeOptions } = context
145
+ const relationships = scopeOptions.relationships || {}
146
+
148
147
  for (const [relName, relDef] of Object.entries(relationships)) {
149
148
  if (relDef.belongsToPolymorphic) {
150
- const validation = validatePolymorphicRelationship(relDef, scopeName, scopes);
149
+ const validation = validatePolymorphicRelationship(relDef, scopeName, scopes)
151
150
  if (!validation.valid) {
152
151
  throw new Error(
153
152
  `Invalid polymorphic relationship '${relName}' in scope '${scopeName}': ${validation.error}`
154
- );
153
+ )
155
154
  }
156
155
  }
157
-
156
+
158
157
  // Validate based on relationship type
159
158
  if (relDef.type === 'hasMany') {
160
- const validation = validateHasManyRelationship(relDef, relName, scopeName);
159
+ const validation = validateHasManyRelationship(relDef, relName, scopeName)
161
160
  if (!validation.valid) {
162
161
  throw new Error(
163
162
  `Invalid hasMany relationship '${relName}' in scope '${scopeName}': ${validation.error}`
164
- );
163
+ )
165
164
  }
166
165
  }
167
-
166
+
168
167
  if (relDef.type === 'hasOne') {
169
- const validation = validateHasOneRelationship(relDef, relName, scopeName);
168
+ const validation = validateHasOneRelationship(relDef, relName, scopeName)
170
169
  if (!validation.valid) {
171
170
  throw new Error(
172
171
  `Invalid hasOne relationship '${relName}' in scope '${scopeName}': ${validation.error}`
173
- );
172
+ )
174
173
  }
175
174
  }
176
-
175
+
177
176
  if (relDef.type === 'manyToMany') {
178
- const validation = validateManyToManyRelationship(relDef, relName, scopeName);
177
+ const validation = validateManyToManyRelationship(relDef, relName, scopeName)
179
178
  if (!validation.valid) {
180
179
  throw new Error(
181
180
  `Invalid manyToMany relationship '${relName}' in scope '${scopeName}': ${validation.error}`
182
- );
181
+ )
183
182
  }
184
183
  }
185
184
  }
186
185
  }
187
186
 
188
-
189
187
  /**
190
188
  * Validates a polymorphic relationship definition
191
- *
189
+ *
192
190
  * @param {Object} relDef - Relationship definition with belongsToPolymorphic
193
191
  * @param {string} scopeName - Scope being registered (for error messages)
194
192
  * @param {Object} scopes - All registered scopes for validation
195
193
  * @returns {Object} Validation result {valid: boolean, error?: string}
196
- *
194
+ *
197
195
  * @example
198
196
  * // Input: Valid polymorphic configuration
199
197
  * const relDef = {
@@ -205,7 +203,7 @@ export function validateRelationships({ context, scopes }) {
205
203
  * };
206
204
  * validatePolymorphicRelationship(relDef, 'comments', scopes);
207
205
  * // Output: { valid: true }
208
- *
206
+ *
209
207
  * @example
210
208
  * // Input: Missing required types array
211
209
  * const relDef = {
@@ -216,11 +214,11 @@ export function validateRelationships({ context, scopes }) {
216
214
  * }
217
215
  * };
218
216
  * validatePolymorphicRelationship(relDef, 'comments', scopes);
219
- * // Output: {
220
- * // valid: false,
221
- * // error: 'belongsToPolymorphic.types must be a non-empty array'
217
+ * // Output: {
218
+ * // valid: false,
219
+ * // error: 'belongsToPolymorphic.types must be a non-empty array'
222
220
  * // }
223
- *
221
+ *
224
222
  * @example
225
223
  * // Input: References non-existent scope
226
224
  * const relDef = {
@@ -231,11 +229,11 @@ export function validateRelationships({ context, scopes }) {
231
229
  * }
232
230
  * };
233
231
  * validatePolymorphicRelationship(relDef, 'attachments', scopes);
234
- * // Output: {
235
- * // valid: false,
236
- * // error: "Polymorphic type 'unicorns' is not a registered scope"
232
+ * // Output: {
233
+ * // valid: false,
234
+ * // error: "Polymorphic type 'unicorns' is not a registered scope"
237
235
  * // }
238
- *
236
+ *
239
237
  * @private
240
238
  */
241
239
  const validatePolymorphicRelationship = (relDef, scopeName, scopes) => {
@@ -245,57 +243,57 @@ const validatePolymorphicRelationship = (relDef, scopeName, scopes) => {
245
243
  // 3. Ensure types is non-empty array
246
244
  // 4. Verify all types are registered scopes
247
245
  // 5. Check that typeField and idField exist in the schema
248
-
249
- const { belongsToPolymorphic } = relDef;
250
-
246
+
247
+ const { belongsToPolymorphic } = relDef
248
+
251
249
  if (!belongsToPolymorphic) {
252
- return { valid: false, error: 'Missing belongsToPolymorphic definition' };
250
+ return { valid: false, error: 'Missing belongsToPolymorphic definition' }
253
251
  }
254
-
255
- const { types, typeField, idField } = belongsToPolymorphic;
256
-
252
+
253
+ const { types, typeField, idField } = belongsToPolymorphic
254
+
257
255
  if (!types || !Array.isArray(types) || types.length === 0) {
258
- return {
259
- valid: false,
260
- error: 'belongsToPolymorphic.types must be a non-empty array'
261
- };
256
+ return {
257
+ valid: false,
258
+ error: 'belongsToPolymorphic.types must be a non-empty array'
259
+ }
262
260
  }
263
-
261
+
264
262
  if (!typeField || typeof typeField !== 'string') {
265
- return {
266
- valid: false,
267
- error: 'belongsToPolymorphic.typeField must be specified'
268
- };
263
+ return {
264
+ valid: false,
265
+ error: 'belongsToPolymorphic.typeField must be specified'
266
+ }
269
267
  }
270
-
268
+
271
269
  if (!idField || typeof idField !== 'string') {
272
- return {
273
- valid: false,
274
- error: 'belongsToPolymorphic.idField must be specified'
275
- };
270
+ return {
271
+ valid: false,
272
+ error: 'belongsToPolymorphic.idField must be specified'
273
+ }
276
274
  }
277
-
275
+
278
276
  // Check that all types are valid scopes
279
277
  for (const type of types) {
280
278
  if (!scopes[type]) {
281
- return {
282
- valid: false,
283
- error: `Polymorphic type '${type}' is not a registered scope`
284
- };
279
+ return {
280
+ valid: false,
281
+ error: `Polymorphic type '${type}' is not a registered scope`
282
+ }
285
283
  }
286
284
  }
287
-
288
- return { valid: true };
289
- };
285
+
286
+ return { valid: true }
287
+ }
290
288
 
291
289
  /**
292
290
  * Validates a hasMany relationship definition
293
- *
291
+ *
294
292
  * @param {Object} relDef - Relationship definition with hasMany
295
293
  * @param {string} relName - Relationship name
296
294
  * @param {string} scopeName - Scope being registered
297
295
  * @returns {Object} Validation result {valid: boolean, error?: string}
298
- *
296
+ *
299
297
  * @example
300
298
  * // Input: Valid hasMany configuration
301
299
  * const relDef = {
@@ -305,7 +303,7 @@ const validatePolymorphicRelationship = (relDef, scopeName, scopes) => {
305
303
  * };
306
304
  * validateHasManyRelationship(relDef, 'posts', 'users');
307
305
  * // Output: { valid: true }
308
- *
306
+ *
309
307
  * @example
310
308
  * // Input: Missing required foreignKey
311
309
  * const relDef = {
@@ -314,11 +312,11 @@ const validatePolymorphicRelationship = (relDef, scopeName, scopes) => {
314
312
  * // Missing: foreignKey
315
313
  * };
316
314
  * validateHasManyRelationship(relDef, 'posts', 'users');
317
- * // Output: {
318
- * // valid: false,
319
- * // error: 'hasMany relationship requires foreignKey to be specified...'
315
+ * // Output: {
316
+ * // valid: false,
317
+ * // error: 'hasMany relationship requires foreignKey to be specified...'
320
318
  * // }
321
- *
319
+ *
322
320
  * @example
323
321
  * // Input: Polymorphic hasMany with 'via' (doesn't need foreignKey)
324
322
  * const relDef = {
@@ -328,49 +326,49 @@ const validatePolymorphicRelationship = (relDef, scopeName, scopes) => {
328
326
  * };
329
327
  * validateHasManyRelationship(relDef, 'comments', 'posts');
330
328
  * // Output: { valid: true }
331
- *
329
+ *
332
330
  * @private
333
331
  */
334
332
  const validateHasManyRelationship = (relDef, relName, scopeName) => {
335
333
  // Validate target is specified
336
334
  if (!relDef.target) {
337
- return {
338
- valid: false,
339
- error: `hasMany relationship requires 'target' to be specified.`
340
- };
335
+ return {
336
+ valid: false,
337
+ error: 'hasMany relationship requires \'target\' to be specified.'
338
+ }
341
339
  }
342
-
340
+
343
341
  // Polymorphic hasMany relationships using 'via' don't need foreignKey
344
342
  // They use the polymorphic fields (typeField, idField) from the belongsToPolymorphic relationship
345
343
  if (relDef.via) {
346
- return { valid: true };
344
+ return { valid: true }
347
345
  }
348
-
346
+
349
347
  if (!relDef.foreignKey) {
350
- return {
351
- valid: false,
352
- error: `hasMany relationship requires foreignKey to be specified. Add foreignKey: '<field_name>' to the relationship definition.`
353
- };
348
+ return {
349
+ valid: false,
350
+ error: 'hasMany relationship requires foreignKey to be specified. Add foreignKey: \'<field_name>\' to the relationship definition.'
351
+ }
354
352
  }
355
-
353
+
356
354
  if (typeof relDef.foreignKey !== 'string') {
357
- return {
358
- valid: false,
355
+ return {
356
+ valid: false,
359
357
  error: `hasMany relationship foreignKey must be a string, got ${typeof relDef.foreignKey}`
360
- };
358
+ }
361
359
  }
362
-
363
- return { valid: true };
364
- };
360
+
361
+ return { valid: true }
362
+ }
365
363
 
366
364
  /**
367
365
  * Validates a hasOne relationship definition
368
- *
366
+ *
369
367
  * @param {Object} relDef - Relationship definition with hasOne
370
368
  * @param {string} relName - Relationship name
371
369
  * @param {string} scopeName - Scope being registered
372
370
  * @returns {Object} Validation result {valid: boolean, error?: string}
373
- *
371
+ *
374
372
  * @example
375
373
  * // Input: Valid hasOne configuration
376
374
  * const relDef = {
@@ -380,43 +378,43 @@ const validateHasManyRelationship = (relDef, relName, scopeName) => {
380
378
  * };
381
379
  * validateHasOneRelationship(relDef, 'profile', 'users');
382
380
  * // Output: { valid: true }
383
- *
381
+ *
384
382
  * @private
385
383
  */
386
384
  const validateHasOneRelationship = (relDef, relName, scopeName) => {
387
385
  // Validate target is specified
388
386
  if (!relDef.target) {
389
- return {
390
- valid: false,
391
- error: `hasOne relationship requires 'target' to be specified.`
392
- };
387
+ return {
388
+ valid: false,
389
+ error: 'hasOne relationship requires \'target\' to be specified.'
390
+ }
393
391
  }
394
-
392
+
395
393
  if (!relDef.foreignKey) {
396
- return {
397
- valid: false,
398
- error: `hasOne relationship requires foreignKey to be specified. Add foreignKey: '<field_name>' to the relationship definition.`
399
- };
394
+ return {
395
+ valid: false,
396
+ error: 'hasOne relationship requires foreignKey to be specified. Add foreignKey: \'<field_name>\' to the relationship definition.'
397
+ }
400
398
  }
401
-
399
+
402
400
  if (typeof relDef.foreignKey !== 'string') {
403
- return {
404
- valid: false,
401
+ return {
402
+ valid: false,
405
403
  error: `hasOne relationship foreignKey must be a string, got ${typeof relDef.foreignKey}`
406
- };
404
+ }
407
405
  }
408
-
409
- return { valid: true };
410
- };
406
+
407
+ return { valid: true }
408
+ }
411
409
 
412
410
  /**
413
411
  * Validates a manyToMany relationship definition
414
- *
412
+ *
415
413
  * @param {Object} relDef - Relationship definition with manyToMany
416
414
  * @param {string} relName - Relationship name
417
415
  * @param {string} scopeName - Scope being registered
418
416
  * @returns {Object} Validation result {valid: boolean, error?: string}
419
- *
417
+ *
420
418
  * @example
421
419
  * // Input: Valid manyToMany configuration
422
420
  * const relDef = {
@@ -427,7 +425,7 @@ const validateHasOneRelationship = (relDef, relName, scopeName) => {
427
425
  * };
428
426
  * validateManyToManyRelationship(relDef, 'tags', 'articles');
429
427
  * // Output: { valid: true }
430
- *
428
+ *
431
429
  * @example
432
430
  * // Input: Missing required fields
433
431
  * const relDef = {
@@ -437,51 +435,50 @@ const validateHasOneRelationship = (relDef, relName, scopeName) => {
437
435
  * // Missing: otherKey
438
436
  * };
439
437
  * validateManyToManyRelationship(relDef, 'tags', 'articles');
440
- * // Output: {
441
- * // valid: false,
442
- * // error: 'manyToMany relationship requires otherKey to be specified...'
438
+ * // Output: {
439
+ * // valid: false,
440
+ * // error: 'manyToMany relationship requires otherKey to be specified...'
443
441
  * // }
444
- *
442
+ *
445
443
  * @private
446
444
  */
447
445
  const validateManyToManyRelationship = (relDef, relName, scopeName) => {
448
- const { through, foreignKey, otherKey } = relDef;
449
-
446
+ const { through, foreignKey, otherKey } = relDef
447
+
450
448
  if (!through) {
451
- return {
452
- valid: false,
453
- error: `manyToMany relationship requires 'through' table to be specified`
454
- };
449
+ return {
450
+ valid: false,
451
+ error: 'manyToMany relationship requires \'through\' table to be specified'
452
+ }
455
453
  }
456
-
454
+
457
455
  if (!foreignKey) {
458
- return {
459
- valid: false,
460
- error: `manyToMany relationship requires foreignKey to be specified. Add foreignKey: '<field_name>' to the manyToMany configuration.`
461
- };
456
+ return {
457
+ valid: false,
458
+ error: 'manyToMany relationship requires foreignKey to be specified. Add foreignKey: \'<field_name>\' to the manyToMany configuration.'
459
+ }
462
460
  }
463
-
461
+
464
462
  if (!otherKey) {
465
- return {
466
- valid: false,
467
- error: `manyToMany relationship requires otherKey to be specified. Add otherKey: '<field_name>' to the manyToMany configuration.`
468
- };
463
+ return {
464
+ valid: false,
465
+ error: 'manyToMany relationship requires otherKey to be specified. Add otherKey: \'<field_name>\' to the manyToMany configuration.'
466
+ }
469
467
  }
470
-
468
+
471
469
  if (typeof foreignKey !== 'string') {
472
- return {
473
- valid: false,
470
+ return {
471
+ valid: false,
474
472
  error: `manyToMany relationship foreignKey must be a string, got ${typeof foreignKey}`
475
- };
473
+ }
476
474
  }
477
-
475
+
478
476
  if (typeof otherKey !== 'string') {
479
- return {
480
- valid: false,
477
+ return {
478
+ valid: false,
481
479
  error: `manyToMany relationship otherKey must be a string, got ${typeof otherKey}`
482
- };
480
+ }
483
481
  }
484
-
485
- return { valid: true };
486
- };
487
482
 
483
+ return { valid: true }
484
+ }