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.
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 +11 -2
  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 +1 -1
  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 +99 -99
  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 +11 -15
  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,62 +1,61 @@
1
-
2
- import { RestApiResourceError, RestApiValidationError, RestApiPayloadError } from "../../../lib/rest-api-errors.js";
3
- import { findRelationshipDefinition, handleWriteMethodError } from "./common.js";
1
+ import { RestApiResourceError, RestApiValidationError, RestApiPayloadError } from '../../../lib/rest-api-errors.js'
2
+ import { findRelationshipDefinition, handleWriteMethodError } from './common.js'
4
3
 
5
4
  /**
6
5
  * DELETE RELATIONSHIP
7
6
  * Removes specific members from a to-many relationship
8
7
  * DELETE /api/articles/1/relationships/tags
9
- *
8
+ *
10
9
  * @param {string} id - The ID of the resource
11
10
  * @param {string} relationshipName - The name of the relationship
12
11
  * @param {array} relationshipData - Array of resource identifiers to remove
13
12
  * @returns {Promise<void>} 204 No Content
14
13
  */
15
- export default async function deleteRelationshipMethod({ params, context, vars, helpers, scope, scopes, runHooks, scopeName, api, log }) {
16
- context.method = 'deleteRelationship';
17
- context.id = params.id;
18
- context.relationshipName = params.relationshipName;
19
- context.schemaInfo = scopes[scopeName].vars.schemaInfo;
14
+ export default async function deleteRelationshipMethod ({ params, context, vars, helpers, scope, scopes, runHooks, scopeName, api, log }) {
15
+ context.method = 'deleteRelationship'
16
+ context.id = params.id
17
+ context.relationshipName = params.relationshipName
18
+ context.schemaInfo = scopes[scopeName].vars.schemaInfo
20
19
 
21
20
  // Transaction handling
22
- context.transaction = params.transaction ||
23
- (helpers.newTransaction && !params.transaction ? await helpers.newTransaction() : null);
24
- context.shouldCommit = !params.transaction && !!context.transaction;
21
+ context.transaction = params.transaction ||
22
+ (helpers.newTransaction && !params.transaction ? await helpers.newTransaction() : null)
23
+ context.shouldCommit = !params.transaction && !!context.transaction
25
24
  context.db = context.transaction || api.knex.instance
26
25
 
27
26
  try {
28
27
  // Validate
29
- const relDef = findRelationshipDefinition(context.schemaInfo, context.relationshipName);
28
+ const relDef = findRelationshipDefinition(context.schemaInfo, context.relationshipName)
30
29
  if (!relDef) {
31
30
  throw new RestApiResourceError(
32
31
  `Relationship '${context.relationshipName}' not found on resource '${scopeName}'`,
33
32
  { subtype: 'relationship_not_found' }
34
- );
33
+ )
35
34
  }
36
35
 
37
36
  if (relDef.type !== 'hasMany' && relDef.type !== 'manyToMany') {
38
37
  throw new RestApiValidationError(
39
38
  `Cannot DELETE from to-one relationship '${context.relationshipName}'`,
40
39
  { fields: ['data'] }
41
- );
40
+ )
42
41
  }
43
42
 
44
43
  if (!Array.isArray(params.relationshipData)) {
45
- throw new RestApiPayloadError('DELETE from relationship requires array of resource identifiers');
44
+ throw new RestApiPayloadError('DELETE from relationship requires array of resource identifiers')
46
45
  }
47
46
 
48
47
  // Check permissions
49
- await runHooks('checkPermissions');
50
- await runHooks('checkPermissionsDeleteRelationship');
48
+ await runHooks('checkPermissions')
49
+ await runHooks('checkPermissionsDeleteRelationship')
51
50
 
52
51
  // Verify parent exists
53
52
  const exists = await helpers.dataExists({
54
53
  scopeName,
55
- context: { db: context.db, id: context.id, schemaInfo: context.schemaInfo }
56
- });
54
+ context: { db: context.db, id: context.id, schemaInfo: context.schemaInfo }
55
+ })
57
56
 
