@platecms/delta-client 1.6.0 → 1.7.0

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/README.md CHANGED
@@ -44,7 +44,7 @@ const articleSchema = schema.buildingBlock({
44
44
  // Array of items
45
45
  tags: schema.array(schema.tag()),
46
46
  // For related content items
47
- author: schema.contentItem({
47
+ author: schema.relatedContentItem({
48
48
  name: schema.string(),
49
49
  email: schema.string(),
50
50
  }),
@@ -85,14 +85,20 @@ const article = articleSchema.parse(buildingBlockFieldFulfillments);
85
85
 
86
86
  #### Available Types
87
87
 
88
+ Root schemas
89
+
90
+ - **`schema.contentItem()`** - Content items structures
91
+ - **`schema.buildingBlock()`** - Building block structures
92
+
93
+ Chainable or seperate schemas from the root schemas
94
+
88
95
  - **`schema.string()`** - String values
89
96
  - **`schema.number()`** - Numeric values
90
97
  - **`schema.boolean()`** - Boolean values
91
98
  - **`schema.date()`** - Date values
92
99
  - **`schema.asset()`** - Asset references
93
100
  - **`schema.smartText()`** - Rich text content
94
- - **`schema.contentItem()`** - Related content items
95
- - **`schema.buildingBlock()`** - Building block structures
101
+ - **`schema.relatedContentItem()`** - Related content items
96
102
  - **`schema.array()`** - Arrays of any schema
97
103
  - **`schema.gridPlacement()`** - Grid layout placements
98
104
  - **`schema.contentType()`** - Content type references
@@ -118,11 +124,11 @@ const tagsSchema = schema.array(
118
124
 
119
125
  // Nested structures
120
126
  const pageSchema = schema.buildingBlock({
121
- hero: schema.contentItem({
127
+ hero: schema.relatedContentItem({
122
128
  title: schema.string(),
123
129
  image: schema.asset(),
124
130
  }),
125
- sections: schema.array(schema.contentItem({
131
+ sections: schema.array(schema.relatedContentItem({
126
132
  type: schema.string(),
127
133
  content: schema.smartText(),
128
134
  })),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platecms/delta-client",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Utilities and functions to interact with the Delta CMS.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
@@ -18,7 +18,7 @@
18
18
  "src/**/*"
19
19
  ],
20
20
  "peerDependencies": {
21
- "@platecms/delta-cast": "1.6.0",
21
+ "@platecms/delta-cast": "1.7.0",
22
22
  "@graphql-typed-document-node/core": "3.2.0",
23
23
  "graphql": "16.11.0",
24
24
  "tslib": "2.8.1",
@@ -145,10 +145,10 @@ describe("Schema", () => {
145
145
  title: [schema.number(), schema.string()],
146
146
  description: schema.smartText(),
147
147
  vegatables: schema.array(
148
- schema.contentItem({
148
+ schema.relatedContentItem({
149
149
  name: [schema.string(), schema.number()],
150
150
  calories: schema.number(),
151
- author: schema.contentItem({
151
+ author: schema.relatedContentItem({
152
152
  name: schema.string(),
153
153
  email: schema.string(),
154
154
  }),
@@ -217,4 +217,52 @@ describe("Schema", () => {
217
217
  },
218
218
  });
219
219
  });
220
+
221
+ it("should parse a content item and its related content item with its values", () => {
222
+ const book: ContentItem = {
223
+ contentValues: [
224
+ {
225
+ contentField: {
226
+ name: "name",
227
+ slug: "name",
228
+ },
229
+ primitiveValue: "The Great Gatsby",
230
+ },
231
+ {
232
+ contentField: {
233
+ name: "year",
234
+ slug: "year",
235
+ },
236
+ primitiveValue: 1925,
237
+ },
238
+ {
239
+ contentField: {
240
+ name: "author",
241
+ slug: "author",
242
+ },
243
+ relatedContentItem: johnDoe,
244
+ },
245
+ ],
246
+ } as unknown as ContentItem;
247
+
248
+ const contentItem = schema.contentItem({
249
+ name: schema.string(),
250
+ year: schema.number(),
251
+ author: schema.relatedContentItem({
252
+ name: schema.string(),
253
+ email: schema.string(),
254
+ }),
255
+ });
256
+
257
+ const result = contentItem.parse(book);
258
+
259
+ expect(result).toEqual({
260
+ name: "The Great Gatsby",
261
+ year: 1925,
262
+ author: {
263
+ name: "John Doe",
264
+ email: "john.doe@example.com",
265
+ },
266
+ });
267
+ });
220
268
  });
@@ -96,7 +96,7 @@ describe("Array schema", () => {
96
96
 
97
97
  it("should parse an array of content values", () => {
98
98
  const testSchema = schemaBuilder.array(
99
- schemaBuilder.contentItem({
99
+ schemaBuilder.relatedContentItem({
100
100
  name: schemaBuilder.string(),
101
101
  }),
102
102
  );
@@ -19,16 +19,14 @@ describe("ContentItem schema", () => {
19
19
  });
20
20
 
21
21
  const result = contentItemSchema.parse({
22
- relatedContentItem: {
23
- contentValues: [
24
- {
25
- contentField: {
26
- slug: "title",
27
- },
28
- primitiveValue: "hello",
22
+ contentValues: [
23
+ {
24
+ contentField: {
25
+ slug: "title",
29
26
  },
30
- ],
31
- },
27
+ primitiveValue: "hello",
28
+ },
29
+ ],
32
30
  });
33
31
 
34
32
  expect(result).toEqual({
@@ -42,16 +40,14 @@ describe("ContentItem schema", () => {
42
40
  });
43
41
 
44
42
  const result = contentItemSchema.parse({
45
- relatedContentItem: {
46
- contentValues: [
47
- {
48
- contentField: {
49
- slug: "title",
50
- },
51
- primitiveValue: "hello",
43
+ contentValues: [
44
+ {
45
+ contentField: {
46
+ slug: "title",
52
47
  },
53
- ],
54
- },
48
+ primitiveValue: "hello",
49
+ },
50
+ ],
55
51
  });
56
52
 
57
53
  expect(result).toEqual({
@@ -1,5 +1,5 @@
1
1
  import { ObjectSchema, Schema, SchemaConfig } from ".";
2
- import { isContentValue } from "../utils/isContentValue";
2
+ import { isContentItem } from "../utils/isContentValue";
3
3
  import { isArray } from "../utils";
4
4
  export class ContentItemSchema<T extends Record<string, Schema | Schema[]>>
5
5
  implements Schema<ObjectSchema<T>, unknown>
@@ -22,10 +22,10 @@ export class ContentItemSchema<T extends Record<string, Schema | Schema[]>>
22
22
 
23
23
  return Object.entries(this.structure).reduce(
24
24
  (acc, [key, value]) => {
25
- const relatedContentItem = isContentValue(data) ? data.relatedContentItem : null;
25
+ const contentItem = isContentItem(data) ? data : null;
26
26
 
27
27
  const contentValuesForKey =
28
- relatedContentItem?.contentValues.filter((contentValue) => contentValue.contentField?.slug === key) ?? [];
28
+ contentItem?.contentValues.filter((contentValue) => contentValue.contentField?.slug === key) ?? [];
29
29
  const shapes = Array.isArray(value) ? value : [value];
30
30
  const parsedValues = shapes.map((shape) => shape.parse(contentValuesForKey, config));
31
31
 
@@ -13,6 +13,7 @@ import { TagSchema } from "./tag";
13
13
  import { ContentTypeSchema } from "./contentType";
14
14
  import { Asset, ContentType, GridPlacement, PathPart, Tag } from "../../../__generated__/graphql";
15
15
  import { Root } from "@platecms/delta-cast";
16
+ import { RelatedContentItemSchema } from "./relatedContentItem";
16
17
 
17
18
  export type ResultType =
18
19
  | Asset
@@ -47,6 +48,8 @@ export interface SchemaConfig {
47
48
  export const schema = {
48
49
  buildingBlock: <T extends Record<string, Schema | Schema[]>>(structure: T): BuildingBlockSchema<T> =>
49
50
  new BuildingBlockSchema(structure),
51
+ relatedContentItem: <T extends Record<string, Schema | Schema[]>>(structure: T): RelatedContentItemSchema<T> =>
52
+ new RelatedContentItemSchema(structure),
50
53
  contentItem: <T extends Record<string, Schema | Schema[]>>(structure: T): ContentItemSchema<T> =>
51
54
  new ContentItemSchema(structure),
52
55
  array: <T extends Schema | Schema[]>(structure: T): ArraySchema<T> => new ArraySchema(structure),
@@ -0,0 +1,61 @@
1
+ import { describe, it } from "vitest";
2
+ import { schema } from ".";
3
+ import { RelatedContentItemSchema } from "./relatedContentItem";
4
+
5
+ describe("RelatedContentItem schema", () => {
6
+ it("should parse an empty content item", () => {
7
+ const relatedContentItemSchema = new RelatedContentItemSchema({});
8
+
9
+ const result = relatedContentItemSchema.parse({
10
+ contentValues: [],
11
+ });
12
+
13
+ expect(result).toEqual({});
14
+ });
15
+
16
+ it("should parse a content item with its values", () => {
17
+ const relatedContentItemSchema = new RelatedContentItemSchema({
18
+ title: schema.string(),
19
+ });
20
+
21
+ const result = relatedContentItemSchema.parse({
22
+ relatedContentItem: {
23
+ contentValues: [
24
+ {
25
+ contentField: {
26
+ slug: "title",
27
+ },
28
+ primitiveValue: "hello",
29
+ },
30
+ ],
31
+ },
32
+ });
33
+
34
+ expect(result).toEqual({
35
+ title: "hello",
36
+ });
37
+ });
38
+
39
+ it("should parse a content item with multiple values", () => {
40
+ const relatedContentItemSchema = new RelatedContentItemSchema({
41
+ title: [schema.number(), schema.string()],
42
+ });
43
+
44
+ const result = relatedContentItemSchema.parse({
45
+ relatedContentItem: {
46
+ contentValues: [
47
+ {
48
+ contentField: {
49
+ slug: "title",
50
+ },
51
+ primitiveValue: "hello",
52
+ },
53
+ ],
54
+ },
55
+ });
56
+
57
+ expect(result).toEqual({
58
+ title: "hello",
59
+ });
60
+ });
61
+ });
@@ -0,0 +1,39 @@
1
+ import { ObjectSchema, Schema, SchemaConfig } from ".";
2
+ import { isContentValue } from "../utils/isContentValue";
3
+ import { isArray } from "../utils";
4
+ export class RelatedContentItemSchema<T extends Record<string, Schema | Schema[]>>
5
+ implements Schema<ObjectSchema<T>, unknown>
6
+ {
7
+ public constructor(private readonly structure: T) {}
8
+
9
+ public parse(
10
+ data: unknown,
11
+ config?: SchemaConfig,
12
+ ): {
13
+ [key in keyof T]: T[key] extends Schema[]
14
+ ? ReturnType<T[key][number]["parse"]>
15
+ : T[key] extends Schema
16
+ ? ReturnType<T[key]["parse"]>
17
+ : never;
18
+ } {
19
+ if (isArray(data)) {
20
+ data = data[0];
21
+ }
22
+
23
+ return Object.entries(this.structure).reduce(
24
+ (acc, [key, value]) => {
25
+ const relatedContentItem = isContentValue(data) ? data.relatedContentItem : null;
26
+
27
+ const contentValuesForKey =
28
+ relatedContentItem?.contentValues.filter((contentValue) => contentValue.contentField?.slug === key) ?? [];
29
+ const shapes = Array.isArray(value) ? value : [value];
30
+ const parsedValues = shapes.map((shape) => shape.parse(contentValuesForKey, config));
31
+
32
+ acc[key as keyof T] = (parsedValues.find((parsedValue) => parsedValue !== null) ??
33
+ null) as ObjectSchema<T>[keyof T];
34
+ return acc;
35
+ },
36
+ {} as unknown as ObjectSchema<T>,
37
+ );
38
+ }
39
+ }
@@ -1,4 +1,4 @@
1
- import { ContentValue } from "../../../__generated__/graphql";
1
+ import { ContentItem, ContentValue } from "../../../__generated__/graphql";
2
2
 
3
3
  export function isContentValue(data: unknown): data is ContentValue {
4
4
  return (
@@ -15,3 +15,7 @@ export function isContentValue(data: unknown): data is ContentValue {
15
15
  "interpolatedSmartText" in data)
16
16
  );
17
17
  }
18
+
19
+ export function isContentItem(data: unknown): data is ContentItem {
20
+ return data !== null && typeof data === "object" && "contentValues" in data;
21
+ }