json-rest-api 1.0.6 → 1.0.8

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 (146) hide show
  1. package/.claude/agents/library-guide-expert.md +29 -0
  2. package/.claude/agents/rest-api-internals-expert.md +53 -0
  3. package/CLAUDE.md +139 -1
  4. package/README.md +2 -5
  5. package/docTest.js +238 -0
  6. package/docs/GUIDE/GUIDE_1_Initial_Setup.md +955 -0
  7. package/docs/GUIDE/GUIDE_2_1_The_Starting_Point.md +54 -0
  8. package/docs/GUIDE/GUIDE_2_2_Manipulating_And_Searching_Tables.md +750 -0
  9. package/docs/GUIDE/GUIDE_2_3_BelongsTo_Relationships.md +494 -0
  10. package/docs/GUIDE/GUIDE_2_4_HasMany_Records.md +398 -0
  11. package/docs/GUIDE/GUIDE_2_5_HasMany_Polymorphic.md +882 -0
  12. package/docs/GUIDE/GUIDE_2_6_Many_To_Many.md +709 -0
  13. package/docs/GUIDE/GUIDE_2_7_Pagination_And_Ordering.md +1233 -0
  14. package/docs/GUIDE/GUIDE_2_8_Effects_of_PUT_and_PATCH.md +796 -0
  15. package/{README_X_Relationship_Plugin.md → docs/GUIDE/GUIDE_2_9_Relationships_Urls.md} +1 -4
  16. package/docs/GUIDE/GUIDE_2_Data_And_Relations.md +66 -0
  17. package/docs/GUIDE/GUIDE_3_Field_Transformations.md +1246 -0
  18. package/docs/GUIDE/GUIDE_5_Non-Db_Stores.md +0 -0
  19. package/docs/GUIDE/GUIDE_7_Hooks_Data_Management_And_Plugins.md +1490 -0
  20. package/{README_X_SocketIO.md → docs/GUIDE/GUIDE_X_SocketIO.md} +17 -17
  21. package/docs/GUIDE/index.md +58 -0
  22. package/docs/GUIDE.md +61 -2238
  23. package/docs/ONBOARDING/Computed_Properties_And_Sparse_Fields.md +398 -0
  24. package/docs/README.md +57 -2239
  25. package/{README_2_Computed_and_hidden_fields.md → docs/README_VARIOUS/GUIDE_2_Computed_and_hidden_fields.md} +22 -17
  26. package/docs/README_VARIOUS/GUIDE_IN_DOCS.md +2277 -0
  27. package/{README.ORIG.md → docs/README_VARIOUS/README.ORIG.md} +8 -8
  28. package/{README_8_Polymorphic_Relationships.md → docs/README_VARIOUS/README_8_Polymorphic_Relationships.md} +1 -1
  29. package/docs/README_VARIOUS/README_IN_DOCS.ms +2277 -0
  30. package/{RELATIONSHIPS_ADVANCED.md → docs/README_VARIOUS/RELATIONSHIPS_ADVANCED.md} +3 -3
  31. package/{correct-schema-format.md → docs/README_VARIOUS/correct-schema-format.md} +13 -13
  32. package/{pagination.md → docs/README_VARIOUS/pagination.md} +11 -8
  33. package/docs/assets/css/style.scss +78 -5
  34. package/docs/index.md +2 -12
  35. package/helper-reorganization-plan.md +85 -0
  36. package/helper-usage-analysis.md +94 -0
  37. package/package.json +5 -4
  38. package/plugins/core/bulk-operations-plugin.js +2 -2
  39. package/plugins/core/connectors/express-plugin.js +99 -33
  40. package/plugins/core/lib/querying/knex-cross-table-search.js +609 -0
  41. package/plugins/core/lib/querying/knex-json-api-transformers-querying.js +491 -0
  42. package/plugins/core/lib/querying/knex-pagination-helpers.js +544 -0
  43. package/plugins/core/lib/{knex-process-includes.js → querying/knex-process-includes.js} +65 -50
  44. package/plugins/core/lib/querying/knex-query-helpers-base.js +74 -0
  45. package/plugins/core/lib/{knex-query-helpers.js → querying/knex-query-helpers.js} +416 -180
  46. package/plugins/core/lib/{knex-relationship-includes.js → querying/knex-relationship-includes.js} +430 -114
  47. package/plugins/core/lib/querying/knex-window-queries.js +328 -0
  48. package/plugins/core/lib/querying-writing/compile-schemas.js +328 -0
  49. package/plugins/core/{utils → lib/querying-writing}/connectors-query-parser.js +62 -57
  50. package/plugins/core/lib/{database-capabilities.js → querying-writing/database-capabilities.js} +113 -7
  51. package/plugins/core/lib/querying-writing/database-value-normalizers.js +369 -0
  52. package/plugins/core/lib/querying-writing/default-data-helpers.js +72 -0
  53. package/plugins/core/{utils → lib/querying-writing}/field-utils.js +41 -31
  54. package/plugins/core/{utils → lib/querying-writing}/knex-constants.js +1 -0
  55. package/plugins/core/lib/{knex-field-helpers.js → querying-writing/knex-field-helpers.js} +190 -57
  56. package/plugins/core/lib/querying-writing/knex-json-api-transformers.js +162 -0
  57. package/plugins/core/lib/{payload-validators.js → querying-writing/payload-validators.js} +297 -217
  58. package/plugins/core/lib/querying-writing/schema-helpers.js +497 -0
  59. package/plugins/core/lib/querying-writing/scope-validations.js +431 -0
  60. package/plugins/core/lib/{simplified-helpers.js → querying-writing/simplified-helpers.js} +216 -176
  61. package/plugins/core/lib/writing/knex-json-api-transformers-writing.js +110 -0
  62. package/plugins/core/lib/writing/many-to-many-manipulations.js +300 -0
  63. package/plugins/core/lib/writing/relationship-processor.js +252 -0
  64. package/plugins/core/rest-api-knex-plugin.js +183 -62
  65. package/plugins/core/rest-api-plugin-hooks/compile-resource-schemas.js +7 -0
  66. package/plugins/core/rest-api-plugin-hooks/register-relationship-routes.js +72 -0
  67. package/plugins/core/rest-api-plugin-hooks/register-scope-routes.js +102 -0
  68. package/plugins/core/rest-api-plugin-hooks/turn-scope-init-into-vars.js +50 -0
  69. package/plugins/core/rest-api-plugin-hooks/validate-include-configurations.js +39 -0
  70. package/plugins/core/rest-api-plugin-methods/add-route.js +23 -0
  71. package/plugins/core/rest-api-plugin-methods/check-permissions.js +18 -0
  72. package/plugins/core/rest-api-plugin-methods/common.js +605 -0
  73. package/plugins/core/rest-api-plugin-methods/delete-relationship.js +115 -0
  74. package/plugins/core/rest-api-plugin-methods/delete.js +109 -0
  75. package/plugins/core/rest-api-plugin-methods/enrich-attributes.js +186 -0
  76. package/plugins/core/rest-api-plugin-methods/get-related.js +295 -0
  77. package/plugins/core/rest-api-plugin-methods/get-relationship.js +62 -0
  78. package/plugins/core/rest-api-plugin-methods/get.js +187 -0
  79. package/plugins/core/rest-api-plugin-methods/patch-relationship.js +56 -0
  80. package/plugins/core/rest-api-plugin-methods/patch.js +193 -0
  81. package/plugins/core/rest-api-plugin-methods/post-relationship.js +104 -0
  82. package/plugins/core/rest-api-plugin-methods/post.js +157 -0
  83. package/plugins/core/rest-api-plugin-methods/put.js +257 -0
  84. package/plugins/core/rest-api-plugin-methods/query.js +208 -0
  85. package/plugins/core/rest-api-plugin.js +108 -2498
  86. package/plugins/core/socketio-plugin.js +28 -5
  87. package/plugins/storage/local-storage.js +2 -2
  88. package/tests/computed-fields.test.js +483 -0
  89. package/tests/cors.test.js +4 -4
  90. package/tests/curl.test.js +5 -4
  91. package/tests/custom-idproperty-relationships.test.js +891 -0
  92. package/tests/field-getters.test.js +353 -0
  93. package/tests/field-setters.test.js +310 -0
  94. package/tests/fixtures/api-configs.js +800 -28
  95. package/tests/jwt-auth.test.js +0 -2
  96. package/tests/nested-includes.test.js +1 -1
  97. package/tests/pagination-cursor-multifield.test.js +514 -0
  98. package/tests/pagination-enhanced.test.js +12 -9
  99. package/tests/polymorphic-relationships.test.js +10 -8
  100. package/tests/polymorphic-simple.test.js +6 -4
  101. package/tests/positioning-advanced.test.js +12 -12
  102. package/tests/positioning-extended.test.js +25 -25
  103. package/tests/positioning-multifilter.test.js +24 -24
  104. package/tests/positioning.test.js +3 -3
  105. package/tests/query-limits.test.js +24 -8
  106. package/tests/relationship-endpoints.test.js +4 -5
  107. package/tests/relationships.test.js +0 -1
  108. package/tests/socketio.test.js +12 -1
  109. package/tests/virtual-fields.test.js +13 -13
  110. package/PLAN_FOR_WEBSOCKETS.md +0 -398
  111. package/README_1_Initial_Setup.md +0 -393
  112. package/README_X_Hooks.md +0 -647
  113. package/TODO_rest-api-plugin-extras.todo +0 -23
  114. package/connectors_ideas/express-plugin.js +0 -120
  115. package/connectors_ideas/http-plugin.js +0 -138
  116. package/docs/examples/express-plugin.js +0 -366
  117. package/example.js +0 -301
  118. package/plugins/core/HELPER_MODULES.md +0 -285
  119. package/plugins/core/lib/compile-schemas.js +0 -245
  120. package/plugins/core/lib/database-value-normalizers.js +0 -192
  121. package/plugins/core/lib/default-data-helpers.js +0 -100
  122. package/plugins/core/lib/knex-cross-table-search.js +0 -442
  123. package/plugins/core/lib/knex-json-api-helpers.js +0 -84
  124. package/plugins/core/lib/knex-json-api-transformers.js +0 -449
  125. package/plugins/core/lib/knex-pagination-helpers.js +0 -193
  126. package/plugins/core/lib/knex-window-queries.js +0 -142
  127. package/plugins/core/lib/many-to-many-manipulations.js +0 -343
  128. package/plugins/core/lib/relationship-processor.js +0 -278
  129. package/plugins/core/lib/schema-helpers.js +0 -343
  130. package/plugins/core/lib/scope-validations.js +0 -252
  131. package/plugins/core/rest-api-relationships-plugin.js +0 -700
  132. package/plugins/core/utils/knex-query-helpers-base.js +0 -56
  133. /package/{README_X_Permissions.md → docs/GUIDE/GUIDE_4_Authentication_And_Permissions.md} +0 -0
  134. /package/{README_X_Positioning.md → docs/GUIDE/GUIDE_6_Positioning.md} +0 -0
  135. /package/{README_X_Bulk_Operations.md → docs/GUIDE/GUIDE_X_Bulk_Operations.md} +0 -0
  136. /package/{README_X_Cors.md → docs/GUIDE/GUIDE_X_Cors.md} +0 -0
  137. /package/{README_X_Multihome.md → docs/GUIDE/GUIDE_X_Multihome.md} +0 -0
  138. /package/{README_X_Appendices.md → docs/GUIDE/GUIDE_Y_Appendices.md} +0 -0
  139. /package/{QUERY_DEPTH_PROTECTION.md → docs/README_VARIOUS/QUERY_DEPTH_PROTECTION.md} +0 -0
  140. /package/{RELATIONSHIPS.md → docs/README_VARIOUS/RELATIONSHIPS.md} +0 -0
  141. /package/{WEBSOCKET_IMPLEMENTATION_STATUS.md → docs/README_VARIOUS/WEBSOCKET_IMPLEMENTATION_STATUS.md} +0 -0
  142. /package/{helper-functions-chart.md → docs/README_VARIOUS/helper-functions-chart.md} +0 -0
  143. /package/docs/{implementation-hidden-computed-fields.md → README_VARIOUS/implementation-hidden-computed-fields.md} +0 -0
  144. /package/docs/{include-limits-migration-guide.md → README_VARIOUS/include-limits-migration-guide.md} +0 -0
  145. /package/{readmeSnippets → docs/README_VARIOUS}/test_put_behavior.js +0 -0
  146. /package/{readmeSnippets → docs/README_VARIOUS}/test_put_fields_without_defaults.js +0 -0
