@jskit-ai/crud-core 0.1.144 → 0.1.145

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.
@@ -1,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/crud-core",
4
- version: "0.1.144",
4
+ version: "0.1.145",
5
5
  kind: "runtime",
6
6
  description: "Shared CRUD helpers used by CRUD modules.",
7
7
  dependsOn: [
@@ -28,7 +28,7 @@ export default Object.freeze({
28
28
  mutations: {
29
29
  dependencies: {
30
30
  runtime: {
31
- "@jskit-ai/crud-core": "0.1.144"
31
+ "@jskit-ai/crud-core": "0.1.145"
32
32
  },
33
33
  dev: {}
34
34
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/crud-core",
3
- "version": "0.1.144",
3
+ "version": "0.1.145",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -27,15 +27,15 @@
27
27
  "./server/routeContracts": "./src/server/routeContracts.js"
28
28
  },
29
29
  "dependencies": {
30
- "@jskit-ai/database-runtime": "0.1.134",
31
- "@jskit-ai/http-runtime": "0.1.133",
32
- "@jskit-ai/kernel": "0.1.135",
30
+ "@jskit-ai/database-runtime": "0.1.135",
31
+ "@jskit-ai/http-runtime": "0.1.134",
32
+ "@jskit-ai/kernel": "0.1.136",
33
33
  "json-rest-schema": "1.x.x",
34
- "@jskit-ai/realtime": "0.1.132",
35
- "@jskit-ai/resource-crud-core": "0.1.78",
36
- "@jskit-ai/shell-web": "0.1.136",
37
- "@jskit-ai/users-core": "0.1.146",
38
- "@jskit-ai/users-web": "0.1.152"
34
+ "@jskit-ai/realtime": "0.1.133",
35
+ "@jskit-ai/resource-crud-core": "0.1.79",
36
+ "@jskit-ai/shell-web": "0.1.137",
37
+ "@jskit-ai/users-core": "0.1.148",
38
+ "@jskit-ai/users-web": "0.1.153"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@tanstack/vue-query": "^5.90.5",
@@ -25,6 +25,23 @@ const lookupIncludeQueryValidator = Object.freeze({
25
25
  mode: "patch"
26
26
  });
27
27
 
28
+ const jsonApiFieldsetsQueryValidator = Object.freeze({
29
+ schema: createSchema({
30
+ fields: {
31
+ type: "object",
32
+ required: false,
33
+ values: {
34
+ type: "array",
35
+ items: {
36
+ type: "string",
37
+ minLength: 1
38
+ }
39
+ }
40
+ }
41
+ }),
42
+ mode: "patch"
43
+ });
44
+
28
45
  function resolveCrudListUsesOrderedCursor(list = {}) {
29
46
  const entries = Array.isArray(list?.orderBy)
30
47
  ? list.orderBy
@@ -92,6 +109,7 @@ export {
92
109
  createCrudCursorPaginationQueryValidator,
93
110
  listSearchQueryValidator,
94
111
  lookupIncludeQueryValidator,
112
+ jsonApiFieldsetsQueryValidator,
95
113
  resolveCrudParentFilterKeys,
96
114
  createCrudParentFilterQueryValidator
97
115
  };
@@ -11,6 +11,7 @@ import {
11
11
  createCrudCursorPaginationQueryValidator,
12
12
  listSearchQueryValidator as defaultListSearchQueryValidator,
13
13
  lookupIncludeQueryValidator as defaultLookupIncludeQueryValidator,
14
+ jsonApiFieldsetsQueryValidator,
14
15
  createCrudParentFilterQueryValidator
15
16
  } from "./listQueryValidators.js";
16
17
 
@@ -454,7 +455,12 @@ function createCrudJsonApiRouteContracts({
454
455
  listSearchQueryValidator,
455
456
  listParentFilterQueryValidator,
456
457
  ...(resolvedListFilterQueryValidator ? [resolvedListFilterQueryValidator] : []),
457
- lookupIncludeQueryValidator
458
+ lookupIncludeQueryValidator,
459
+ jsonApiFieldsetsQueryValidator
460
+ ]);
461
+ const viewRouteQueryValidator = composeSchemaDefinitions([
462
+ lookupIncludeQueryValidator,
463
+ jsonApiFieldsetsQueryValidator
458
464
  ]);
459
465
  const recordRouteParamsValidator = routeParamsValidator
460
466
  ? composeSchemaDefinitions([
@@ -511,19 +517,23 @@ function createCrudJsonApiRouteContracts({
511
517
  query: listRouteQueryValidator,
512
518
  output: viewOutput,
513
519
  outputKind: "collection",
520
+ includeValidation400: true,
514
521
  outputAttributeExcludeKeys,
515
522
  outputRelationshipEntries: viewOutputRelationships,
523
+ allowSparseFields: true,
516
524
  getRecordAttributes: viewRecordAttributes,
517
525
  getRecordRelationships: viewRecordRelationships,
518
526
  getIncluded: viewIncluded
519
527
  }),
520
528
  viewRouteContract: createJsonApiResourceRouteContract({
521
529
  type: routeType,
522
- query: lookupIncludeQueryValidator,
530
+ query: viewRouteQueryValidator,
523
531
  output: viewOutput,
524
532
  outputKind: "record",
533
+ includeValidation400: true,
525
534
  outputAttributeExcludeKeys,
526
535
  outputRelationshipEntries: viewOutputRelationships,
536
+ allowSparseFields: true,
527
537
  getRecordAttributes: viewRecordAttributes,
528
538
  getRecordRelationships: viewRecordRelationships,
529
539
  getIncluded: viewIncluded
@@ -177,7 +177,11 @@ test("createCrudJsonApiRouteContracts builds default CRUD JSON:API contracts", a
177
177
  include: " ownerId ",
178
178
  contactId: " 42 ",
179
179
  cursor: " offset:2 ",
180
- limit: "25"
180
+ limit: "25",
181
+ fields: {
182
+ contacts: ["id", "name"],
183
+ userProfiles: ["id", "name"]
184
+ }
181
185
  }, { phase: "input" });
182
186
 
183
187
  assert.deepEqual(normalizedListQuery, {
@@ -185,9 +189,39 @@ test("createCrudJsonApiRouteContracts builds default CRUD JSON:API contracts", a
185
189
  include: "ownerId",
186
190
  contactId: "42",
187
191
  cursor: "offset:2",
188
- limit: 25
192
+ limit: 25,
193
+ fields: {
194
+ contacts: ["id", "name"],
195
+ userProfiles: ["id", "name"]
196
+ }
189
197
  });
190
198
 
199
+ assert.deepEqual(
200
+ await validateSchemaPayload(contracts.viewRouteContract.query, {
201
+ include: "owner",
202
+ fields: {
203
+ contacts: ["id", "name"],
204
+ userProfiles: ["id", "name"]
205
+ }
206
+ }, { phase: "input" }),
207
+ {
208
+ include: "owner",
209
+ fields: {
210
+ contacts: ["id", "name"],
211
+ userProfiles: ["id", "name"]
212
+ }
213
+ }
214
+ );
215
+
216
+ const sparseResourceSchema =
217
+ contracts.listRouteContract.responses[200].transportSchema.definitions.contactsSuccessResource;
218
+ const sparseAttributesSchemaName = sparseResourceSchema.properties.attributes.allOf[0].$ref
219
+ .replace("#/definitions/", "");
220
+ const sparseAttributesSchema =
221
+ contracts.listRouteContract.responses[200].transportSchema.definitions[sparseAttributesSchemaName];
222
+ assert.deepEqual(sparseResourceSchema.required, ["type", "id"]);
223
+ assert.equal(Object.hasOwn(sparseAttributesSchema, "required"), false);
224
+
191
225
  const decodedCreateBody = contracts.createRouteContract.transport.request.body({
192
226
  data: {
193
227
  type: "contacts",