58
57
  if (!exists) {
59
- throw new RestApiResourceError('Resource not found', { subtype: 'not_found' });
58
+ throw new RestApiResourceError('Resource not found', { subtype: 'not_found' })
60
59
  }
61
60
 
62
61
  // Remove relationships
@@ -68,26 +67,26 @@ export default async function deleteRelationshipMethod({ params, context, vars,
68
67
  relName: context.relationshipName,
69
68
  relDef,
70
69
  relData: params.relationshipData,
71
- });
70
+ })
72
71
  } else {
73
- const knex = api.knex?.instance || helpers.db;
74
- const pivotResource = relDef.through;
75
- const pivotScope = api.resources[pivotResource];
76
- const pivotTable = pivotScope?.vars?.schemaInfo?.tableName || pivotResource;
77
- const localKey = relDef.foreignKey;
78
- const foreignKey = relDef.otherKey;
72
+ const knex = api.knex?.instance || helpers.db
73
+ const pivotResource = relDef.through
74
+ const pivotScope = api.resources[pivotResource]
75
+ const pivotTable = pivotScope?.vars?.schemaInfo?.tableName || pivotResource
76
+ const localKey = relDef.foreignKey
77
+ const foreignKey = relDef.otherKey
79
78
 
80
79
  for (const identifier of params.relationshipData) {
81
80
  await knex(pivotTable)
82
81
  .where(localKey, context.id)
83
82
  .where(foreignKey, identifier.id)
84
83
  .delete()
85
- .transacting(context.transaction);
84
+ .transacting(context.transaction)
86
85
  }
87
86
  }
88
87
  } else {
89
88
  // Null out foreign keys for hasMany
90
- const targetType = relDef.target;
89
+ const targetType = relDef.target
91
90
  for (const identifier of params.relationshipData) {
92
91
  await api.resources[targetType].patch({
93
92
  id: identifier.id,
@@ -100,20 +99,19 @@ export default async function deleteRelationshipMethod({ params, context, vars,
100
99
  },
101
100
  transaction: context.transaction,
102
101
  simplified: false
103
- });
102
+ })
104
103
  }
105
104
  }
106
105
 
107
- await runHooks('finish');
108
- await runHooks('finishDeleteRelationship');
106
+ await runHooks('finish')
107
+ await runHooks('finishDeleteRelationship')
109
108
 
110
109
  if (context.shouldCommit) {
111
- await context.transaction.commit();
110
+ await context.transaction.commit()
112
111
  }
113
112
 
114
- return; // 204 No Content
115
-
113
+ // 204 No Content
116
114
  } catch (error) {
117
- await handleWriteMethodError(error, context, 'DELETE_RELATIONSHIP', scopeName, log, runHooks);
115
+ await handleWriteMethodError(error, context, 'DELETE_RELATIONSHIP', scopeName, log, runHooks)
118
116
  }
119
117
  }
@@ -1,5 +1,5 @@
1
- import { RestApiResourceError } from '../../../lib/rest-api-errors.js';
2
- import { handleWriteMethodError } from './common.js';
1
+ import { RestApiResourceError } from '../../../lib/rest-api-errors.js'
2
+ import { handleWriteMethodError } from './common.js'
3
3
 
4
4
  /**
5
5
  * DELETE
@@ -7,100 +7,98 @@ import { handleWriteMethodError } from './common.js';
7
7
  * Returns 204 No Content on success, indicating the resource has been removed.
8
8
  * This method does not return the deleted resource.
9
9
  */