@@ -223,13 +223,13 @@ api.addResource('users', {
223
223
  ```javascript
224
224
  searchSchema: {
225
225
  // Simple field search
226
- title: { type: 'string', filterUsing: 'like' },
226
+ title: { type: 'string', filterOperator: 'like' },
227
227
 
228
228
  // Cross-table search
229
229
  authorName: {
230
230
  type: 'string',
231
231
  actualField: 'users.name', // Table.field notation
232
- filterUsing: 'like'
232
+ filterOperator: 'like'
233
233
  },
234
234
 
235
235
  // Multi-field search
@@ -254,7 +254,7 @@ searchSchema: {
254
254
  searchSchema: {
255
255
  trackableTitle: {
256
256
  type: 'string',
257
- filterUsing: 'like',
257
+ filterOperator: 'like',
258
258
  polymorphicField: 'trackable', // References relationship name
259
259
  targetFields: {
260
260
  articles: 'title', // When type=articles, search title
@@ -6,7 +6,7 @@ The format you're using with `indexed: true` is not recognized by the REST API p
6
6
  ```javascript
7
7
  // INCORRECT - This won't work for filtering
8
8
  {
9
- title: { type: 'string', indexed: true, search: { filterUsing: 'like' } },
9
+ title: { type: 'string', indexed: true, search: { filterOperator: 'like' } },
10
10
  status: { type: 'string', indexed: true, search: true }
11
11
  }
12
12
  ```
@@ -43,13 +43,13 @@ For partial string matching:
43
43
  title: {
44
44
  type: 'string',
45
45
  search: {
46
- filterUsing: 'like' // Enables LIKE filtering
46
+ filterOperator: 'like' // Enables LIKE filtering
47
47
  }
48
48
  },
49
49
  body: {
50
50
  type: 'string',
51
51
  search: {
52
- filterUsing: 'like'
52
+ filterOperator: 'like'
53
53
  }
54
54
  }
55
55
  }
@@ -67,10 +67,10 @@ For creating multiple filter parameters from a single field:
67
67
  type: 'datetime',
68
68
  search: {
69
69
  published_after: {
70
- filterUsing: '>='
70
+ filterOperator: '>='
71
71
  },
72
72
  published_before: {
73
- filterUsing: '<='
73
+ filterOperator: '<='
74
74
  }
75
75
  }
76
76
  }
@@ -119,7 +119,7 @@ api.addResource('products', {
119
119
  searchSchema: {
120
120
  name: {
121
121
  type: 'string',
122
- filterUsing: 'like'
122
+ filterOperator: 'like'
123
123
  },
124
124
  category: {
125
125
  type: 'string' // Exact match
@@ -127,12 +127,12 @@ api.addResource('products', {
127
127
  price_min: {
128
128
  type: 'number',
129
129
  actualField: 'price',
130
- filterUsing: '>='
130
+ filterOperator: '>='
131
131
  },
132
132
  price_max: {
133
133
  type: 'number',
134
134
  actualField: 'price',
135
- filterUsing: '<='
135
+ filterOperator: '<='
136
136
  }
137
137
  }
138
138
  });
@@ -151,7 +151,7 @@ const articlesSchema = {
151
151
  type: 'string',
152
152
  required: true,
153
153
  search: {
154
- filterUsing: 'like' // Enables contains/LIKE search
154
+ filterOperator: 'like' // Enables contains/LIKE search
155
155
  }
156
156
  },
157
157
 
@@ -173,10 +173,10 @@ const articlesSchema = {
173
173
  type: 'datetime',
174
174
  search: {
175
175
  created_after: {
176
- filterUsing: '>='
176
+ filterOperator: '>='
177
177
  },
178
178
  created_before: {
179
- filterUsing: '<='
179
+ filterOperator: '<='
180
180
  }
181
181
  }
182
182
  },
@@ -199,8 +199,8 @@ api.addResource('articles', {
199
199
 
200
200
  1. **Remove `indexed: true`** - This property is not used by the REST API plugin for filtering
201
201
  2. **Use `search: true`** for simple equality filters
202
- 3. **Use `search: { filterUsing: 'like' }`** for contains/partial matching
203
- 4. **Use `search: { field_name: { filterUsing: 'operator' } }`** for custom filter names
202
+ 3. **Use `search: { filterOperator: 'like' }`** for contains/partial matching
203
+ 4. **Use `search: { field_name: { filterOperator: 'operator' } }`** for custom filter names
204
204
  5. The filter validation happens in the `query` method of the REST API plugin
205
205
  6. If no `searchSchema` is provided, it's automatically generated from fields with the `search` property
206
206
 
@@ -165,31 +165,34 @@ const secondPage = await api.resources.books.query({
165
165
  "pageSize": 5,
166
166
  "hasMore": true,
167
167
  "cursor": {
168
- "next": "eyJpZCI6MTB9" // Base64 encoded cursor
168
+ "next": "id:10" // Simple cursor format
169
169
  }
170
170
  }
171
171
  },
172
172
  "links": {
173
173
  "self": "https://api.example.com/v1/books?page[size]=5&sort=-id",
174
174
  "first": "https://api.example.com/v1/books?page[size]=5&sort=-id",
175
- "next": "https://api.example.com/v1/books?page[size]=5&sort=-id&page[after]=eyJpZCI6MTB9"
175
+ "next": "https://api.example.com/v1/books?page[size]=5&sort=-id&page[after]=id:10"
176
176
  }
177
177
  }
178
178
  ```
179
179
 
180
180
  ### How Cursors Work
181
181
 
182
- Cursors are Base64-encoded JSON objects containing the sort field values of the last record:
182
+ Cursors use a simple format containing the sort field values of the last record:
183
183
 
184
184
  ```javascript
185
- // Cursor for record with id=10
186
- const cursor = "eyJpZCI6MTB9";
185
+ // Single field cursor (id=10)
186
+ const cursor = "id:10";
187
187
 
188
- // Decoded:
189
- // {"id": 10}
188
+ // Multi-field cursor (category='Fruit', name='Cherry')
189
+ const cursor = "category:Fruit,name:Cherry";
190
+
191
+ // With special characters (URL-encoded values)
192
+ const cursor = "title:Chapter%202%3A%20The%20Journey";
190
193
  ```
191
194
 
192
- This allows efficient pagination by using WHERE clauses instead of OFFSET.
195
+ This allows efficient pagination by using WHERE clauses instead of OFFSET. Values are URL-encoded to safely handle special characters like colons and commas.
193
196
 
194
197
  ## Pagination Metadata
195
198
 
@@ -180,13 +180,86 @@ pre code {
180
180
  line-height: 1.5;
181
181
  }
182
182
 
183
- .language-javascript .k { color: #569cd6; }
184
- .language-javascript .s { color: #ce9178; }
185
- .language-javascript .c { color: #6a9955; }
186
- .language-javascript .n { color: #9cdcfe; }
187
- .language-javascript .o { color: #d4d4d4; }
183
+ /* Rouge syntax highlighting - VS Code Dark+ theme */
184
+ .highlight .hll { background-color: #515151 }
185
+ .highlight { color: #d4d4d4; }
186
+ .highlight .c { color: #6a9955 } /* Comment */
187
+ .highlight .err { color: #f44747 } /* Error */
188
+ .highlight .k { color: #569cd6 } /* Keyword */
189
+ .highlight .l { color: #b5cea8 } /* Literal */
190
+ .highlight .n { color: #d4d4d4 } /* Name */
191
+ .highlight .o { color: #d4d4d4 } /* Operator */
192
+ .highlight .p { color: #d4d4d4 } /* Punctuation */
193
+ .highlight .cm { color: #6a9955 } /* Comment.Multiline */
194
+ .highlight .cp { color: #6a9955 } /* Comment.Preproc */
195
+ .highlight .c1 { color: #6a9955 } /* Comment.Single */
196
+ .highlight .cs { color: #6a9955 } /* Comment.Special */
197
+ .highlight .gd { color: #f44747 } /* Generic.Deleted */
198
+ .highlight .ge { font-style: italic } /* Generic.Emph */
199
+ .highlight .gh { color: #d4d4d4; font-weight: bold } /* Generic.Heading */
200
+ .highlight .gi { color: #4ec9b0 } /* Generic.Inserted */
201
+ .highlight .gp { color: #6a9955; font-weight: bold } /* Generic.Prompt */
202
+ .highlight .gs { font-weight: bold } /* Generic.Strong */
203
+ .highlight .gu { color: #d4d4d4; font-weight: bold } /* Generic.Subheading */
204
+ .highlight .kc { color: #569cd6 } /* Keyword.Constant */
205
+ .highlight .kd { color: #569cd6 } /* Keyword.Declaration */
206
+ .highlight .kn { color: #c586c0 } /* Keyword.Namespace */
207
+ .highlight .kp { color: #569cd6 } /* Keyword.Pseudo */
208
+ .highlight .kr { color: #569cd6 } /* Keyword.Reserved */
209
+ .highlight .kt { color: #4ec9b0 } /* Keyword.Type */
210
+ .highlight .ld { color: #ce9178 } /* Literal.Date */
211
+ .highlight .m { color: #b5cea8 } /* Literal.Number */
212
+ .highlight .s { color: #ce9178 } /* Literal.String */
213
+ .highlight .na { color: #9cdcfe } /* Name.Attribute */
214
+ .highlight .nb { color: #9cdcfe } /* Name.Builtin */
215
+ .highlight .nc { color: #4ec9b0 } /* Name.Class */
216
+ .highlight .no { color: #569cd6 } /* Name.Constant */
217
+ .highlight .nd { color: #c586c0 } /* Name.Decorator */
218
+ .highlight .ni { color: #d4d4d4 } /* Name.Entity */
219
+ .highlight .ne { color: #4ec9b0 } /* Name.Exception */
220
+ .highlight .nf { color: #dcdcaa } /* Name.Function */
221
+ .highlight .nl { color: #d4d4d4 } /* Name.Label */
222
+ .highlight .nn { color: #d4d4d4 } /* Name.Namespace */
223
+ .highlight .nx { color: #9cdcfe } /* Name.Other */
224
+ .highlight .py { color: #d4d4d4 } /* Name.Property */
225
+ .highlight .nt { color: #569cd6 } /* Name.Tag */
226
+ .highlight .nv { color: #9cdcfe } /* Name.Variable */
227
+ .highlight .ow { color: #c586c0 } /* Operator.Word */
228
+ .highlight .w { color: #d4d4d4 } /* Text.Whitespace */
229
+ .highlight .mf { color: #b5cea8 } /* Literal.Number.Float */
230
+ .highlight .mh { color: #b5cea8 } /* Literal.Number.Hex */
231
+ .highlight .mi { color: #b5cea8 } /* Literal.Number.Integer */
232
+ .highlight .mo { color: #b5cea8 } /* Literal.Number.Oct */
233
+ .highlight .sb { color: #ce9178 } /* Literal.String.Backtick */
234
+ .highlight .sc { color: #ce9178 } /* Literal.String.Char */
235
+ .highlight .sd { color: #6a9955 } /* Literal.String.Doc */
236
+ .highlight .s2 { color: #ce9178 } /* Literal.String.Double */
237
+ .highlight .se { color: #d7ba7d } /* Literal.String.Escape */
238
+ .highlight .sh { color: #ce9178 } /* Literal.String.Heredoc */
239
+ .highlight .si { color: #ce9178 } /* Literal.String.Interpol */
240
+ .highlight .sx { color: #ce9178 } /* Literal.String.Other */
241
+ .highlight .sr { color: #d16969 } /* Literal.String.Regex */
242
+ .highlight .s1 { color: #ce9178 } /* Literal.String.Single */
243
+ .highlight .ss { color: #ce9178 } /* Literal.String.Symbol */
244
+ .highlight .bp { color: #9cdcfe } /* Name.Builtin.Pseudo */
245
+ .highlight .vc { color: #9cdcfe } /* Name.Variable.Class */
246
+ .highlight .vg { color: #9cdcfe } /* Name.Variable.Global */
247
+ .highlight .vi { color: #9cdcfe } /* Name.Variable.Instance */
248
+ .highlight .il { color: #b5cea8 } /* Literal.Number.Integer.Long */
249
+
250
+ /* Language-specific adjustments */
251
+ .language-javascript .nx { color: #9cdcfe }
252
+ .language-javascript .s1,
253
+ .language-javascript .s2 { color: #ce9178 }
254
+ .language-javascript .kd { color: #569cd6 }
255
+ .language-javascript .k { color: #c586c0 }
256
+ .language-javascript .o { color: #d4d4d4 }
257
+ .language-javascript .p { color: #d4d4d4 }
258
+ .language-javascript .c1 { color: #6a9955 }
188
259
 
189
260
  .language-bash { color: #4ec9b0; }
261
+ .language-bash .nv { color: #9cdcfe; }
262
+ .language-bash .s2 { color: #ce9178; }
190
263
 
191
264
  ul, ol {
192
265
  margin-bottom: 16px;
package/docs/index.md CHANGED
@@ -50,6 +50,7 @@ JSON REST API is a lightweight, plugin-based framework that makes building REST
50
50
  <p>Follow industry standards with native JSON:API support. Compatible with any JSON:API client library.</p>
51
51
  </div>
52
52
 
53
+ <!--
53
54
  <div class="feature-card">
54
55
  <h3>🌐 Microservices Ready</h3>
55
56
  <p>Build distributed systems with native microservices support. Multiple transports, service discovery, and more.</p>
@@ -64,6 +65,7 @@ JSON REST API is a lightweight, plugin-based framework that makes building REST
64
65
  <h3>🔄 API Gateway</h3>
65
66
  <p>Transform into an API gateway to orchestrate external services with circuit breakers and saga support.</p>
66
67
  </div>
68
+ -->
67
69
  </div>
68
70
 
69
71
  ## Quick Example
@@ -137,15 +139,3 @@ npm install json-rest-api
137
139
  - [API Reference]({{ '/API' | relative_url }}) - Detailed API documentation
138
140
  - [Tutorial]({{ '/ONBOARDING' | relative_url }}) - Step-by-step walkthrough
139
141
  - [GitHub](https://github.com/mobily-enterprises/json-rest-api) - Source code and issues
140
-
141
- ### Advanced Topics
142
-
143
- - [API Gateway]({{ '/GUIDE_8_API_Gateway' | relative_url }}) - Orchestrate external services
144
- - [CLI Interface]({{ '/GUIDE_9_CLI_Interface' | relative_url }}) - Command-line interface for your API
145
-
146
- ### Enterprise Features
147
-
148
- - [Enterprise Guide]({{ '/enterprise/ENTERPRISE_GUIDE' | relative_url }}) - Complete guide for enterprise teams
149
- - [Microservices Architecture]({{ '/enterprise/GUIDE_8_Microservices' | relative_url }}) - Build distributed systems
150
- - [CQRS Pattern]({{ '/enterprise/GUIDE_9_CQRS' | relative_url }}) - Command Query Responsibility Segregation
151
- - [Domain-Driven Design]({{ '/enterprise/GUIDE_11_Domain_Driven_Design' | relative_url }}) - DDD patterns and implementation
@@ -0,0 +1,85 @@
1
+ # Helper Reorganization Plan
2
+
3
+ ## Files to Split and Move
4
+
5
+ ### 1. payload-validators.js
6
+ This file contains method-specific validators that should be split:
7
+
8
+ **Move to `querying/payload-validators-querying.js`:**
9
+ - `validateGetPayload` (used only by GET)
10
+ - `validateQueryPayload` (used only by QUERY)
11
+ - `validateIncludeDepth` (helper used by GET/QUERY validators)
12
+
13
+ **Move to `writing/payload-validators-writing.js`:**
14
+ - `validatePostPayload` (used only by POST)
15
+ - `validatePutPayload` (used only by PUT)
16
+ - `validatePatchPayload` (used only by PATCH)
17
+ - `validateResourceIdentifier` (helper used by writing validators)
18
+ - `validateRelationship` (helper used by writing validators)
19
+
20
+ ### 2. knex-field-helpers.js
21
+ This file has mixed functions:
22
+
23
+ **Move to `querying/knex-field-helpers-querying.js`:**
24
+ - `buildFieldSelection` (used only by GET/QUERY for sparse fieldsets)
25
+ - `getRequestedComputedFields` (used only by GET/QUERY)
26
+
27
+ **Keep in `querying-writing/knex-field-helpers.js`:**
28
+ - `isNonDatabaseField` (used by both reading and writing)
29
+ - `getForeignKeyFields` (re-exported, used by both)
30
+ - `filterHiddenFields` (re-exported, used by both)
31
+
32
+ ### 3. knex-json-api-transformers.js
33
+ This file has functions with different usage:
34
+
35
+ **Move to `querying/knex-json-api-transformers-querying.js`:**
36
+ - `toJsonApiRecord` (used only by QUERY)
37
+ - `buildJsonApiResponse` (used only by GET/QUERY)
38
+
39
+ **Move to `writing/knex-json-api-transformers-writing.js`:**
40
+ - `processBelongsToRelationships` (used only by PUT/PATCH)
41
+
42
+ **Keep in `querying-writing/knex-json-api-transformers.js`:**
43
+ - `toJsonApiRecordWithBelongsTo` (used by GET minimal and DELETE)
44
+
45
+ ### 4. simplified-helpers.js
46
+ Based on the analysis, this file likely contains:
47
+ - `transformSimplifiedToJsonApi` - used by writing methods
48
+ - `transformJsonApiToSimplified` - used by all methods (should stay shared)
49
+ - `transformSingleJsonApiToSimplified` - used by all methods (should stay shared)
50
+
51
+ Need to verify the actual usage of each function.
52
+
53
+ ## Summary of New Structure
54
+
55
+ ### `querying/` (10 files total)
56
+ - knex-cross-table-search.js ✓
57
+ - knex-pagination-helpers.js ✓
58
+ - knex-process-includes.js ✓
59
+ - knex-query-helpers.js ✓
60
+ - knex-relationship-includes.js ✓
61
+ - knex-window-queries.js ✓
62
+ - **payload-validators-querying.js** (NEW - split from payload-validators.js)
63
+ - **knex-field-helpers-querying.js** (NEW - split from knex-field-helpers.js)
64
+ - **knex-json-api-transformers-querying.js** (NEW - split from knex-json-api-transformers.js)
65
+
66
+ ### `writing/` (5 files total)
67
+ - many-to-many-manipulations.js ✓
68
+ - relationship-processor.js ✓
69
+ - **payload-validators-writing.js** (NEW - split from payload-validators.js)
70
+ - **knex-json-api-transformers-writing.js** (NEW - split from knex-json-api-transformers.js)
71
+ - **simplified-helpers-writing.js** (NEW - if transformSimplifiedToJsonApi is only used by writing)
72
+
73
+ ### `querying-writing/` (remaining shared files)
74
+ - compile-schemas.js ✓
75
+ - database-capabilities.js ✓
76
+ - database-value-normalizers.js ✓
77
+ - default-data-helpers.js ✓
78
+ - knex-field-helpers.js (reduced - only shared functions)
79
+ - knex-json-api-helpers.js ✓
80
+ - knex-json-api-transformers.js (reduced - only shared functions)
81
+ - schema-helpers.js ✓
82
+ - scope-validations.js ✓
83
+ - simplified-helpers.js (possibly reduced if some functions move to writing)
84
+
85
+ This reorganization will create a much more balanced structure with clearer separation of concerns.
@@ -0,0 +1,94 @@
1
+ # REST API Helper Usage Analysis
2
+
3
+ This document analyzes which helpers from `plugins/core/lib/` are used by each REST API method (get, query, post, put, patch, delete).
4
+
5
+ ## Helper Categorization
6
+
7
+ ### 1. Helpers Used ONLY by Querying Methods (GET, QUERY)
8
+
9
+ #### From rest-api-plugin.js:
10
+ - **parseJsonApiQuery** - Parses JSON:API query strings into query parameters
11
+ - **getRequestedComputedFields** - Determines which computed fields are requested based on sparse fieldsets
12
+
13
+ #### From rest-api-knex-plugin.js:
14
+ - **buildFieldSelection** - Builds field selection for sparse fieldsets and tracks computed field dependencies
15
+ - **buildQuerySelection** - Applies field selection to Knex query
16
+ - **loadRelationshipIdentifiers** - Loads hasMany relationship identifiers for included resources
17
+ - **processIncludes** - Processes relationship includes based on query parameters
18
+ - **toJsonApiRecord** - Transforms database records to JSON:API format
19
+ - **buildJsonApiResponse** - Builds complete JSON:API response with data and included resources
20
+ - **polymorphicFiltersHook** - Handles filtering for polymorphic relationships
21
+ - **crossTableFiltersHook** - Handles cross-table filtering with JOINs
22
+ - **basicFiltersHook** - Handles basic table filtering
23
+ - **calculatePaginationMeta** - Calculates pagination metadata
24
+ - **generatePaginationLinks** - Generates pagination links for offset-based pagination
25
+ - **generateCursorPaginationLinks** - Generates pagination links for cursor-based pagination
26
+ - **buildCursorMeta** - Builds cursor pagination metadata
27
+ - **parseCursor** - Parses cursor strings for cursor pagination
28
+
29
+ ### 2. Helpers Used ONLY by Writing Methods (POST, PUT, PATCH, DELETE)
30
+
31
+ #### From rest-api-plugin.js:
32
+ - **validatePostPayload** - Validates POST request payload
33
+ - **validatePutPayload** - Validates PUT request payload
34
+ - **validatePatchPayload** - Validates PATCH request payload
35
+ - **processRelationships** - Extracts foreign keys from JSON:API relationships
36
+ - **updateManyToManyRelationship** - Updates many-to-many relationships intelligently
37
+ - **createPivotRecords** - Creates pivot table records for many-to-many relationships
38
+ - **transformSimplifiedToJsonApi** - Transforms simplified API format to JSON:API
39
+
40
+ #### From rest-api-knex-plugin.js:
41
+ - **processBelongsToRelationships** - Processes belongsTo relationships to extract foreign keys
42
+ - **stripNonDatabaseFields** - Removes computed and virtual fields before database operations
43
+
44
+ ### 3. Helpers Used by BOTH Querying and Writing Methods
45
+
46
+ #### From rest-api-plugin.js:
47
+ - **validateQueryPayload** - Used by QUERY method
48
+ - **validateGetPayload** - Used by GET method
49
+ - **compileSchemas** - Used during scope initialization (affects all methods)
50
+ - **normalizeRecordAttributes** - Normalizes database values (used by GET and QUERY)
51
+ - **transformJsonApiToSimplified** - Transforms JSON:API to simplified format (used by all methods when simplified mode is enabled)
52
+ - **filterHiddenFields** - Filters hidden fields from responses (used by all methods)
53
+ - **createDefaultDataHelpers** - Creates default helper implementations
54
+
55
+ #### From rest-api-knex-plugin.js:
56
+ - **toJsonApiRecordWithBelongsTo** - Used by GET (minimal record) and data fetching operations
57
+ - **getForeignKeyFields** - While imported, not directly used in the analyzed code
58
+ - **isNonDatabaseField** - While imported, not directly used in the analyzed code
59
+
60
+ ## Summary by Method
61
+
62
+ ### GET Method
63
+ **Uses:** validateGetPayload, getRequestedComputedFields, normalizeRecordAttributes, filterHiddenFields, transformJsonApiToSimplified, buildFieldSelection, buildQuerySelection, loadRelationshipIdentifiers, processIncludes, buildJsonApiResponse, toJsonApiRecordWithBelongsTo
64
+
65
+ ### QUERY Method
66
+ **Uses:** validateQueryPayload, getRequestedComputedFields, normalizeRecordAttributes, filterHiddenFields, transformJsonApiToSimplified, parseJsonApiQuery, buildFieldSelection, buildQuerySelection, polymorphicFiltersHook, crossTableFiltersHook, basicFiltersHook, calculatePaginationMeta, generatePaginationLinks, generateCursorPaginationLinks, buildCursorMeta, parseCursor, loadRelationshipIdentifiers, processIncludes, buildJsonApiResponse
67
+
68
+ ### POST Method
69
+ **Uses:** validatePostPayload, processRelationships, createPivotRecords, transformSimplifiedToJsonApi, filterHiddenFields, transformJsonApiToSimplified, stripNonDatabaseFields
70
+
71
+ ### PUT Method
72
+ **Uses:** validatePutPayload, processRelationships, updateManyToManyRelationship, createPivotRecords, transformSimplifiedToJsonApi, filterHiddenFields, transformJsonApiToSimplified, processBelongsToRelationships, stripNonDatabaseFields
73
+
74
+ ### PATCH Method
75
+ **Uses:** validatePatchPayload, processRelationships, updateManyToManyRelationship, transformSimplifiedToJsonApi, filterHiddenFields, transformJsonApiToSimplified, processBelongsToRelationships, stripNonDatabaseFields
76
+
77
+ ### DELETE Method
78
+ **Uses:** toJsonApiRecordWithBelongsTo (for minimal record fetching)
79
+
80
+ ## Key Observations
81
+
82
+ 1. **Clear Separation**: There's a clear separation between read and write helpers, with minimal overlap.
83
+
84
+ 2. **Query Complexity**: Query methods use the most helpers due to filtering, pagination, includes, and sparse fieldsets.
85
+
86
+ 3. **Relationship Handling**: Write methods focus heavily on relationship processing and validation.
87
+
88
+ 4. **Format Transformation**: Both read and write methods use format transformation helpers for simplified API mode.
89
+
90
+ 5. **DELETE Simplicity**: DELETE method uses the fewest helpers, only needing minimal record fetching.
91
+
92
+ 6. **Validation Pattern**: Each write method has its own specific payload validator.
93
+
94
+ 7. **Database Abstraction**: The knex plugin handles all direct database operations, while the REST API plugin handles validation and transformation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-rest-api",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,8 +22,9 @@
22
22
  "homepage": "https://github.com/mobily-enterprises/jsonrestapi#readme",
23
23
  "description": "REST API plugin for hooked-api with JSON:API compliance",
24
24
  "dependencies": {
25
- "hooked-api": "^1.0.8",
26
- "json-rest-schema": "^1.0.6"
25
+ "hooked-api": "^1.0.14",
26
+ "json-rest-schema": "^1.0.8",
27
+ "semver": "^7.7.2"
27
28
  },
28
29
  "peerDependencies": {
29
30
  "@socket.io/redis-adapter": "^8.3.0",
@@ -79,7 +80,7 @@
79
80
  },
80
81
  "devDependencies": {
81
82
  "@socket.io/redis-adapter": "^8.3.0",
82
- "better-sqlite3": "^11.0.0",
83
+ "better-sqlite3": "^11.10.0",
83
84
  "express": "^5.1.0",
84
85
  "fractional-indexing": "^3.2.0",
85
86
  "jsonwebtoken": "^9.0.2",
@@ -348,8 +348,8 @@ export const BulkOperationsPlugin = {
348
348
 
349
349
  // Hook into scope creation to add bulk routes
350
350
  addHook('afterAddScope', 'bulkOperationsRoutes', {}, async ({ scopeName }) => {
351
- const resourceUrlPrefix = api.vars.resourceUrlPrefix || '/api';
352
- const scopePath = `${resourceUrlPrefix}/${scopeName}`;
351
+ const urlPrefix = api.vars.transport?.mountPath || '';
352
+ const scopePath = `${urlPrefix}/${scopeName}`;
353
353
 
354
354
  // Create route handlers
355
355
  const createBulkRouteHandler = (method) => {