10
- export default async function deleteMethod({
11
- params,
12
- context,
13
- vars,
14
- helpers,
15
- scope,
16
- scopes,
17
- runHooks,
18
- apiOptions,
19
- pluginOptions,
20
- scopeOptions,
10
+ export default async function deleteMethod ({
11
+ params,
12
+ context,
13
+ vars,
14
+ helpers,
15
+ scope,
16
+ scopes,
17
+ runHooks,
18
+ apiOptions,
19
+ pluginOptions,
20
+ scopeOptions,
21
21
  scopeName,
22
22
  api,
23
23
  log
24
24
  }) {
25
25
  // Make the method available to all hooks
26
- context.method = 'delete';
27
-
26
+ context.method = 'delete'
27
+
28
28
  // Set the ID in context
29
- context.id = params.id;
30
-
29
+ context.id = params.id
30
+
31
31
  // Set scopeName in context (needed for broadcasting)
32
- context.scopeName = scopeName;
33
-
32
+ context.scopeName = scopeName
33
+
34
34
  // Set schema info even for DELETE (needed by storage layer)
35
- context.schemaInfo = scopes[scopeName].vars.schemaInfo;
36
-
35
+ context.schemaInfo = scopes[scopeName].vars.schemaInfo
36
+
37
37
  // Transaction handling
38
- context.transaction = params.transaction ||
39
- (helpers.newTransaction && !params.transaction ? await helpers.newTransaction() : null);
40
- context.shouldCommit = !params.transaction && !!context.transaction;
41
- context.db = context.transaction || api.knex.instance;
42
-
38
+ context.transaction = params.transaction ||
39
+ (helpers.newTransaction && !params.transaction ? await helpers.newTransaction() : null)
40
+ context.shouldCommit = !params.transaction && !!context.transaction
41
+ context.db = context.transaction || api.knex.instance
42
+
43
43
  try {
44
44
  // No payload validation needed for DELETE
45
-
45
+
46
46
  // Fetch minimal record for authorization and logging
47
47
  const minimalRecord = await helpers.dataGetMinimal({
48
48
  scopeName,
49
49
  context,
50
50
  runHooks
51
- });
52
-
51
+ })
52
+
53
53
  if (!minimalRecord) {
54
54
  throw new RestApiResourceError(
55
- `Resource not found`,
56
- {
55
+ 'Resource not found',
56
+ {
57
57
  subtype: 'not_found',
58
58
  resourceType: scopeName,
59
59
  resourceId: context.id
60
60
  }
61
- );
61
+ )
62
62
  }
63
-
64
- context.originalMinimalRecord = minimalRecord;
65
- context.minimalRecord = minimalRecord;
66
-
63
+
64
+ context.originalMinimalRecord = minimalRecord
65
+ context.minimalRecord = minimalRecord
66
+
67
67
  // Centralised checkPermissions function
68
68
  await scope.checkPermissions({
69
69
  method: 'delete',
70
70
  originalContext: context,
71
- });
72
-
71
+ })
72
+
73
73
  // Before data operations
74
- await runHooks('beforeDataCall');
75
- await runHooks('beforeDataCallDelete');
76
-
74
+ await runHooks('beforeDataCall')
75
+ await runHooks('beforeDataCallDelete')
76
+
77
77
  // Initialize record context for hooks
78
- context.record = {};
79
-
78
+ context.record = {}
79
+
80
80
  // Call the storage helper
81
81
  await helpers.dataDelete({
82
82
  scopeName,
83
83
  context
84
- });
85
-
86
- await runHooks('afterDataCallDelete');
87
- await runHooks('afterDataCall');
88
-
84
+ })
85
+
86
+ await runHooks('afterDataCallDelete')
87
+ await runHooks('afterDataCall')
88
+
89
89
  // No return record for DELETE (204 No Content)
90
-
91
- await runHooks('finish');
92
- await runHooks('finishDelete');
93
-
90
+
91
+ await runHooks('finish')
92
+ await runHooks('finishDelete')
93
+
94
94
  // Commit transaction if we created it
95
95
  if (context.shouldCommit) {
96
- await context.transaction.commit();
97
- await runHooks('afterCommit');
96
+ await context.transaction.commit()
97
+ await runHooks('afterCommit')
98
98
  }
99
-
99
+
100
100
  // DELETE typically returns void/undefined (204 No Content)
101
- return;
102
-
103
101
  } catch (error) {
104
- await handleWriteMethodError(error, context, 'DELETE', scopeName, log, runHooks);
102
+ await handleWriteMethodError(error, context, 'DELETE', scopeName, log, runHooks)
105
103
  }
106
- }
104
+ }